Home | History | Annotate | Download | only in mp4
      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 
     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
     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
     76 bool 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
    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
    174 bool AVC::IsValidAnnexB(const std::vector<uint8>& buffer,
    175                         const std::vector<SubsampleEntry>& subsamples) {
    176   return IsValidAnnexB(&buffer[0], buffer.size(), subsamples);
    177 }
    178 
    179 bool 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