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