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