40609a8755cbc19b530a285460427347911ebd7e
[platform/framework/web/chromium-efl.git] / media / formats / mp4 / avc.cc
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/formats/mp4/avc.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/logging.h"
11 #include "base/ranges/algorithm.h"
12 #include "media/base/decrypt_config.h"
13 #include "media/formats/mp4/box_definitions.h"
14 #include "media/formats/mp4/box_reader.h"
15 #include "media/video/h264_parser.h"
16
17 namespace media {
18 namespace mp4 {
19
20 static constexpr uint8_t kAnnexBStartCode[] = {0, 0, 0, 1};
21 static constexpr int kAnnexBStartCodeSize = 4;
22
23 static bool ConvertAVCToAnnexBInPlaceForLengthSize4(std::vector<uint8_t>* buf) {
24   const size_t kLengthSize = 4;
25   size_t pos = 0;
26   while (buf->size() > kLengthSize && buf->size() - kLengthSize > pos) {
27     uint32_t nal_length = (*buf)[pos];
28     nal_length = (nal_length << 8) + (*buf)[pos+1];
29     nal_length = (nal_length << 8) + (*buf)[pos+2];
30     nal_length = (nal_length << 8) + (*buf)[pos+3];
31
32     if (nal_length == 0) {
33       DVLOG(3) << "nal_length is 0";
34       return false;
35     }
36
37     base::ranges::copy(kAnnexBStartCode, buf->begin() + pos);
38     pos += kLengthSize + nal_length;
39   }
40   return pos == buf->size();
41 }
42
43 // static
44 int AVC::FindSubsampleIndex(const std::vector<uint8_t>& buffer,
45                             const std::vector<SubsampleEntry>* subsamples,
46                             const uint8_t* ptr) {
47   DCHECK(ptr >= &buffer[0]);
48   DCHECK(ptr <= &buffer[buffer.size()-1]);
49   if (!subsamples || subsamples->empty())
50     return 0;
51
52   const uint8_t* p = &buffer[0];
53   for (size_t i = 0; i < subsamples->size(); ++i) {
54     p += (*subsamples)[i].clear_bytes + (*subsamples)[i].cypher_bytes;
55     if (p > ptr)
56       return i;
57   }
58   NOTREACHED_NORETURN();
59 }
60
61 // static
62 bool AVC::ConvertFrameToAnnexB(size_t length_size,
63                                std::vector<uint8_t>* buffer,
64                                std::vector<SubsampleEntry>* subsamples) {
65   RCHECK(length_size == 1 || length_size == 2 || length_size == 4);
66   DVLOG(5) << __func__ << " length_size=" << length_size
67            << " buffer->size()=" << buffer->size()
68            << " subsamples=" << (subsamples ? subsamples->size() : 0);
69
70   if (length_size == 4)
71     return ConvertAVCToAnnexBInPlaceForLengthSize4(buffer);
72
73   std::vector<uint8_t> temp;
74   temp.swap(*buffer);
75   buffer->reserve(temp.size() + 32);
76
77   size_t pos = 0;
78   while (temp.size() > length_size && temp.size() - length_size > pos) {
79     size_t nal_length = temp[pos];
80     if (length_size == 2) nal_length = (nal_length << 8) + temp[pos+1];
81     pos += length_size;
82
83     if (nal_length == 0) {
84       DVLOG(3) << "nal_length is 0";
85       return false;
86     }
87
88     RCHECK(temp.size() >= nal_length && temp.size() - nal_length >= pos);
89     buffer->insert(buffer->end(), kAnnexBStartCode,
90                    kAnnexBStartCode + kAnnexBStartCodeSize);
91     if (subsamples && !subsamples->empty()) {
92       uint8_t* buffer_pos = &(*(buffer->end() - kAnnexBStartCodeSize));
93       int subsample_index = FindSubsampleIndex(*buffer, subsamples, buffer_pos);
94       // We've replaced NALU size value with an AnnexB start code.
95       int size_adjustment = kAnnexBStartCodeSize - length_size;
96       (*subsamples)[subsample_index].clear_bytes += size_adjustment;
97     }
98     buffer->insert(buffer->end(), temp.begin() + pos,
99                    temp.begin() + pos + nal_length);
100     pos += nal_length;
101   }
102   return pos == temp.size();
103 }
104
105 // static
106 bool AVC::InsertParamSetsAnnexB(const AVCDecoderConfigurationRecord& avc_config,
107                                 std::vector<uint8_t>* buffer,
108                                 std::vector<SubsampleEntry>* subsamples) {
109   std::unique_ptr<H264Parser> parser(new H264Parser());
110   const uint8_t* start = &(*buffer)[0];
111   parser->SetEncryptedStream(start, buffer->size(), *subsamples);
112
113   H264NALU nalu;
114   if (parser->AdvanceToNextNALU(&nalu) != H264Parser::kOk)
115     return false;
116
117   std::vector<uint8_t>::iterator config_insert_point = buffer->begin();
118
119   if (nalu.nal_unit_type == H264NALU::kAUD) {
120     // Move insert point to just after the AUD.
121     config_insert_point += (nalu.data + nalu.size) - start;
122   }
123
124   // Clear |parser| and |start| since they aren't needed anymore and
125   // will hold stale pointers once the insert happens.
126   parser.reset();
127   start = NULL;
128
129   std::vector<uint8_t> param_sets;
130   RCHECK(AVC::ConvertConfigToAnnexB(avc_config, &param_sets));
131
132   if (subsamples && !subsamples->empty()) {
133     if (config_insert_point != buffer->end()) {
134       int subsample_index =
135           FindSubsampleIndex(*buffer, subsamples, &(*config_insert_point));
136       // Update the size of the subsample where SPS/PPS is to be inserted.
137       (*subsamples)[subsample_index].clear_bytes += param_sets.size();
138     } else {
139       int subsample_index = (*subsamples).size() - 1;
140       if ((*subsamples)[subsample_index].cypher_bytes == 0) {
141         // Extend the last clear range to include the inserted data.
142         (*subsamples)[subsample_index].clear_bytes += param_sets.size();
143       } else {
144         // Append a new subsample to cover the inserted data.
145         (*subsamples).emplace_back(param_sets.size(), 0);
146       }
147     }
148   }
149
150   buffer->insert(config_insert_point,
151                  param_sets.begin(), param_sets.end());
152   return true;
153 }
154
155 // static
156 bool AVC::ConvertConfigToAnnexB(const AVCDecoderConfigurationRecord& avc_config,
157                                 std::vector<uint8_t>* buffer) {
158   DCHECK(buffer->empty());
159   buffer->clear();
160   int total_size = 0;
161   for (size_t i = 0; i < avc_config.sps_list.size(); i++)
162     total_size += avc_config.sps_list[i].size() + kAnnexBStartCodeSize;
163   for (size_t i = 0; i < avc_config.pps_list.size(); i++)
164     total_size += avc_config.pps_list[i].size() + kAnnexBStartCodeSize;
165   buffer->reserve(total_size);
166
167   for (size_t i = 0; i < avc_config.sps_list.size(); i++) {
168     buffer->insert(buffer->end(), kAnnexBStartCode,
169                 kAnnexBStartCode + kAnnexBStartCodeSize);
170     buffer->insert(buffer->end(), avc_config.sps_list[i].begin(),
171                 avc_config.sps_list[i].end());
172   }
173
174   for (size_t i = 0; i < avc_config.pps_list.size(); i++) {
175     buffer->insert(buffer->end(), kAnnexBStartCode,
176                    kAnnexBStartCode + kAnnexBStartCodeSize);
177     buffer->insert(buffer->end(), avc_config.pps_list[i].begin(),
178                    avc_config.pps_list[i].end());
179   }
180   return true;
181 }
182
183 // static
184 BitstreamConverter::AnalysisResult AVC::AnalyzeAnnexB(
185     const uint8_t* buffer,
186     size_t size,
187     const std::vector<SubsampleEntry>& subsamples) {
188   DVLOG(3) << __func__;
189   DCHECK(buffer);
190
191   BitstreamConverter::AnalysisResult result;
192   result.is_conformant = false;  // Will change if needed before return.
193
194   if (size == 0) {
195     result.is_conformant = true;
196     return result;
197   }
198
199   H264Parser parser;
200   parser.SetEncryptedStream(buffer, size, subsamples);
201
202   typedef enum {
203     kAUDAllowed,
204     kBeforeFirstVCL,  // VCL == nal_unit_types 1-5
205     kAfterFirstVCL,
206     kEOStreamAllowed,
207     kNoMoreDataAllowed,
208   } NALUOrderState;
209
210   H264NALU nalu;
211   NALUOrderState order_state = kAUDAllowed;
212   int last_nalu_type = H264NALU::kUnspecified;
213   bool done = false;
214   while (!done) {
215     switch (parser.AdvanceToNextNALU(&nalu)) {
216       case H264Parser::kOk:
217         DVLOG(3) << "nal_unit_type " << nalu.nal_unit_type;
218
219         switch (nalu.nal_unit_type) {
220           case H264NALU::kAUD:
221             if (order_state > kAUDAllowed) {
222               DVLOG(1) << "Unexpected AUD in order_state " << order_state;
223               return result;
224             }
225             order_state = kBeforeFirstVCL;
226             break;
227
228           case H264NALU::kSEIMessage:
229           case H264NALU::kPrefix:
230           case H264NALU::kSubsetSPS:
231           case H264NALU::kDPS:
232           case H264NALU::kReserved17:
233           case H264NALU::kReserved18:
234           case H264NALU::kPPS:
235           case H264NALU::kSPS:
236             if (order_state > kBeforeFirstVCL) {
237               DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
238                        << " in order_state " << order_state;
239               return result;
240             }
241             order_state = kBeforeFirstVCL;
242             break;
243
244           case H264NALU::kSPSExt:
245             if (last_nalu_type != H264NALU::kSPS) {
246               DVLOG(1) << "SPS extension does not follow an SPS.";
247               return result;
248             }
249             break;
250
251           case H264NALU::kNonIDRSlice:
252           case H264NALU::kSliceDataA:
253           case H264NALU::kSliceDataB:
254           case H264NALU::kSliceDataC:
255           case H264NALU::kIDRSlice:
256             if (order_state > kAfterFirstVCL) {
257               DVLOG(1) << "Unexpected VCL in order_state " << order_state;
258               return result;
259             }
260
261             if (!result.is_keyframe.has_value())
262               result.is_keyframe = nalu.nal_unit_type == H264NALU::kIDRSlice;
263
264             order_state = kAfterFirstVCL;
265             break;
266
267           case H264NALU::kCodedSliceAux:
268             if (order_state != kAfterFirstVCL) {
269               DVLOG(1) << "Unexpected extension in order_state " << order_state;
270               return result;
271             }
272             break;
273
274           case H264NALU::kEOSeq:
275             if (order_state != kAfterFirstVCL) {
276               DVLOG(1) << "Unexpected EOSeq in order_state " << order_state;
277               return result;
278             }
279             order_state = kEOStreamAllowed;
280             break;
281
282           case H264NALU::kEOStream:
283             if (order_state < kAfterFirstVCL) {
284               DVLOG(1) << "Unexpected EOStream in order_state " << order_state;
285               return result;
286             }
287             order_state = kNoMoreDataAllowed;
288             break;
289
290           case H264NALU::kFiller:
291           case H264NALU::kUnspecified:
292             if (!(order_state >= kAfterFirstVCL &&
293                   order_state < kEOStreamAllowed)) {
294               DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
295                        << " in order_state " << order_state;
296               return result;
297             }
298             break;
299
300           default:
301             DCHECK_GE(nalu.nal_unit_type, 20);
302             if (nalu.nal_unit_type >= 20 && nalu.nal_unit_type <= 31 &&
303                 order_state != kAfterFirstVCL) {
304               DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
305                        << " in order_state " << order_state;
306               return result;
307             }
308         }
309         last_nalu_type = nalu.nal_unit_type;
310         break;
311
312       case H264Parser::kInvalidStream:
313         return result;
314
315       case H264Parser::kUnsupportedStream:
316         NOTREACHED() << "AdvanceToNextNALU() returned kUnsupportedStream!";
317         return result;
318
319       case H264Parser::kEOStream:
320         done = true;
321     }
322   }
323
324   if (order_state < kAfterFirstVCL)
325     return result;
326
327   result.is_conformant = true;
328   DCHECK(result.is_keyframe.has_value());
329   return result;
330 }
331
332 AVCBitstreamConverter::AVCBitstreamConverter(
333     std::unique_ptr<AVCDecoderConfigurationRecord> avc_config)
334     : avc_config_(std::move(avc_config)) {
335   DCHECK(avc_config_);
336 }
337
338 AVCBitstreamConverter::~AVCBitstreamConverter() = default;
339
340 bool AVCBitstreamConverter::ConvertAndAnalyzeFrame(
341     std::vector<uint8_t>* frame_buf,
342     bool is_keyframe,
343     std::vector<SubsampleEntry>* subsamples,
344     AnalysisResult* analysis_result) const {
345   // Convert the AVC NALU length fields to Annex B headers, as expected by
346   // decoding libraries. Since this may enlarge the size of the buffer, we also
347   // update the clear byte count for each subsample if encryption is used to
348   // account for the difference in size between the length prefix and Annex B
349   // start code.
350   RCHECK(AVC::ConvertFrameToAnnexB(avc_config_->length_size, frame_buf,
351                                    subsamples));
352
353   // |is_keyframe| may be incorrect. Analyze the frame to see if it is a
354   // keyframe. |is_keyframe| will be used if the analysis is inconclusive.
355   // Also, provide the analysis result to the caller via out parameter
356   // |analysis_result|.
357   *analysis_result = Analyze(frame_buf, subsamples);
358
359   if (analysis_result->is_keyframe.value_or(is_keyframe)) {
360     // If this is a keyframe, we (re-)inject SPS and PPS headers at the start of
361     // a frame. If subsample info is present, we also update the clear byte
362     // count for that first subsample.
363     RCHECK(AVC::InsertParamSetsAnnexB(*avc_config_, frame_buf, subsamples));
364   }
365
366   return true;
367 }
368
369 BitstreamConverter::AnalysisResult AVCBitstreamConverter::Analyze(
370     std::vector<uint8_t>* frame_buf,
371     std::vector<SubsampleEntry>* subsamples) const {
372   return AVC::AnalyzeAnnexB(frame_buf->data(), frame_buf->size(), *subsamples);
373 }
374
375 }  // namespace mp4
376 }  // namespace media