1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/formats/mp4/hevc.h"
10 #include "base/logging.h"
11 #include "media/base/decrypt_config.h"
12 #include "media/filters/h265_parser.h"
13 #include "media/formats/mp4/avc.h"
14 #include "media/formats/mp4/box_definitions.h"
15 #include "media/formats/mp4/box_reader.h"
20 HEVCDecoderConfigurationRecord::HEVCDecoderConfigurationRecord()
21 : configurationVersion(0),
22 general_profile_space(0),
24 general_profile_idc(0),
25 general_profile_compatibility_flags(0),
26 general_constraint_indicator_flags(0),
28 min_spatial_segmentation_idc(0),
31 bitDepthLumaMinus8(0),
32 bitDepthChromaMinus8(0),
37 lengthSizeMinusOne(0),
40 HEVCDecoderConfigurationRecord::~HEVCDecoderConfigurationRecord() {}
41 FourCC
HEVCDecoderConfigurationRecord::BoxType() const { return FOURCC_HVCC
; }
43 bool HEVCDecoderConfigurationRecord::Parse(BoxReader
* reader
) {
44 return ParseInternal(reader
, reader
->media_log());
47 bool HEVCDecoderConfigurationRecord::Parse(const uint8
* data
, int data_size
) {
48 BufferReader
reader(data
, data_size
);
49 return ParseInternal(&reader
, new MediaLog());
52 HEVCDecoderConfigurationRecord::HVCCNALArray::HVCCNALArray()
55 HEVCDecoderConfigurationRecord::HVCCNALArray::~HVCCNALArray() {}
57 bool HEVCDecoderConfigurationRecord::ParseInternal(
59 const scoped_refptr
<MediaLog
>& media_log
) {
60 uint8 profile_indication
= 0;
61 uint32 general_constraint_indicator_flags_hi
= 0;
62 uint16 general_constraint_indicator_flags_lo
= 0;
64 RCHECK(reader
->Read1(&configurationVersion
) && configurationVersion
== 1 &&
65 reader
->Read1(&profile_indication
) &&
66 reader
->Read4(&general_profile_compatibility_flags
) &&
67 reader
->Read4(&general_constraint_indicator_flags_hi
) &&
68 reader
->Read2(&general_constraint_indicator_flags_lo
) &&
69 reader
->Read1(&general_level_idc
) &&
70 reader
->Read2(&min_spatial_segmentation_idc
) &&
71 reader
->Read1(¶llelismType
) &&
72 reader
->Read1(&chromaFormat
) &&
73 reader
->Read1(&bitDepthLumaMinus8
) &&
74 reader
->Read1(&bitDepthChromaMinus8
) &&
75 reader
->Read2(&avgFrameRate
) &&
76 reader
->Read1(&misc
) &&
77 reader
->Read1(&numOfArrays
));
79 general_profile_space
= profile_indication
>> 6;
80 general_tier_flag
= (profile_indication
>> 5) & 1;
81 general_profile_idc
= profile_indication
& 0x1f;
83 general_constraint_indicator_flags
= general_constraint_indicator_flags_hi
;
84 general_constraint_indicator_flags
<<= 16;
85 general_constraint_indicator_flags
|= general_constraint_indicator_flags_lo
;
87 min_spatial_segmentation_idc
&= 0xfff;
90 bitDepthLumaMinus8
&= 7;
91 bitDepthChromaMinus8
&= 7;
93 constantFrameRate
= misc
>> 6;
94 numTemporalLayers
= (misc
>> 3) & 7;
95 temporalIdNested
= (misc
>> 2) & 1;
96 lengthSizeMinusOne
= misc
& 3;
98 DVLOG(2) << __FUNCTION__
<< " numOfArrays=" << (int)numOfArrays
;
99 arrays
.resize(numOfArrays
);
100 for (uint32 j
= 0; j
< numOfArrays
; j
++) {
101 RCHECK(reader
->Read1(&arrays
[j
].first_byte
));
103 RCHECK(reader
->Read2(&numNalus
));
104 arrays
[j
].units
.resize(numNalus
);
105 for (uint32 i
= 0; i
< numNalus
; ++i
) {
106 uint16 naluLength
= 0;
107 RCHECK(reader
->Read2(&naluLength
) &&
108 reader
->ReadVec(&arrays
[j
].units
[i
], naluLength
));
109 DVLOG(4) << __FUNCTION__
<< " naluType="
110 << (int)(arrays
[j
].first_byte
& 0x3f)
111 << " size=" << arrays
[j
].units
[i
].size();
115 if (media_log
.get()) {
116 MEDIA_LOG(INFO
, media_log
) << "Video codec: hevc";
122 static const uint8 kAnnexBStartCode
[] = {0, 0, 0, 1};
123 static const int kAnnexBStartCodeSize
= 4;
125 bool HEVC::InsertParamSetsAnnexB(
126 const HEVCDecoderConfigurationRecord
& hevc_config
,
127 std::vector
<uint8
>* buffer
,
128 std::vector
<SubsampleEntry
>* subsamples
) {
129 DCHECK(HEVC::IsValidAnnexB(*buffer
, *subsamples
));
131 scoped_ptr
<H265Parser
> parser(new H265Parser());
132 const uint8
* start
= &(*buffer
)[0];
133 parser
->SetEncryptedStream(start
, buffer
->size(), *subsamples
);
136 if (parser
->AdvanceToNextNALU(&nalu
) != H265Parser::kOk
)
139 std::vector
<uint8
>::iterator config_insert_point
= buffer
->begin();
141 if (nalu
.nal_unit_type
== H265NALU::AUD_NUT
) {
142 // Move insert point to just after the AUD.
143 config_insert_point
+= (nalu
.data
+ nalu
.size
) - start
;
146 // Clear |parser| and |start| since they aren't needed anymore and
147 // will hold stale pointers once the insert happens.
151 std::vector
<uint8
> param_sets
;
152 RCHECK(HEVC::ConvertConfigToAnnexB(hevc_config
, ¶m_sets
));
153 DVLOG(4) << __FUNCTION__
<< " converted hvcC to AnnexB "
154 << " size=" << param_sets
.size() << " inserted at "
155 << (int)(config_insert_point
- buffer
->begin());
157 if (subsamples
&& !subsamples
->empty()) {
158 int subsample_index
= AVC::FindSubsampleIndex(*buffer
, subsamples
,
159 &(*config_insert_point
));
160 // Update the size of the subsample where SPS/PPS is to be inserted.
161 (*subsamples
)[subsample_index
].clear_bytes
+= param_sets
.size();
164 buffer
->insert(config_insert_point
,
165 param_sets
.begin(), param_sets
.end());
167 DCHECK(HEVC::IsValidAnnexB(*buffer
, *subsamples
));
171 bool HEVC::ConvertConfigToAnnexB(
172 const HEVCDecoderConfigurationRecord
& hevc_config
,
173 std::vector
<uint8
>* buffer
) {
174 DCHECK(buffer
->empty());
177 for (size_t j
= 0; j
< hevc_config
.arrays
.size(); j
++) {
178 uint8 naluType
= hevc_config
.arrays
[j
].first_byte
& 0x3f;
179 for (size_t i
= 0; i
< hevc_config
.arrays
[j
].units
.size(); ++i
) {
180 DVLOG(3) << __FUNCTION__
<< " naluType=" << (int)naluType
181 << " size=" << hevc_config
.arrays
[j
].units
[i
].size();
182 buffer
->insert(buffer
->end(), kAnnexBStartCode
,
183 kAnnexBStartCode
+ kAnnexBStartCodeSize
);
184 buffer
->insert(buffer
->end(), hevc_config
.arrays
[j
].units
[i
].begin(),
185 hevc_config
.arrays
[j
].units
[i
].end());
192 // Verifies AnnexB NALU order according to section 7.4.2.4.4 of ISO/IEC 23008-2.
193 bool HEVC::IsValidAnnexB(const std::vector
<uint8
>& buffer
,
194 const std::vector
<SubsampleEntry
>& subsamples
) {
195 return IsValidAnnexB(&buffer
[0], buffer
.size(), subsamples
);
198 bool HEVC::IsValidAnnexB(const uint8
* buffer
, size_t size
,
199 const std::vector
<SubsampleEntry
>& subsamples
) {
205 // TODO(servolk): Implement this, see crbug.com/527595
209 HEVCBitstreamConverter::HEVCBitstreamConverter(
210 scoped_ptr
<HEVCDecoderConfigurationRecord
> hevc_config
)
211 : hevc_config_(hevc_config
.Pass()) {
212 DCHECK(hevc_config_
);
215 HEVCBitstreamConverter::~HEVCBitstreamConverter() {
218 bool HEVCBitstreamConverter::ConvertFrame(
219 std::vector
<uint8
>* frame_buf
,
221 std::vector
<SubsampleEntry
>* subsamples
) const {
222 RCHECK(AVC::ConvertFrameToAnnexB(hevc_config_
->lengthSizeMinusOne
+ 1,
223 frame_buf
, subsamples
));
226 // If this is a keyframe, we (re-)inject HEVC params headers at the start of
227 // a frame. If subsample info is present, we also update the clear byte
228 // count for that first subsample.
229 RCHECK(HEVC::InsertParamSetsAnnexB(*hevc_config_
, frame_buf
, subsamples
));
232 DCHECK(HEVC::IsValidAnnexB(*frame_buf
, *subsamples
));