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