avc.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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
16namespace media {
17namespace mp4 {
18
19static const uint8 kAnnexBStartCode[] = {0, 0, 0, 1};
20static const int kAnnexBStartCodeSize = 4;
21
22static 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
44bool 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
76bool AVC::InsertParamSetsAnnexB(const AVCDecoderConfigurationRecord& avc_config,
77                                std::vector<uint8>* buffer,
78                                std::vector<SubsampleEntry>* subsamples) {
79  DCHECK(AVC::IsValidAnnexB(*buffer, *subsamples));
80
81  scoped_ptr<H264Parser> parser(new H264Parser());
82  const uint8* start = &(*buffer)[0];
83  parser->SetEncryptedStream(start, buffer->size(), *subsamples);
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, *subsamples));
130  return true;
131}
132
133// static
134bool 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
174bool AVC::IsValidAnnexB(const std::vector<uint8>& buffer,
175                        const std::vector<SubsampleEntry>& subsamples) {
176  return IsValidAnnexB(&buffer[0], buffer.size(), subsamples);
177}
178
179bool AVC::IsValidAnnexB(const uint8* buffer, size_t size,
180                        const std::vector<SubsampleEntry>& subsamples) {
181  DVLOG(1) << __FUNCTION__;
182  DCHECK(buffer);
183
184  if (size == 0)
185    return true;
186
187  H264Parser parser;
188  parser.SetEncryptedStream(buffer, size, subsamples);
189
190  typedef enum {
191    kAUDAllowed,
192    kBeforeFirstVCL,  // VCL == nal_unit_types 1-5
193    kAfterFirstVCL,
194    kEOStreamAllowed,
195    kNoMoreDataAllowed,
196  } NALUOrderState;
197
198  H264NALU nalu;
199  NALUOrderState order_state = kAUDAllowed;
200  int last_nalu_type = H264NALU::kUnspecified;
201  bool done = false;
202  while (!done) {
203    switch (parser.AdvanceToNextNALU(&nalu)) {
204      case H264Parser::kOk:
205        DVLOG(1) << "nal_unit_type " << nalu.nal_unit_type;
206
207        switch (nalu.nal_unit_type) {
208          case H264NALU::kAUD:
209            if (order_state > kAUDAllowed) {
210              DVLOG(1) << "Unexpected AUD in order_state " << order_state;
211              return false;
212            }
213            order_state = kBeforeFirstVCL;
214            break;
215
216          case H264NALU::kSEIMessage:
217          case H264NALU::kReserved14:
218          case H264NALU::kReserved15:
219          case H264NALU::kReserved16:
220          case H264NALU::kReserved17:
221          case H264NALU::kReserved18:
222          case H264NALU::kPPS:
223          case H264NALU::kSPS:
224            if (order_state > kBeforeFirstVCL) {
225              DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
226                       << " in order_state " << order_state;
227              return false;
228            }
229            order_state = kBeforeFirstVCL;
230            break;
231
232          case H264NALU::kSPSExt:
233            if (last_nalu_type != H264NALU::kSPS) {
234              DVLOG(1) << "SPS extension does not follow an SPS.";
235              return false;
236            }
237            break;
238
239          case H264NALU::kNonIDRSlice:
240          case H264NALU::kSliceDataA:
241          case H264NALU::kSliceDataB:
242          case H264NALU::kSliceDataC:
243          case H264NALU::kIDRSlice:
244            if (order_state > kAfterFirstVCL) {
245              DVLOG(1) << "Unexpected VCL in order_state " << order_state;
246              return false;
247            }
248            order_state = kAfterFirstVCL;
249            break;
250
251          case H264NALU::kCodedSliceAux:
252            if (order_state != kAfterFirstVCL) {
253              DVLOG(1) << "Unexpected extension in order_state " << order_state;
254              return false;
255            }
256            break;
257
258          case H264NALU::kEOSeq:
259            if (order_state != kAfterFirstVCL) {
260              DVLOG(1) << "Unexpected EOSeq in order_state " << order_state;
261              return false;
262            }
263            order_state = kEOStreamAllowed;
264            break;
265
266          case H264NALU::kEOStream:
267            if (order_state < kAfterFirstVCL) {
268              DVLOG(1) << "Unexpected EOStream in order_state " << order_state;
269              return false;
270            }
271            order_state = kNoMoreDataAllowed;
272            break;
273
274          case H264NALU::kFiller:
275          case H264NALU::kUnspecified:
276            if (!(order_state >= kAfterFirstVCL &&
277                  order_state < kEOStreamAllowed)) {
278              DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
279                       << " in order_state " << order_state;
280              return false;
281            }
282            break;
283
284          default:
285            DCHECK_GE(nalu.nal_unit_type, 20);
286            if (nalu.nal_unit_type >= 20 && nalu.nal_unit_type <= 31 &&
287                order_state != kAfterFirstVCL) {
288              DVLOG(1) << "Unexpected NALU type " << nalu.nal_unit_type
289                       << " in order_state " << order_state;
290              return false;
291            }
292        }
293        last_nalu_type = nalu.nal_unit_type;
294        break;
295
296      case H264Parser::kInvalidStream:
297        return false;
298
299      case H264Parser::kUnsupportedStream:
300        NOTREACHED() << "AdvanceToNextNALU() returned kUnsupportedStream!";
301        return false;
302
303      case H264Parser::kEOStream:
304        done = true;
305    }
306  }
307
308  return order_state >= kAfterFirstVCL;
309}
310}  // namespace mp4
311}  // namespace media
312