OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/formats/mp2t/es_parser_h264.h" | 5 #include "media/formats/mp2t/es_parser_h264.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/numerics/safe_conversions.h" | 10 #include "base/numerics/safe_conversions.h" |
| 11 #include "media/base/decrypt_config.h" |
11 #include "media/base/encryption_scheme.h" | 12 #include "media/base/encryption_scheme.h" |
12 #include "media/base/media_util.h" | 13 #include "media/base/media_util.h" |
13 #include "media/base/stream_parser_buffer.h" | 14 #include "media/base/stream_parser_buffer.h" |
14 #include "media/base/timestamp_constants.h" | 15 #include "media/base/timestamp_constants.h" |
15 #include "media/base/video_frame.h" | 16 #include "media/base/video_frame.h" |
16 #include "media/filters/h264_parser.h" | 17 #include "media/filters/h264_parser.h" |
17 #include "media/formats/common/offset_byte_queue.h" | 18 #include "media/formats/common/offset_byte_queue.h" |
18 #include "media/formats/mp2t/mp2t_common.h" | 19 #include "media/formats/mp2t/mp2t_common.h" |
19 #include "ui/gfx/geometry/rect.h" | 20 #include "ui/gfx/geometry/rect.h" |
20 #include "ui/gfx/geometry/size.h" | 21 #include "ui/gfx/geometry/size.h" |
(...skipping 23 matching lines...) Expand all Loading... |
44 return H264PROFILE_SCALABLEHIGH; | 45 return H264PROFILE_SCALABLEHIGH; |
45 case H264SPS::kProfileIDStereoHigh: | 46 case H264SPS::kProfileIDStereoHigh: |
46 return H264PROFILE_STEREOHIGH; | 47 return H264PROFILE_STEREOHIGH; |
47 case H264SPS::kProfileIDSMultiviewHigh: | 48 case H264SPS::kProfileIDSMultiviewHigh: |
48 return H264PROFILE_MULTIVIEWHIGH; | 49 return H264PROFILE_MULTIVIEWHIGH; |
49 } | 50 } |
50 NOTREACHED() << "unknown video profile: " << profile_idc; | 51 NOTREACHED() << "unknown video profile: " << profile_idc; |
51 return VIDEO_CODEC_PROFILE_UNKNOWN; | 52 return VIDEO_CODEC_PROFILE_UNKNOWN; |
52 } | 53 } |
53 | 54 |
| 55 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| 56 |
| 57 const int kSampleAESMaxUnprotectedNALULength = 48; |
| 58 const int kSampleAESClearLeaderSize = 32; |
| 59 const int kSampleAESEncryptBlocks = 1; |
| 60 const int kSampleAESSkipBlocks = 9; |
| 61 const int kSampleAESPatternUnit = |
| 62 (kSampleAESEncryptBlocks + kSampleAESSkipBlocks) * 16; |
| 63 |
| 64 // Attempts to find the first or only EP3B (emulation prevention 3 byte) in |
| 65 // the part of the |buffer| between |start_pos| and |end_pos|. Returns the |
| 66 // position of the EP3B, or 0 if there are none. |
| 67 // Note: the EP3B always follows two zero bytes, so the value 0 can never be a |
| 68 // valid position. |
| 69 int FindEP3B(const uint8_t* buffer, int start_pos, int end_pos) { |
| 70 const uint8_t* data = buffer + start_pos; |
| 71 int data_size = end_pos - start_pos; |
| 72 DCHECK_GE(data_size, 0); |
| 73 int bytes_left = data_size; |
| 74 |
| 75 while (bytes_left >= 4) { |
| 76 if (data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x03 && |
| 77 data[3] <= 0x03) { |
| 78 return (data - buffer) + 2; |
| 79 } |
| 80 ++data; |
| 81 --bytes_left; |
| 82 } |
| 83 return 0; |
| 84 } |
| 85 |
| 86 // Remove the byte at |pos| in the |buffer| and close up the gap, moving all the |
| 87 // bytes from [pos + 1, end_pos) to [pos, end_pos - 1). |
| 88 void RemoveByte(uint8_t* buffer, int pos, int end_pos) { |
| 89 memmove(&buffer[pos], &buffer[pos + 1], end_pos - pos - 1); |
| 90 } |
| 91 |
| 92 // Given an Access Unit pointed to by |au| of size |au_size|, removes emulation |
| 93 // prevention 3 bytes (EP3B) from within the |protected_blocks|. Also computes |
| 94 // the |subsamples| vector describing the resulting AU. |
| 95 // Returns the allocated buffer holding the adjusted copy, or NULL if no size |
| 96 // adjustment was necessary. |
| 97 std::unique_ptr<uint8_t[]> AdjustAUForSampleAES( |
| 98 const uint8_t* au, |
| 99 int* au_size, |
| 100 const Ranges<int>& protected_blocks, |
| 101 std::vector<SubsampleEntry>* subsamples) { |
| 102 DCHECK(subsamples); |
| 103 DCHECK(au_size); |
| 104 std::unique_ptr<uint8_t[]> result; |
| 105 int& au_end_pos = *au_size; |
| 106 |
| 107 // 1. Considering each protected block in turn, find any emulation prevention |
| 108 // 3 bytes (EP3B) within it, keeping track of their positions. While doing so, |
| 109 // produce a revised Ranges<int> reflecting the new protected block positions |
| 110 // that will apply after we have removed the EP3Bs. |
| 111 Ranges<int> adjusted_protected_blocks; |
| 112 std::vector<int> epbs; |
| 113 int adjustment = 0; |
| 114 for (size_t i = 0; i < protected_blocks.size(); i++) { |
| 115 int start_pos = protected_blocks.start(i) - adjustment; |
| 116 int end_pos = protected_blocks.end(i) - adjustment; |
| 117 int search_pos = start_pos; |
| 118 int epb_pos; |
| 119 int block_adjustment = 0; |
| 120 while ((epb_pos = FindEP3B(au, search_pos, end_pos))) { |
| 121 epbs.push_back(epb_pos); |
| 122 block_adjustment++; |
| 123 search_pos = epb_pos + 2; |
| 124 } |
| 125 end_pos -= block_adjustment; |
| 126 adjustment += block_adjustment; |
| 127 adjusted_protected_blocks.Add(start_pos, end_pos); |
| 128 } |
| 129 |
| 130 // 2. If we actually found any EP3Bs, make a copy of the AU and then remove |
| 131 // the EP3Bs in the copy (we can't modify the original). |
| 132 if (adjustment) { |
| 133 result.reset(new uint8_t[au_end_pos]); |
| 134 uint8_t* temp = result.get(); |
| 135 memcpy(temp, au, au_end_pos); |
| 136 for (auto epb_pos = epbs.rbegin(); epb_pos != epbs.rend(); ++epb_pos) { |
| 137 RemoveByte(temp, *epb_pos, au_end_pos); |
| 138 au_end_pos--; |
| 139 } |
| 140 au = temp; |
| 141 } |
| 142 |
| 143 // We now have either the original AU, or a copy with the EP3Bs removed. |
| 144 // We also have an updated Ranges<int> indicating the protected blocks. |
| 145 // Also au_end_pos has been adjusted to indicate the new au_size. |
| 146 |
| 147 // 3. Use a new Ranges<int> to collect all the clear ranges. They will |
| 148 // automatically be coalesced to minimize the number of (disjoint) ranges. |
| 149 Ranges<int> clear_ranges; |
| 150 int previous_pos = 0; |
| 151 for (size_t i = 0; i < adjusted_protected_blocks.size(); i++) { |
| 152 int start_pos = adjusted_protected_blocks.start(i); |
| 153 int end_pos = adjusted_protected_blocks.end(i); |
| 154 // Add the clear range prior to this protected block. |
| 155 clear_ranges.Add(previous_pos, start_pos); |
| 156 int block_size = end_pos - start_pos; |
| 157 DCHECK_GT(block_size, kSampleAESMaxUnprotectedNALULength); |
| 158 // Add the clear leader. |
| 159 clear_ranges.Add(start_pos, start_pos + kSampleAESClearLeaderSize); |
| 160 block_size -= kSampleAESClearLeaderSize; |
| 161 // The bytes beyond an integral multiple of AES blocks (16 bytes) are to be |
| 162 // left clear. Also, if the last 16 bytes would be the only block in a |
| 163 // pattern unit (160 bytes), they are also left clear. |
| 164 int residual_bytes = block_size % kSampleAESPatternUnit; |
| 165 if (residual_bytes > 16) |
| 166 residual_bytes = residual_bytes % 16; |
| 167 clear_ranges.Add(end_pos - residual_bytes, end_pos); |
| 168 previous_pos = end_pos; |
| 169 } |
| 170 // Add the trailing bytes, if any, beyond the last protected block. |
| 171 clear_ranges.Add(previous_pos, au_end_pos); |
| 172 |
| 173 // 4. Convert the disjoint set of clear ranges into subsample entries. Each |
| 174 // subsample entry is a count of clear bytes followed by a count of protected |
| 175 // bytes. |
| 176 subsamples->clear(); |
| 177 for (size_t i = 0; i < clear_ranges.size(); i++) { |
| 178 int start_pos = clear_ranges.start(i); |
| 179 int end_pos = clear_ranges.end(i); |
| 180 int clear_size = end_pos - start_pos; |
| 181 int encrypt_end_pos = au_end_pos; |
| 182 |
| 183 if (i + 1 < clear_ranges.size()) |
| 184 encrypt_end_pos = clear_ranges.start(i + 1); |
| 185 SubsampleEntry subsample(clear_size, encrypt_end_pos - end_pos); |
| 186 subsamples->push_back(subsample); |
| 187 } |
| 188 return result; |
| 189 } |
| 190 |
| 191 #endif // BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
54 } // namespace | 192 } // namespace |
55 | 193 |
56 // An AUD NALU is at least 4 bytes: | 194 // An AUD NALU is at least 4 bytes: |
57 // 3 bytes for the start code + 1 byte for the NALU type. | 195 // 3 bytes for the start code + 1 byte for the NALU type. |
58 const int kMinAUDSize = 4; | 196 const int kMinAUDSize = 4; |
59 | 197 |
60 EsParserH264::EsParserH264( | 198 EsParserH264::EsParserH264(const NewVideoConfigCB& new_video_config_cb, |
61 const NewVideoConfigCB& new_video_config_cb, | 199 const EmitBufferCB& emit_buffer_cb) |
62 const EmitBufferCB& emit_buffer_cb) | |
63 : es_adapter_(new_video_config_cb, emit_buffer_cb), | 200 : es_adapter_(new_video_config_cb, emit_buffer_cb), |
64 h264_parser_(new H264Parser()), | 201 h264_parser_(new H264Parser()), |
65 current_access_unit_pos_(0), | 202 current_access_unit_pos_(0), |
66 next_access_unit_pos_(0) { | 203 next_access_unit_pos_(0) |
| 204 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| 205 , |
| 206 use_hls_sample_aes_(false), |
| 207 get_decrypt_config_cb_() |
| 208 #endif |
| 209 { |
67 } | 210 } |
68 | 211 |
| 212 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| 213 EsParserH264::EsParserH264(const NewVideoConfigCB& new_video_config_cb, |
| 214 const EmitBufferCB& emit_buffer_cb, |
| 215 bool use_hls_sample_aes, |
| 216 const GetDecryptConfigCB& get_decrypt_config_cb) |
| 217 : es_adapter_(new_video_config_cb, emit_buffer_cb), |
| 218 h264_parser_(new H264Parser()), |
| 219 current_access_unit_pos_(0), |
| 220 next_access_unit_pos_(0), |
| 221 use_hls_sample_aes_(use_hls_sample_aes), |
| 222 get_decrypt_config_cb_(get_decrypt_config_cb) { |
| 223 DCHECK_EQ(!get_decrypt_config_cb_.is_null(), use_hls_sample_aes_); |
| 224 } |
| 225 #endif |
| 226 |
69 EsParserH264::~EsParserH264() { | 227 EsParserH264::~EsParserH264() { |
70 } | 228 } |
71 | 229 |
72 void EsParserH264::Flush() { | 230 void EsParserH264::Flush() { |
73 DVLOG(1) << __FUNCTION__; | 231 DVLOG(1) << __FUNCTION__; |
74 if (!FindAUD(¤t_access_unit_pos_)) | 232 if (!FindAUD(¤t_access_unit_pos_)) |
75 return; | 233 return; |
76 | 234 |
77 // Simulate an additional AUD to force emitting the last access unit | 235 // Simulate an additional AUD to force emitting the last access unit |
78 // which is assumed to be complete at this point. | 236 // which is assumed to be complete at this point. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 if (h264_parser_->ParseSliceHeader(nalu, &shdr) != H264Parser::kOk) { | 364 if (h264_parser_->ParseSliceHeader(nalu, &shdr) != H264Parser::kOk) { |
207 // Only accept an invalid SPS/PPS at the beginning when the stream | 365 // Only accept an invalid SPS/PPS at the beginning when the stream |
208 // does not necessarily start with an SPS/PPS/IDR. | 366 // does not necessarily start with an SPS/PPS/IDR. |
209 // TODO(damienv): Should be able to differentiate a missing SPS/PPS | 367 // TODO(damienv): Should be able to differentiate a missing SPS/PPS |
210 // from a slice header parsing error. | 368 // from a slice header parsing error. |
211 if (last_video_decoder_config_.IsValidConfig()) | 369 if (last_video_decoder_config_.IsValidConfig()) |
212 return false; | 370 return false; |
213 } else { | 371 } else { |
214 pps_id_for_access_unit = shdr.pic_parameter_set_id; | 372 pps_id_for_access_unit = shdr.pic_parameter_set_id; |
215 } | 373 } |
| 374 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| 375 // With HLS SampleAES, protected blocks in H.264 consist of IDR and non- |
| 376 // IDR slices that are more than 48 bytes in length. |
| 377 if (use_hls_sample_aes_ && |
| 378 nalu.size > kSampleAESMaxUnprotectedNALULength) { |
| 379 int64_t nal_begin = nalu.data - es; |
| 380 protected_blocks_.Add(nal_begin, nal_begin + nalu.size); |
| 381 } |
| 382 #endif |
216 break; | 383 break; |
217 } | 384 } |
218 default: { | 385 default: { |
219 DVLOG(LOG_LEVEL_ES) << "NALU: " << nalu.nal_unit_type; | 386 DVLOG(LOG_LEVEL_ES) << "NALU: " << nalu.nal_unit_type; |
220 } | 387 } |
221 } | 388 } |
222 } | 389 } |
223 | 390 |
224 // Emit a frame and move the stream to the next AUD position. | 391 // Emit a frame and move the stream to the next AUD position. |
225 RCHECK(EmitFrame(current_access_unit_pos_, access_unit_size, | 392 RCHECK(EmitFrame(current_access_unit_pos_, access_unit_size, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 // does not necessarily start with an SPS/PPS/IDR. | 426 // does not necessarily start with an SPS/PPS/IDR. |
260 // In this case, the initial frames are conveyed to the upper layer with | 427 // In this case, the initial frames are conveyed to the upper layer with |
261 // an invalid VideoDecoderConfig and it's up to the upper layer | 428 // an invalid VideoDecoderConfig and it's up to the upper layer |
262 // to process this kind of frame accordingly. | 429 // to process this kind of frame accordingly. |
263 if (last_video_decoder_config_.IsValidConfig()) | 430 if (last_video_decoder_config_.IsValidConfig()) |
264 return false; | 431 return false; |
265 } else { | 432 } else { |
266 const H264SPS* sps = h264_parser_->GetSPS(pps->seq_parameter_set_id); | 433 const H264SPS* sps = h264_parser_->GetSPS(pps->seq_parameter_set_id); |
267 if (!sps) | 434 if (!sps) |
268 return false; | 435 return false; |
269 RCHECK(UpdateVideoDecoderConfig(sps, Unencrypted())); | 436 EncryptionScheme scheme = Unencrypted(); |
| 437 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| 438 if (use_hls_sample_aes_) { |
| 439 // Note that for SampleAES the (encrypt,skip) pattern is constant. |
| 440 scheme = |
| 441 EncryptionScheme(EncryptionScheme::CIPHER_MODE_AES_CBC, |
| 442 EncryptionScheme::Pattern(kSampleAESEncryptBlocks, |
| 443 kSampleAESSkipBlocks)); |
| 444 } |
| 445 #endif |
| 446 RCHECK(UpdateVideoDecoderConfig(sps, scheme)); |
270 } | 447 } |
271 | 448 |
272 // Emit a frame. | 449 // Emit a frame. |
273 DVLOG(LOG_LEVEL_ES) << "Emit frame: stream_pos=" << current_access_unit_pos_ | 450 DVLOG(LOG_LEVEL_ES) << "Emit frame: stream_pos=" << current_access_unit_pos_ |
274 << " size=" << access_unit_size; | 451 << " size=" << access_unit_size; |
275 int es_size; | 452 int es_size; |
276 const uint8_t* es; | 453 const uint8_t* es; |
277 es_queue_->PeekAt(current_access_unit_pos_, &es, &es_size); | 454 es_queue_->PeekAt(current_access_unit_pos_, &es, &es_size); |
278 CHECK_GE(es_size, access_unit_size); | 455 CHECK_GE(es_size, access_unit_size); |
279 | 456 |
| 457 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| 458 std::unique_ptr<uint8_t[]> adjusted_au; |
| 459 std::vector<SubsampleEntry> subsamples; |
| 460 if (use_hls_sample_aes_) { |
| 461 adjusted_au = AdjustAUForSampleAES(es, &access_unit_size, protected_blocks_, |
| 462 &subsamples); |
| 463 protected_blocks_.clear(); |
| 464 if (adjusted_au) |
| 465 es = adjusted_au.get(); |
| 466 } |
| 467 #endif |
| 468 |
280 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId | 469 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId |
281 // type and allow multiple video tracks. See https://crbug.com/341581. | 470 // type and allow multiple video tracks. See https://crbug.com/341581. |
282 scoped_refptr<StreamParserBuffer> stream_parser_buffer = | 471 scoped_refptr<StreamParserBuffer> stream_parser_buffer = |
283 StreamParserBuffer::CopyFrom( | 472 StreamParserBuffer::CopyFrom( |
284 es, | 473 es, |
285 access_unit_size, | 474 access_unit_size, |
286 is_key_frame, | 475 is_key_frame, |
287 DemuxerStream::VIDEO, | 476 DemuxerStream::VIDEO, |
288 0); | 477 0); |
289 stream_parser_buffer->SetDecodeTimestamp(current_timing_desc.dts); | 478 stream_parser_buffer->SetDecodeTimestamp(current_timing_desc.dts); |
290 stream_parser_buffer->set_timestamp(current_timing_desc.pts); | 479 stream_parser_buffer->set_timestamp(current_timing_desc.pts); |
| 480 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| 481 if (use_hls_sample_aes_) { |
| 482 DCHECK(!get_decrypt_config_cb_.is_null()); |
| 483 const DecryptConfig* base_decrypt_config = get_decrypt_config_cb_.Run(); |
| 484 RCHECK(base_decrypt_config); |
| 485 std::unique_ptr<DecryptConfig> decrypt_config(new DecryptConfig( |
| 486 base_decrypt_config->key_id(), base_decrypt_config->iv(), subsamples)); |
| 487 stream_parser_buffer->set_decrypt_config(std::move(decrypt_config)); |
| 488 } |
| 489 #endif |
291 return es_adapter_.OnNewBuffer(stream_parser_buffer); | 490 return es_adapter_.OnNewBuffer(stream_parser_buffer); |
292 } | 491 } |
293 | 492 |
294 bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps, | 493 bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps, |
295 const EncryptionScheme& scheme) { | 494 const EncryptionScheme& scheme) { |
296 // Set the SAR to 1 when not specified in the H264 stream. | 495 // Set the SAR to 1 when not specified in the H264 stream. |
297 int sar_width = (sps->sar_width == 0) ? 1 : sps->sar_width; | 496 int sar_width = (sps->sar_width == 0) ? 1 : sps->sar_width; |
298 int sar_height = (sps->sar_height == 0) ? 1 : sps->sar_height; | 497 int sar_height = (sps->sar_height == 0) ? 1 : sps->sar_height; |
299 | 498 |
300 // TODO(damienv): a MAP unit can be either 16 or 32 pixels. | 499 // TODO(damienv): a MAP unit can be either 16 or 32 pixels. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 << " height=" << sps->sar_height; | 544 << " height=" << sps->sar_height; |
346 last_video_decoder_config_ = video_decoder_config; | 545 last_video_decoder_config_ = video_decoder_config; |
347 es_adapter_.OnConfigChanged(video_decoder_config); | 546 es_adapter_.OnConfigChanged(video_decoder_config); |
348 } | 547 } |
349 | 548 |
350 return true; | 549 return true; |
351 } | 550 } |
352 | 551 |
353 } // namespace mp2t | 552 } // namespace mp2t |
354 } // namespace media | 553 } // namespace media |
OLD | NEW |