Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: media/formats/mp2t/es_parser_adts.cc

Issue 1517473002: Support HLS MPEG2 TS with SAMPLE-AES encryption. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@encryption_scheme
Patch Set: remove test data Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_adts.h" 5 #include "media/formats/mp2t/es_parser_adts.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "media/base/audio_timestamp_helper.h" 12 #include "media/base/audio_timestamp_helper.h"
13 #include "media/base/bit_reader.h" 13 #include "media/base/bit_reader.h"
14 #include "media/base/channel_layout.h" 14 #include "media/base/channel_layout.h"
15 #include "media/base/decrypt_config.h"
15 #include "media/base/encryption_scheme.h" 16 #include "media/base/encryption_scheme.h"
16 #include "media/base/stream_parser_buffer.h" 17 #include "media/base/stream_parser_buffer.h"
17 #include "media/base/timestamp_constants.h" 18 #include "media/base/timestamp_constants.h"
18 #include "media/formats/common/offset_byte_queue.h" 19 #include "media/formats/common/offset_byte_queue.h"
19 #include "media/formats/mp2t/mp2t_common.h" 20 #include "media/formats/mp2t/mp2t_common.h"
20 #include "media/formats/mpeg/adts_constants.h" 21 #include "media/formats/mpeg/adts_constants.h"
21 22
22 namespace media { 23 namespace media {
23 24
24 static int ExtractAdtsFrameSize(const uint8* adts_header) { 25 static int ExtractAdtsFrameSize(const uint8* adts_header) {
25 return ((static_cast<int>(adts_header[5]) >> 5) | 26 return ((static_cast<int>(adts_header[5]) >> 5) |
26 (static_cast<int>(adts_header[4]) << 3) | 27 (static_cast<int>(adts_header[4]) << 3) |
27 ((static_cast<int>(adts_header[3]) & 0x3) << 11)); 28 ((static_cast<int>(adts_header[3]) & 0x3) << 11));
28 } 29 }
29 30
31 static int AdtsHeaderSize(const uint8* adts_header) {
32 // protection absent bit: set to 1 if there is no CRC and 0 if there is CRC
33 return (adts_header[1] & 0x1) ? kADTSHeaderSizeNoCrc : kADTSHeaderSizeWithCrc;
34 }
35
30 static size_t ExtractAdtsFrequencyIndex(const uint8* adts_header) { 36 static size_t ExtractAdtsFrequencyIndex(const uint8* adts_header) {
31 return ((adts_header[2] >> 2) & 0xf); 37 return ((adts_header[2] >> 2) & 0xf);
32 } 38 }
33 39
34 static size_t ExtractAdtsChannelConfig(const uint8* adts_header) { 40 static size_t ExtractAdtsChannelConfig(const uint8* adts_header) {
35 return (((adts_header[3] >> 6) & 0x3) | 41 return (((adts_header[3] >> 6) & 0x3) |
36 ((adts_header[2] & 0x1) << 2)); 42 ((adts_header[2] & 0x1) << 2));
37 } 43 }
38 44
39 // Return true if buf corresponds to an ADTS syncword. 45 // Return true if buf corresponds to an ADTS syncword.
40 // |buf| size must be at least 2. 46 // |buf| size must be at least 2.
41 static bool isAdtsSyncWord(const uint8* buf) { 47 static bool isAdtsSyncWord(const uint8* buf) {
42 // The first 12 bits must be 1. 48 // The first 12 bits must be 1.
43 // The layer field (2 bits) must be set to 0. 49 // The layer field (2 bits) must be set to 0.
44 return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0); 50 return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0);
45 } 51 }
46 52
47 namespace mp2t { 53 namespace mp2t {
48 54
49 struct EsParserAdts::AdtsFrame { 55 struct EsParserAdts::AdtsFrame {
50 // Pointer to the ES data. 56 // Pointer to the ES data.
51 const uint8* data; 57 const uint8* data;
52 58
53 // Frame size; 59 // Frame size;
54 int size; 60 int size;
61 int header_size;
55 62
56 // Frame offset in the ES queue. 63 // Frame offset in the ES queue.
57 int64 queue_offset; 64 int64 queue_offset;
58 }; 65 };
59 66
60 bool EsParserAdts::LookForAdtsFrame(AdtsFrame* adts_frame) { 67 bool EsParserAdts::LookForAdtsFrame(AdtsFrame* adts_frame) {
61 int es_size; 68 int es_size;
62 const uint8* es; 69 const uint8* es;
63 es_queue_->Peek(&es, &es_size); 70 es_queue_->Peek(&es, &es_size);
64 71
65 int max_offset = es_size - kADTSHeaderMinSize; 72 int max_offset = es_size - kADTSHeaderMinSize;
66 if (max_offset <= 0) 73 if (max_offset <= 0)
67 return false; 74 return false;
68 75
69 for (int offset = 0; offset < max_offset; offset++) { 76 for (int offset = 0; offset < max_offset; offset++) {
70 const uint8* cur_buf = &es[offset]; 77 const uint8* cur_buf = &es[offset];
71 if (!isAdtsSyncWord(cur_buf)) 78 if (!isAdtsSyncWord(cur_buf))
72 continue; 79 continue;
73 80
74 int frame_size = ExtractAdtsFrameSize(cur_buf); 81 int frame_size = ExtractAdtsFrameSize(cur_buf);
75 if (frame_size < kADTSHeaderMinSize) { 82 if (frame_size < kADTSHeaderMinSize) {
76 // Too short to be an ADTS frame. 83 // Too short to be an ADTS frame.
77 continue; 84 continue;
78 } 85 }
86 int header_size = AdtsHeaderSize(cur_buf);
79 87
80 int remaining_size = es_size - offset; 88 int remaining_size = es_size - offset;
81 if (remaining_size < frame_size) { 89 if (remaining_size < frame_size) {
82 // Not a full frame: will resume when we have more data. 90 // Not a full frame: will resume when we have more data.
83 es_queue_->Pop(offset); 91 es_queue_->Pop(offset);
84 return false; 92 return false;
85 } 93 }
86 94
87 // Check whether there is another frame 95 // Check whether there is another frame
88 // |size| apart from the current one. 96 // |size| apart from the current one.
89 if (remaining_size >= frame_size + 2 && 97 if (remaining_size >= frame_size + 2 &&
90 !isAdtsSyncWord(&cur_buf[frame_size])) { 98 !isAdtsSyncWord(&cur_buf[frame_size])) {
91 continue; 99 continue;
92 } 100 }
93 101
94 es_queue_->Pop(offset); 102 es_queue_->Pop(offset);
95 es_queue_->Peek(&adts_frame->data, &es_size); 103 es_queue_->Peek(&adts_frame->data, &es_size);
96 adts_frame->queue_offset = es_queue_->head(); 104 adts_frame->queue_offset = es_queue_->head();
97 adts_frame->size = frame_size; 105 adts_frame->size = frame_size;
106 adts_frame->header_size = header_size;
98 DVLOG(LOG_LEVEL_ES) 107 DVLOG(LOG_LEVEL_ES)
99 << "ADTS syncword @ pos=" << adts_frame->queue_offset 108 << "ADTS syncword @ pos=" << adts_frame->queue_offset
100 << " frame_size=" << adts_frame->size; 109 << " frame_size=" << adts_frame->size;
101 DVLOG(LOG_LEVEL_ES) 110 DVLOG(LOG_LEVEL_ES)
102 << "ADTS header: " 111 << "ADTS header: "
103 << base::HexEncode(adts_frame->data, kADTSHeaderMinSize); 112 << base::HexEncode(adts_frame->data, kADTSHeaderMinSize);
104 return true; 113 return true;
105 } 114 }
106 115
107 es_queue_->Pop(max_offset); 116 es_queue_->Pop(max_offset);
108 return false; 117 return false;
109 } 118 }
110 119
111 void EsParserAdts::SkipAdtsFrame(const AdtsFrame& adts_frame) { 120 void EsParserAdts::SkipAdtsFrame(const AdtsFrame& adts_frame) {
112 DCHECK_EQ(adts_frame.queue_offset, es_queue_->head()); 121 DCHECK_EQ(adts_frame.queue_offset, es_queue_->head());
113 es_queue_->Pop(adts_frame.size); 122 es_queue_->Pop(adts_frame.size);
114 } 123 }
115 124
116 EsParserAdts::EsParserAdts( 125 EsParserAdts::EsParserAdts(const NewAudioConfigCB& new_audio_config_cb,
117 const NewAudioConfigCB& new_audio_config_cb, 126 const EmitBufferCB& emit_buffer_cb,
118 const EmitBufferCB& emit_buffer_cb, 127 bool sbr_in_mimetype)
119 bool sbr_in_mimetype) 128 : new_audio_config_cb_(new_audio_config_cb),
120 : new_audio_config_cb_(new_audio_config_cb), 129 emit_buffer_cb_(emit_buffer_cb),
121 emit_buffer_cb_(emit_buffer_cb), 130 #ifdef ENABLE_HLS_SAMPLE_AES
122 sbr_in_mimetype_(sbr_in_mimetype) { 131 get_decrypt_config_cb_(GetDecryptConfigCB()),
yucliu1 2015/12/11 19:55:31 Maybe simply get_decrypt_config_cb_()?
dougsteed 2015/12/14 22:51:46 Done.
132 use_hls_sample_aes_(false),
133 #endif
134 sbr_in_mimetype_(sbr_in_mimetype) {
123 } 135 }
124 136
137 #ifdef ENABLE_HLS_SAMPLE_AES
138 EsParserAdts::EsParserAdts(const NewAudioConfigCB& new_audio_config_cb,
139 const EmitBufferCB& emit_buffer_cb,
140 const GetDecryptConfigCB get_decrypt_config_cb,
yucliu1 2015/12/11 19:55:31 const GetDecryptConfigCB&
dougsteed 2015/12/14 22:51:46 Done.
141 bool use_hls_sample_aes,
142 bool sbr_in_mimetype)
143 : new_audio_config_cb_(new_audio_config_cb),
144 emit_buffer_cb_(emit_buffer_cb),
145 get_decrypt_config_cb_(get_decrypt_config_cb),
146 use_hls_sample_aes_(use_hls_sample_aes),
147 sbr_in_mimetype_(sbr_in_mimetype) {}
148 #endif
149
125 EsParserAdts::~EsParserAdts() { 150 EsParserAdts::~EsParserAdts() {
126 } 151 }
127 152
153 #ifdef ENABLE_HLS_SAMPLE_AES
154 void EsParserAdts::CalculateSubsamplesForAdtsFrame(
155 const AdtsFrame& adts_frame,
156 std::vector<SubsampleEntry>* subsamples) {
157 DCHECK(subsamples);
158 subsamples->clear();
159 int data_size = adts_frame.size - adts_frame.header_size;
160 int residue = data_size % 16;
161 int clear_bytes = adts_frame.header_size;
162 int encrypted_bytes = 0;
163 if (data_size <= 16) {
164 clear_bytes += data_size;
165 residue = 0;
166 } else {
167 clear_bytes += 16;
168 encrypted_bytes = adts_frame.size - clear_bytes - residue;
169 }
170 SubsampleEntry subsample(clear_bytes, encrypted_bytes);
171 subsamples->push_back(subsample);
172 if (residue) {
173 subsample.clear_bytes = residue;
174 subsample.cypher_bytes = 0;
175 subsamples->push_back(subsample);
176 }
177 }
178 #endif
179
128 bool EsParserAdts::ParseFromEsQueue() { 180 bool EsParserAdts::ParseFromEsQueue() {
129 // Look for every ADTS frame in the ES buffer. 181 // Look for every ADTS frame in the ES buffer.
130 AdtsFrame adts_frame; 182 AdtsFrame adts_frame;
131 while (LookForAdtsFrame(&adts_frame)) { 183 while (LookForAdtsFrame(&adts_frame)) {
132 // Update the audio configuration if needed. 184 // Update the audio configuration if needed.
133 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize); 185 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize);
134 if (!UpdateAudioConfiguration(adts_frame.data)) 186 if (!UpdateAudioConfiguration(adts_frame.data))
135 return false; 187 return false;
136 188
137 // Get the PTS & the duration of this access unit. 189 // Get the PTS & the duration of this access unit.
(...skipping 19 matching lines...) Expand all
157 scoped_refptr<StreamParserBuffer> stream_parser_buffer = 209 scoped_refptr<StreamParserBuffer> stream_parser_buffer =
158 StreamParserBuffer::CopyFrom( 210 StreamParserBuffer::CopyFrom(
159 adts_frame.data, 211 adts_frame.data,
160 adts_frame.size, 212 adts_frame.size,
161 is_key_frame, 213 is_key_frame,
162 DemuxerStream::AUDIO, 0); 214 DemuxerStream::AUDIO, 0);
163 stream_parser_buffer->set_timestamp(current_pts); 215 stream_parser_buffer->set_timestamp(current_pts);
164 stream_parser_buffer->SetDecodeTimestamp( 216 stream_parser_buffer->SetDecodeTimestamp(
165 DecodeTimestamp::FromPresentationTime(current_pts)); 217 DecodeTimestamp::FromPresentationTime(current_pts));
166 stream_parser_buffer->set_duration(frame_duration); 218 stream_parser_buffer->set_duration(frame_duration);
219 #ifdef ENABLE_HLS_SAMPLE_AES
220 if (use_hls_sample_aes_) {
221 const DecryptConfig& base_decrypt_config = get_decrypt_config_cb_.Run();
222 std::vector<SubsampleEntry> subsamples;
223 CalculateSubsamplesForAdtsFrame(adts_frame, &subsamples);
224 scoped_ptr<DecryptConfig> decrypt_config(new DecryptConfig(
225 base_decrypt_config.key_id(), base_decrypt_config.iv(), subsamples));
226 stream_parser_buffer->set_decrypt_config(decrypt_config.Pass());
227 }
228 #endif
167 emit_buffer_cb_.Run(stream_parser_buffer); 229 emit_buffer_cb_.Run(stream_parser_buffer);
168 230
169 // Update the PTS of the next frame. 231 // Update the PTS of the next frame.
170 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame); 232 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame);
171 233
172 // Skip the current frame. 234 // Skip the current frame.
173 SkipAdtsFrame(adts_frame); 235 SkipAdtsFrame(adts_frame);
174 } 236 }
175 237
176 return true; 238 return true;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 ((adts_profile + 1) << 11) + 282 ((adts_profile + 1) << 11) +
221 // frequency_index is [0..13], per early out above. 283 // frequency_index is [0..13], per early out above.
222 (frequency_index << 7) + 284 (frequency_index << 7) +
223 // channel_configuration is [0..7], per early out above. 285 // channel_configuration is [0..7], per early out above.
224 (channel_configuration << 3)); 286 (channel_configuration << 3));
225 std::vector<uint8_t> extra_data; 287 std::vector<uint8_t> extra_data;
226 extra_data.push_back(static_cast<uint8>(extra_data_int >> 8)); 288 extra_data.push_back(static_cast<uint8>(extra_data_int >> 8));
227 extra_data.push_back(static_cast<uint8>(extra_data_int & 0xff)); 289 extra_data.push_back(static_cast<uint8>(extra_data_int & 0xff));
228 290
229 EncryptionScheme scheme(false); 291 EncryptionScheme scheme(false);
230 292 #ifdef ENABLE_HLS_SAMPLE_AES
293 if (use_hls_sample_aes_) {
294 scheme = EncryptionScheme(kCipherModeAesCbc);
295 }
296 #endif
231 AudioDecoderConfig audio_decoder_config( 297 AudioDecoderConfig audio_decoder_config(
232 kCodecAAC, kSampleFormatS16, 298 kCodecAAC, kSampleFormatS16,
233 kADTSChannelLayoutTable[channel_configuration], 299 kADTSChannelLayoutTable[channel_configuration],
234 extended_samples_per_second, extra_data, scheme); 300 extended_samples_per_second, extra_data, scheme);
235 301
236 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) { 302 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) {
237 DVLOG(1) << "Sampling frequency: " << samples_per_second; 303 DVLOG(1) << "Sampling frequency: " << samples_per_second;
238 DVLOG(1) << "Extended sampling frequency: " << extended_samples_per_second; 304 DVLOG(1) << "Extended sampling frequency: " << extended_samples_per_second;
239 DVLOG(1) << "Channel config: " << channel_configuration; 305 DVLOG(1) << "Channel config: " << channel_configuration;
240 DVLOG(1) << "Adts profile: " << adts_profile; 306 DVLOG(1) << "Adts profile: " << adts_profile;
(...skipping 11 matching lines...) Expand all
252 // Audio config notification. 318 // Audio config notification.
253 last_audio_decoder_config_ = audio_decoder_config; 319 last_audio_decoder_config_ = audio_decoder_config;
254 new_audio_config_cb_.Run(audio_decoder_config); 320 new_audio_config_cb_.Run(audio_decoder_config);
255 } 321 }
256 322
257 return true; 323 return true;
258 } 324 }
259 325
260 } // namespace mp2t 326 } // namespace mp2t
261 } // namespace media 327 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698