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