Home | History | Annotate | Download | only in mp4
      1 // Copyright (c) 2012 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/mp4/avc.h"
      6 
      7 #include <algorithm>
      8 #include <vector>
      9 
     10 #include "media/mp4/box_definitions.h"
     11 #include "media/mp4/box_reader.h"
     12 
     13 namespace media {
     14 namespace mp4 {
     15 
     16 static const uint8 kAnnexBStartCode[] = {0, 0, 0, 1};
     17 static const int kAnnexBStartCodeSize = 4;
     18 
     19 static bool ConvertAVCToAnnexBInPlaceForLengthSize4(std::vector<uint8>* buf) {
     20   const int kLengthSize = 4;
     21   size_t pos = 0;
     22   while (pos + kLengthSize < buf->size()) {
     23     int nal_size = (*buf)[pos];
     24     nal_size = (nal_size << 8) + (*buf)[pos+1];
     25     nal_size = (nal_size << 8) + (*buf)[pos+2];
     26     nal_size = (nal_size << 8) + (*buf)[pos+3];
     27     std::copy(kAnnexBStartCode, kAnnexBStartCode + kAnnexBStartCodeSize,
     28               buf->begin() + pos);
     29     pos += kLengthSize + nal_size;
     30   }
     31   return pos == buf->size();
     32 }
     33 
     34 // static
     35 bool AVC::ConvertFrameToAnnexB(int length_size, std::vector<uint8>* buffer) {
     36   RCHECK(length_size == 1 || length_size == 2 || length_size == 4);
     37 
     38   if (length_size == 4)
     39     return ConvertAVCToAnnexBInPlaceForLengthSize4(buffer);
     40 
     41   std::vector<uint8> temp;
     42   temp.swap(*buffer);
     43   buffer->reserve(temp.size() + 32);
     44 
     45   size_t pos = 0;
     46   while (pos + length_size < temp.size()) {
     47     int nal_size = temp[pos];
     48     if (length_size == 2) nal_size = (nal_size << 8) + temp[pos+1];
     49     pos += length_size;
     50 
     51     RCHECK(pos + nal_size <= temp.size());
     52     buffer->insert(buffer->end(), kAnnexBStartCode,
     53                    kAnnexBStartCode + kAnnexBStartCodeSize);
     54     buffer->insert(buffer->end(), temp.begin() + pos,
     55                    temp.begin() + pos + nal_size);
     56     pos += nal_size;
     57   }
     58   return pos == temp.size();
     59 }
     60 
     61 // static
     62 bool AVC::ConvertConfigToAnnexB(
     63     const AVCDecoderConfigurationRecord& avc_config,
     64     std::vector<uint8>* buffer) {
     65   DCHECK(buffer->empty());
     66   buffer->clear();
     67   int total_size = 0;
     68   for (size_t i = 0; i < avc_config.sps_list.size(); i++)
     69     total_size += avc_config.sps_list[i].size() + kAnnexBStartCodeSize;
     70   for (size_t i = 0; i < avc_config.pps_list.size(); i++)
     71     total_size += avc_config.pps_list[i].size() + kAnnexBStartCodeSize;
     72   buffer->reserve(total_size);
     73 
     74   for (size_t i = 0; i < avc_config.sps_list.size(); i++) {
     75     buffer->insert(buffer->end(), kAnnexBStartCode,
     76                 kAnnexBStartCode + kAnnexBStartCodeSize);
     77     buffer->insert(buffer->end(), avc_config.sps_list[i].begin(),
     78                 avc_config.sps_list[i].end());
     79   }
     80 
     81   for (size_t i = 0; i < avc_config.pps_list.size(); i++) {
     82     buffer->insert(buffer->end(), kAnnexBStartCode,
     83                    kAnnexBStartCode + kAnnexBStartCodeSize);
     84     buffer->insert(buffer->end(), avc_config.pps_list[i].begin(),
     85                    avc_config.pps_list[i].end());
     86   }
     87   return true;
     88 }
     89 
     90 }  // namespace mp4
     91 }  // namespace media
     92