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/stream_parser_buffer.h" | 11 #include "media/base/stream_parser_buffer.h" |
11 #include "media/base/timestamp_constants.h" | 12 #include "media/base/timestamp_constants.h" |
12 #include "media/base/video_frame.h" | 13 #include "media/base/video_frame.h" |
13 #include "media/filters/h264_parser.h" | 14 #include "media/filters/h264_parser.h" |
14 #include "media/formats/common/offset_byte_queue.h" | 15 #include "media/formats/common/offset_byte_queue.h" |
15 #include "media/formats/mp2t/mp2t_common.h" | 16 #include "media/formats/mp2t/mp2t_common.h" |
16 #include "ui/gfx/geometry/rect.h" | 17 #include "ui/gfx/geometry/rect.h" |
17 #include "ui/gfx/geometry/size.h" | 18 #include "ui/gfx/geometry/size.h" |
18 | 19 |
19 namespace media { | 20 namespace media { |
20 namespace mp2t { | 21 namespace mp2t { |
21 | 22 |
23 namespace { | |
24 | |
25 #ifdef ENABLE_HLS_SAMPLE_AES | |
26 | |
27 const int kSampleAESMaxUnprotectedNALULength = 48; | |
28 const int kSampleAESClearLeaderSize = 32; | |
29 const int kSampleAESEncryptBlocks = 1; | |
30 const int kSampleAESSkipBlocks = 9; | |
31 | |
32 // Attempts to find the first or only EP3B (emulation prevention 3 byte) in | |
33 // the part of the |buffer| between |start_pos| and |end_pos|. Returns the | |
34 // position of the EP3B, or 0 if there are none. | |
35 // Note: the EP3B always follows two zero bytes, so the value 0 can never be a | |
36 // valid position. | |
37 int FindEP3B(const uint8* buffer, int start_pos, int end_pos) { | |
38 const uint8* data = buffer + start_pos; | |
39 int data_size = end_pos - start_pos; | |
40 DCHECK_GE(data_size, 0); | |
41 int bytes_left = data_size; | |
42 | |
43 while (bytes_left >= 4) { | |
44 if (data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x03 && | |
45 data[3] <= 0x03) { | |
46 return (data - buffer) + 2; | |
47 } | |
48 ++data; | |
49 --bytes_left; | |
50 } | |
51 return 0; | |
52 } | |
53 | |
54 // Remove the byte at |pos| in the |buffer| and close up the gap, moving all the | |
55 // bytes from [pos + 1, end_pos) to [pos, end_pos - 1). | |
56 void RemoveByte(uint8* buffer, int pos, int end_pos) { | |
57 memmove(&buffer[pos], &buffer[pos + 1], end_pos - pos - 1); | |
58 } | |
59 | |
60 // Given an Access Unit pointed to by |au| of size |au_size|, removes emulation | |
61 // prevention 3 bytes (EP3B) from within the |protected_blocks|. Also computes | |
62 // the |subsamples| vector describing the resulting AU. | |
63 // Returns the allocated buffer holding the adjusted copy, or NULL if no size | |
64 // adjustment was necessary. | |
65 scoped_ptr<uint8[]> AdjustAUForSampleAES( | |
66 const uint8* au, | |
67 int* au_size, | |
68 const Ranges<int>& protected_blocks, | |
69 std::vector<SubsampleEntry>* subsamples) { | |
70 DCHECK(subsamples); | |
71 DCHECK(au_size); | |
72 scoped_ptr<uint8[]> result; | |
73 int& au_end_pos = *au_size; | |
74 | |
75 // 1. Considering each protected block in turn, find any emulation prevention | |
76 // 3 bytes (EP3B) within it, keeping track of their positions. While doing so, | |
77 // produce a revised Ranges<int> reflecting the new protected block positions | |
78 // that will apply after we have removed the EP3Bs. | |
79 Ranges<int> adjusted_protected_blocks; | |
80 std::vector<int> epbs; | |
81 int adjustment = 0; | |
82 for (size_t i = 0; i < protected_blocks.size(); i++) { | |
83 int start_pos = protected_blocks.start(i) - adjustment; | |
84 int end_pos = protected_blocks.end(i) - adjustment; | |
85 int search_pos = start_pos; | |
86 int epb_pos; | |
87 int block_adjustment = 0; | |
88 while ((epb_pos = FindEP3B(au, search_pos, end_pos))) { | |
89 epbs.push_back(epb_pos); | |
90 block_adjustment++; | |
91 search_pos = epb_pos + 2; | |
92 } | |
93 end_pos -= block_adjustment; | |
94 adjustment += block_adjustment; | |
95 adjusted_protected_blocks.Add(start_pos, end_pos); | |
96 } | |
97 | |
98 // 2. If we actually found any EP3Bs, make a copy of the AU and then remove | |
99 // the EP3Bs in the copy (we can't modify the original). | |
100 if (adjustment) { | |
101 result.reset(new uint8[au_end_pos]); | |
102 uint8* temp = result.get(); | |
103 memcpy(temp, au, au_end_pos); | |
104 for (auto epb_pos = epbs.rbegin(); epb_pos != epbs.rend(); ++epb_pos) { | |
105 RemoveByte(temp, *epb_pos, au_end_pos); | |
106 au_end_pos--; | |
107 } | |
108 au = temp; | |
109 } | |
110 | |
111 // We now have either the original AU, or a copy with the EP3Bs removed. | |
112 // We also have an updated Ranges<int> indicating the protected blocks. | |
113 // Also au_end_pos has been adjusted to indicate the new au_size. | |
114 | |
115 // 3. Use a new Ranges<int> to collect all the clear ranges. They will | |
116 // automatically be coalesced to minimize the number of (disjoint) ranges. | |
117 Ranges<int> clear_ranges; | |
118 int previous_pos = 0; | |
119 for (size_t i = 0; i < adjusted_protected_blocks.size(); i++) { | |
120 int start_pos = adjusted_protected_blocks.start(i); | |
121 int end_pos = adjusted_protected_blocks.end(i); | |
122 // Add the clear range prior to this protected block. | |
123 clear_ranges.Add(previous_pos, start_pos); | |
124 int block_size = end_pos - start_pos; | |
125 DCHECK_GT(block_size, kSampleAESMaxUnprotectedNALULength); | |
126 // Add the clear leader. | |
127 clear_ranges.Add(start_pos, start_pos + kSampleAESClearLeaderSize); | |
128 block_size -= kSampleAESClearLeaderSize; | |
129 // Add the bytes beyond an integral multiple of AES blocks (16 bytes). | |
130 int residual_bytes = block_size % 16; | |
131 clear_ranges.Add(end_pos - residual_bytes, end_pos); | |
132 previous_pos = end_pos; | |
133 } | |
134 // Add the trailing bytes beyond the last protected block. | |
135 clear_ranges.Add(previous_pos, au_end_pos); | |
136 | |
137 // 4. Convert the disjoint set of clear ranges into subsample entries. Each | |
138 // subsample entry is a count of clear bytes followed by a count of protected | |
139 // bytes. | |
140 subsamples->clear(); | |
141 for (size_t i = 0; i < clear_ranges.size(); i++) { | |
142 int start_pos = clear_ranges.start(i); | |
143 int end_pos = clear_ranges.end(i); | |
144 int clear_size = end_pos - start_pos; | |
145 int encrypt_start_pos = end_pos; | |
146 if (i + 1 < clear_ranges.size()) | |
147 encrypt_start_pos = clear_ranges.start(i + 1); | |
148 SubsampleEntry subsample(clear_size, encrypt_start_pos - end_pos); | |
149 subsamples->push_back(subsample); | |
150 } | |
151 return result.Pass(); | |
152 } | |
153 | |
154 #endif | |
155 } | |
156 | |
22 // An AUD NALU is at least 4 bytes: | 157 // An AUD NALU is at least 4 bytes: |
23 // 3 bytes for the start code + 1 byte for the NALU type. | 158 // 3 bytes for the start code + 1 byte for the NALU type. |
24 const int kMinAUDSize = 4; | 159 const int kMinAUDSize = 4; |
25 | 160 |
26 EsParserH264::EsParserH264( | 161 EsParserH264::EsParserH264(const NewVideoConfigCB& new_video_config_cb, |
27 const NewVideoConfigCB& new_video_config_cb, | 162 const EmitBufferCB& emit_buffer_cb) |
28 const EmitBufferCB& emit_buffer_cb) | |
29 : es_adapter_(new_video_config_cb, emit_buffer_cb), | 163 : es_adapter_(new_video_config_cb, emit_buffer_cb), |
30 h264_parser_(new H264Parser()), | 164 h264_parser_(new H264Parser()), |
31 current_access_unit_pos_(0), | 165 current_access_unit_pos_(0), |
32 next_access_unit_pos_(0) { | 166 next_access_unit_pos_(0) |
167 #ifdef ENABLE_HLS_SAMPLE_AES | |
168 , | |
169 get_decrypt_config_cb_(GetDecryptConfigCB()), | |
yucliu1
2015/12/11 19:55:31
ditto.
dougsteed
2015/12/14 22:51:46
Done.
| |
170 use_hls_sample_aes_(false) | |
171 #endif | |
172 { | |
33 } | 173 } |
34 | 174 |
175 #ifdef ENABLE_HLS_SAMPLE_AES | |
176 EsParserH264::EsParserH264(const NewVideoConfigCB& new_video_config_cb, | |
177 const EmitBufferCB& emit_buffer_cb, | |
178 const GetDecryptConfigCB& get_decrypt_config_cb, | |
179 bool use_hls_sample_aes) | |
180 : es_adapter_(new_video_config_cb, emit_buffer_cb), | |
181 h264_parser_(new H264Parser()), | |
182 current_access_unit_pos_(0), | |
183 next_access_unit_pos_(0), | |
184 get_decrypt_config_cb_(get_decrypt_config_cb), | |
185 use_hls_sample_aes_(use_hls_sample_aes) {} | |
186 #endif | |
187 | |
35 EsParserH264::~EsParserH264() { | 188 EsParserH264::~EsParserH264() { |
36 } | 189 } |
37 | 190 |
38 void EsParserH264::Flush() { | 191 void EsParserH264::Flush() { |
39 DVLOG(1) << __FUNCTION__; | 192 DVLOG(1) << __FUNCTION__; |
40 if (!FindAUD(¤t_access_unit_pos_)) | 193 if (!FindAUD(¤t_access_unit_pos_)) |
41 return; | 194 return; |
42 | 195 |
43 // Simulate an additional AUD to force emitting the last access unit | 196 // Simulate an additional AUD to force emitting the last access unit |
44 // which is assumed to be complete at this point. | 197 // which is assumed to be complete at this point. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
172 if (h264_parser_->ParseSliceHeader(nalu, &shdr) != H264Parser::kOk) { | 325 if (h264_parser_->ParseSliceHeader(nalu, &shdr) != H264Parser::kOk) { |
173 // Only accept an invalid SPS/PPS at the beginning when the stream | 326 // Only accept an invalid SPS/PPS at the beginning when the stream |
174 // does not necessarily start with an SPS/PPS/IDR. | 327 // does not necessarily start with an SPS/PPS/IDR. |
175 // TODO(damienv): Should be able to differentiate a missing SPS/PPS | 328 // TODO(damienv): Should be able to differentiate a missing SPS/PPS |
176 // from a slice header parsing error. | 329 // from a slice header parsing error. |
177 if (last_video_decoder_config_.IsValidConfig()) | 330 if (last_video_decoder_config_.IsValidConfig()) |
178 return false; | 331 return false; |
179 } else { | 332 } else { |
180 pps_id_for_access_unit = shdr.pic_parameter_set_id; | 333 pps_id_for_access_unit = shdr.pic_parameter_set_id; |
181 } | 334 } |
335 #ifdef ENABLE_HLS_SAMPLE_AES | |
336 // With HLS SampleAES, protected blocks in H.264 consist of IDR and non- | |
337 // IDR slices that are more than 48 bytes in length. | |
338 if (use_hls_sample_aes_ && | |
339 nalu.size > kSampleAESMaxUnprotectedNALULength) { | |
340 int64 nal_begin = nalu.data - es; | |
341 protected_blocks_.Add(nal_begin, nal_begin + nalu.size); | |
342 } | |
343 #endif | |
182 break; | 344 break; |
183 } | 345 } |
184 default: { | 346 default: { |
185 DVLOG(LOG_LEVEL_ES) << "NALU: " << nalu.nal_unit_type; | 347 DVLOG(LOG_LEVEL_ES) << "NALU: " << nalu.nal_unit_type; |
186 } | 348 } |
187 } | 349 } |
188 } | 350 } |
189 | 351 |
190 // Emit a frame and move the stream to the next AUD position. | 352 // Emit a frame and move the stream to the next AUD position. |
191 RCHECK(EmitFrame(current_access_unit_pos_, access_unit_size, | 353 RCHECK(EmitFrame(current_access_unit_pos_, access_unit_size, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 // In this case, the initial frames are conveyed to the upper layer with | 386 // In this case, the initial frames are conveyed to the upper layer with |
225 // an invalid VideoDecoderConfig and it's up to the upper layer | 387 // an invalid VideoDecoderConfig and it's up to the upper layer |
226 // to process this kind of frame accordingly. | 388 // to process this kind of frame accordingly. |
227 if (last_video_decoder_config_.IsValidConfig()) | 389 if (last_video_decoder_config_.IsValidConfig()) |
228 return false; | 390 return false; |
229 } else { | 391 } else { |
230 const H264SPS* sps = h264_parser_->GetSPS(pps->seq_parameter_set_id); | 392 const H264SPS* sps = h264_parser_->GetSPS(pps->seq_parameter_set_id); |
231 if (!sps) | 393 if (!sps) |
232 return false; | 394 return false; |
233 EncryptionScheme scheme(false); | 395 EncryptionScheme scheme(false); |
396 #ifdef ENABLE_HLS_SAMPLE_AES | |
397 if (use_hls_sample_aes_) { | |
398 scheme = | |
399 EncryptionScheme(kCipherModeAesCbc, | |
400 EncryptionScheme::PatternSpec( | |
401 kSampleAESEncryptBlocks, kSampleAESSkipBlocks)); | |
yucliu1
2015/12/11 19:55:31
Add a TODO to support arbitrary enrypt:skip patter
dougsteed
2015/12/14 22:51:46
Not needed for HLS SampleAES. But may be needed wh
| |
402 } | |
403 #endif | |
234 RCHECK(UpdateVideoDecoderConfig(sps, scheme)); | 404 RCHECK(UpdateVideoDecoderConfig(sps, scheme)); |
235 } | 405 } |
236 | 406 |
237 // Emit a frame. | 407 // Emit a frame. |
238 DVLOG(LOG_LEVEL_ES) << "Emit frame: stream_pos=" << current_access_unit_pos_ | 408 DVLOG(LOG_LEVEL_ES) << "Emit frame: stream_pos=" << current_access_unit_pos_ |
239 << " size=" << access_unit_size; | 409 << " size=" << access_unit_size; |
240 int es_size; | 410 int es_size; |
241 const uint8* es; | 411 const uint8* es; |
242 es_queue_->PeekAt(current_access_unit_pos_, &es, &es_size); | 412 es_queue_->PeekAt(current_access_unit_pos_, &es, &es_size); |
243 CHECK_GE(es_size, access_unit_size); | 413 CHECK_GE(es_size, access_unit_size); |
244 | 414 |
415 #ifdef ENABLE_HLS_SAMPLE_AES | |
416 scoped_ptr<uint8[]> adjusted_au; | |
417 std::vector<SubsampleEntry> subsamples; | |
418 if (use_hls_sample_aes_) { | |
419 adjusted_au = AdjustAUForSampleAES(es, &access_unit_size, protected_blocks_, | |
420 &subsamples); | |
421 protected_blocks_.clear(); | |
422 if (adjusted_au) | |
423 es = adjusted_au.get(); | |
424 } | |
425 #endif | |
426 | |
245 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId | 427 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId |
246 // type and allow multiple video tracks. See https://crbug.com/341581. | 428 // type and allow multiple video tracks. See https://crbug.com/341581. |
247 scoped_refptr<StreamParserBuffer> stream_parser_buffer = | 429 scoped_refptr<StreamParserBuffer> stream_parser_buffer = |
248 StreamParserBuffer::CopyFrom( | 430 StreamParserBuffer::CopyFrom( |
249 es, | 431 es, |
250 access_unit_size, | 432 access_unit_size, |
251 is_key_frame, | 433 is_key_frame, |
252 DemuxerStream::VIDEO, | 434 DemuxerStream::VIDEO, |
253 0); | 435 0); |
254 stream_parser_buffer->SetDecodeTimestamp(current_timing_desc.dts); | 436 stream_parser_buffer->SetDecodeTimestamp(current_timing_desc.dts); |
255 stream_parser_buffer->set_timestamp(current_timing_desc.pts); | 437 stream_parser_buffer->set_timestamp(current_timing_desc.pts); |
256 #ifdef ENABLE_HLS_SAMPLE_AES | 438 #ifdef ENABLE_HLS_SAMPLE_AES |
257 if (use_hls_sample_aes_) { | 439 if (use_hls_sample_aes_) { |
258 // TODO(dougsteed): temporary place-holders. | 440 DCHECK(!get_decrypt_config_cb_.is_null()); |
259 const std::string key_id = "XXXXXXXXXXXXXXXX"; | 441 const DecryptConfig& base_decrypt_config = get_decrypt_config_cb_.Run(); |
260 const std::string iv = "IVIVIVIVIVIVIVIV"; | 442 scoped_ptr<DecryptConfig> decrypt_config(new DecryptConfig( |
261 scoped_ptr<DecryptConfig> decrypt_config( | 443 base_decrypt_config.key_id(), base_decrypt_config.iv(), subsamples)); |
262 new DecryptConfig(key_id, iv, subsamples)); | |
263 stream_parser_buffer->set_decrypt_config(decrypt_config.Pass()); | 444 stream_parser_buffer->set_decrypt_config(decrypt_config.Pass()); |
264 } | 445 } |
265 #endif | 446 #endif |
266 return es_adapter_.OnNewBuffer(stream_parser_buffer); | 447 return es_adapter_.OnNewBuffer(stream_parser_buffer); |
267 } | 448 } |
268 | 449 |
269 bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps, | 450 bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps, |
270 const EncryptionScheme& scheme) { | 451 const EncryptionScheme& scheme) { |
271 // Set the SAR to 1 when not specified in the H264 stream. | 452 // Set the SAR to 1 when not specified in the H264 stream. |
272 int sar_width = (sps->sar_width == 0) ? 1 : sps->sar_width; | 453 int sar_width = (sps->sar_width == 0) ? 1 : sps->sar_width; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
307 << " height=" << sps->sar_height; | 488 << " height=" << sps->sar_height; |
308 last_video_decoder_config_ = video_decoder_config; | 489 last_video_decoder_config_ = video_decoder_config; |
309 es_adapter_.OnConfigChanged(video_decoder_config); | 490 es_adapter_.OnConfigChanged(video_decoder_config); |
310 } | 491 } |
311 | 492 |
312 return true; | 493 return true; |
313 } | 494 } |
314 | 495 |
315 } // namespace mp2t | 496 } // namespace mp2t |
316 } // namespace media | 497 } // namespace media |
OLD | NEW |