• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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.
4 
5 #include "media/formats/mp4/avc.h"
6 
7 #include <algorithm>
8 #include <vector>
9 
10 #include "base/logging.h"
11 #include "media/base/decrypt_config.h"
12 #include "media/filters/h264_parser.h"
13 #include "media/formats/mp4/box_definitions.h"
14 #include "media/formats/mp4/box_reader.h"
15 
16 namespace media {
17 namespace mp4 {
18 
19 static const uint8 kAnnexBStartCode[] = {0, 0, 0, 1};
20 static const int kAnnexBStartCodeSize = 4;
21 
ConvertAVCToAnnexBInPlaceForLengthSize4(std::vector<uint8> * buf)22 static bool ConvertAVCToAnnexBInPlaceForLengthSize4(std::vector<uint8>* buf) {
23   const int kLengthSize = 4;
24   size_t pos = 0;
25   while (pos + kLengthSize < buf->size()) {
26     uint32 nal_size = (*buf)[pos];
27     nal_size = (nal_size << 8) + (*buf)[pos+1];
28     nal_size = (nal_size << 8) + (*buf)[pos+2];
29     nal_size = (nal_size << 8) + (*buf)[pos+3];
30 
31     if (nal_size == 0) {
32       DVLOG(1) << "nal_size is 0";
33       return false;
34     }
35 
36     std::copy(kAnnexBStartCode, kAnnexBStartCode + kAnnexBStartCodeSize,
37               buf->begin() + pos);
38     pos += kLengthSize + nal_size;
39   }
40   return pos == buf->size();
41 }
42 
43 // static
ConvertFrameToAnnexB(int length_size,std::vector<uint8> * buffer)44 bool AVC::ConvertFrameToAnnexB(int length_size, std::vector<uint8>* buffer) {
45   RCHECK(length_size == 1 || length_size == 2 || length_size == 4);
46 
47   if (length_size == 4)
48     return ConvertAVCToAnnexBInPlaceForLengthSize4(buffer);
49 
50   std::vector<uint8> temp;
51   temp.swap(*buffer);
52   buffer->reserve(temp.size() + 32);
53 
54   size_t pos = 0;
55   while (pos + length_size < temp.size()) {
56     int nal_size = temp[pos];
57     if (length_size == 2) nal_size = (nal_size << 8) + temp[pos+1];
58     pos += length_size;
59 
60     if (nal_size == 0) {
61       DVLOG(1) << "nal_size is 0";
62       return false;
63     }
64 
65     RCHECK(pos + nal_size <= temp.size());
66     buffer->insert(buffer->end(), kAnnexBStartCode,
67                    kAnnexBStartCode + kAnnexBStartCodeSize);
68     buffer->insert(buffer->end(), temp.begin() + pos,
69                    temp.begin() + pos + nal_size);
70     pos += nal_size;
71   }
72   return pos == temp.size();
73 }
74 
75 // static
InsertParamSetsAnnexB(const AVCDecoderConfigurationRecord & avc_config,std::vector<uint8> * buffer,std::vector<SubsampleEntry> * subsamples)76 bool AVC::InsertParamSetsAnnexB(const AVCDecoderConfigurationRecord& avc_config,
77                                 std::vector<uint8>* buffer,
78                                 std::vector<SubsampleEntry>* subsamples) {
79   DCHECK(AVC::IsValidAnnexB(*buffer));
80 
81   scoped_ptr<H264Parser> parser(new H264Parser());
82   const uint8* start = &(*buffer)[0];
83   parser->SetStream(start, buffer->size());
84 
85   H264NALU nalu;
86   if (parser->AdvanceToNextNALU(&nalu) != H264Parser::kOk)
87     return false;
88 
89   std::vector<uint8>::iterator config_insert_point = buffer->begin();
90   std::vector<SubsampleEntry>::iterator subsamples_insert_point =
91       subsamples->begin();
92 
93   if (nalu.nal_unit_type == H264NALU::kAUD) {
94     // Move insert point to just after the AUD.
95     config_insert_point += (nalu.data + nalu.size) - start;
96 
97     if (!subsamples->empty()) {
98       int64 first_subsample_size =
99           (*subsamples)[0].clear_bytes + (*subsamples)[0].cypher_bytes;
100 
101       if (first_subsample_size != (config_insert_point - buffer->begin()))
102         return false;
103 
104       subsamples_insert_point++;
105     }
106 
107   }
108 
109   // Clear |parser| and |start| since they aren't needed anymore and
110   // will hold stale pointers once the insert happens.
111   parser.reset();
112   start = NULL;
113 
114   std::vector<uint8> param_sets;
115   std::vector<SubsampleEntry> config_subsamples;
116   RCHECK(AVC::ConvertConfigToAnnexB(avc_config,
117                                     &param_sets,
118                                     &config_subsamples));
119 
120   if (!subsamples->empty()) {
121     subsamples->insert(subsamples_insert_point,
122                        config_subsamples.begin(),
123                        config_subsamples.end());
124   }
125 
126   buffer->insert(config_insert_point,
127                  param_sets.begin(), param_sets.end());
128 
129   DCHECK(AVC::IsValidAnnexB(*buffer));
130   return true;
131 }
132 
133 // static
ConvertConfigToAnnexB(const AVCDecoderConfigurationRecord & avc_config,std::vector<uint8> * buffer,std::vector<SubsampleEntry> * subsamples)134 bool AVC::ConvertConfigToAnnexB(
135     const AVCDecoderConfigurationRecord& avc_config,
136     std::vector<uint8>* buffer,
137     std::vector<SubsampleEntry>* subsamples) {
138   DCHECK(buffer->empty());
139   buffer->clear();
140   int total_size = 0;
141   for (size_t i = 0; i < avc_config.sps_list.size(); i++)
142     total_size += avc_config.sps_list[i].size() + kAnnexBStartCodeSize;
143   for (size_t i = 0; i < avc_config.pps_list.size(); i++)
144     total_size += avc_config.pps_list[i].size() + kAnnexBStartCodeSize;
145   buffer->reserve(total_size);
146 
147   for (size_t i = 0; i < avc_config.sps_list.size(); i++) {
148     buffer->insert(buffer->end(), kAnnexBStartCode,
149                 kAnnexBStartCode + kAnnexBStartCodeSize);
150     buffer->insert(buffer->end(), avc_config.sps_list[i].begin(),
151                 avc_config.sps_list[i].end());
152 
153     SubsampleEntry entry;
154     entry.clear_bytes = kAnnexBStartCodeSize + avc_config.sps_list[i].size();
155     entry.cypher_bytes = 0;
156     subsamples->push_back(entry);
157   }
158 
159   for (size_t i = 0; i < avc_config.pps_list.size(); i++) {
160     buffer->insert(buffer->end(), kAnnexBStartCode,
161                    kAnnexBStartCode + kAnnexBStartCodeSize);
162     buffer->insert(buffer->end(), avc_config.pps_list[i].begin(),
163                    avc_config.pps_list[i].end());
164 
165     SubsampleEntry entry;
166     entry.clear_bytes = kAnnexBStartCodeSize + avc_config.pps_list[i].size();
167     entry.cypher_bytes = 0;
168     subsamples->push_back(entry);
169   }
170   return true;
171 }
172 
173 // Verifies AnnexB NALU order according to ISO/IEC 14496-10 Section 7.4.1.2.3
IsValidAnnexB(const std::vector<uint8> & buffer)174 bool AVC::IsValidAnnexB(const std::vector<uint8>& buffer) {
175   return IsValidAnnexB(&buffer[0], buffer.size());
176 }
177 
IsValidAnnexB(const uint8 * buffer,size_t size)178 bool AVC::IsValidAnnexB(const uint8* buffer, size_t size) {
179   DVLOG(1) << __FUNCTION__;
180   DCHECK(buffer);
181 
182   if (size == 0)
183     return true;
184 
185   H264Parser parser;
186   parser.SetStream(buffer, size);
187 
188   typedef enum {
189     kAUDAllowed,
190     kBeforeFirstVCL,  // VCL == nal_unit_types 1-5
191     kAfterFirstVCL,
192     kEOStreamAllowed,
193     kNoMoreDataAllowed,
194   } NALUOrderState;
195 
196   H264NALU nalu;
197   NALUOrderState order_state = kAUDAllowed;
198   int last_nalu_type = H264NALU::kUnspecified;
199   bool done = false;
200   while (!done) {
201     switch (parser.AdvanceToNextNALU(&nalu)) {
202       case H264Parser::kOk:
203         DVLOG(1) << "nal_unit_type " << nalu.nal_unit_type;
204 
205         switch (nalu.nal_unit_type) {
206           case H264NALU::kAUD:
207             if (order_state > kAUDAllowed) {
208               DVLOG(1) << "Unexpected AUD in order_state " << order_state;
209               return false;
210             }
211             order_state = kBeforeFirstVCL;
212             break;
213 
214           case H264NALU::kSEIMessage:
215           case H264NALU::kReserved14:
216           case H264NALU::kReserved15:
217           case H264NALU::kReserved16:
218           case H264NALU::kReserved17:
219           case H264NALU::kReserved18:
220           case H264NALU::kPPS:
221           case H264NALU::kSPS:
222             if (order_state > kBeforeFirstVCL) {
223               DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
224                        << " in order_state " << order_state;
225               return false;
226             }
227             order_state = kBeforeFirstVCL;
228             break;
229 
230           case H264NALU::kSPSExt:
231             if (last_nalu_type != H264NALU::kSPS) {
232               DVLOG(1) << "SPS extension does not follow an SPS.";
233               return false;
234             }
235             break;
236 
237           case H264NALU::kNonIDRSlice:
238           case H264NALU::kSliceDataA:
239           case H264NALU::kSliceDataB:
240           case H264NALU::kSliceDataC:
241           case H264NALU::kIDRSlice:
242             if (order_state > kAfterFirstVCL) {
243               DVLOG(1) << "Unexpected VCL in order_state " << order_state;
244               return false;
245             }
246             order_state = kAfterFirstVCL;
247             break;
248 
249           case H264NALU::kCodedSliceAux:
250             if (order_state != kAfterFirstVCL) {
251               DVLOG(1) << "Unexpected extension in order_state " << order_state;
252               return false;
253             }
254             break;
255 
256           case H264NALU::kEOSeq:
257             if (order_state != kAfterFirstVCL) {
258               DVLOG(1) << "Unexpected EOSeq in order_state " << order_state;
259               return false;
260             }
261             order_state = kEOStreamAllowed;
262             break;
263 
264           case H264NALU::kEOStream:
265             if (order_state < kAfterFirstVCL) {
266               DVLOG(1) << "Unexpected EOStream in order_state " << order_state;
267               return false;
268             }
269             order_state = kNoMoreDataAllowed;
270             break;
271 
272           case H264NALU::kFiller:
273           case H264NALU::kUnspecified:
274             if (!(order_state >= kAfterFirstVCL &&
275                   order_state < kEOStreamAllowed)) {
276               DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
277                        << " in order_state " << order_state;
278               return false;
279             }
280             break;
281 
282           default:
283             DCHECK_GE(nalu.nal_unit_type, 20);
284             if (nalu.nal_unit_type >= 20 && nalu.nal_unit_type <= 31 &&
285                 order_state != kAfterFirstVCL) {
286               DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
287                        << " in order_state " << order_state;
288               return false;
289             }
290         }
291         last_nalu_type = nalu.nal_unit_type;
292         break;
293 
294       case H264Parser::kInvalidStream:
295         return false;
296 
297       case H264Parser::kUnsupportedStream:
298         NOTREACHED() << "AdvanceToNextNALU() returned kUnsupportedStream!";
299         return false;
300 
301       case H264Parser::kEOStream:
302         done = true;
303     }
304   }
305 
306   return order_state >= kAfterFirstVCL;
307 }
308 
309 }  // namespace mp4
310 }  // namespace media
311