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

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: rebase Created 4 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
« no previous file with comments | « media/formats/mp2t/es_parser_adts.h ('k') | media/formats/mp2t/es_parser_h264.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <stddef.h> 7 #include <stddef.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
(...skipping 10 matching lines...) Expand all
21 #include "media/formats/mpeg/adts_constants.h" 21 #include "media/formats/mpeg/adts_constants.h"
22 22
23 namespace media { 23 namespace media {
24 24
25 static int ExtractAdtsFrameSize(const uint8_t* adts_header) { 25 static int ExtractAdtsFrameSize(const uint8_t* adts_header) {
26 return ((static_cast<int>(adts_header[5]) >> 5) | 26 return ((static_cast<int>(adts_header[5]) >> 5) |
27 (static_cast<int>(adts_header[4]) << 3) | 27 (static_cast<int>(adts_header[4]) << 3) |
28 ((static_cast<int>(adts_header[3]) & 0x3) << 11)); 28 ((static_cast<int>(adts_header[3]) & 0x3) << 11));
29 } 29 }
30 30
31 static int AdtsHeaderSize(const uint8_t* 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
31 // Return true if buf corresponds to an ADTS syncword. 36 // Return true if buf corresponds to an ADTS syncword.
32 // |buf| size must be at least 2. 37 // |buf| size must be at least 2.
33 static bool isAdtsSyncWord(const uint8_t* buf) { 38 static bool isAdtsSyncWord(const uint8_t* buf) {
34 // The first 12 bits must be 1. 39 // The first 12 bits must be 1.
35 // The layer field (2 bits) must be set to 0. 40 // The layer field (2 bits) must be set to 0.
36 return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0); 41 return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0);
37 } 42 }
38 43
39 namespace mp2t { 44 namespace mp2t {
40 45
41 struct EsParserAdts::AdtsFrame { 46 struct EsParserAdts::AdtsFrame {
42 // Pointer to the ES data. 47 // Pointer to the ES data.
43 const uint8_t* data; 48 const uint8_t* data;
44 49
45 // Frame size; 50 // Frame size;
46 int size; 51 int size;
52 int header_size;
47 53
48 // Frame offset in the ES queue. 54 // Frame offset in the ES queue.
49 int64_t queue_offset; 55 int64_t queue_offset;
50 }; 56 };
51 57
52 bool EsParserAdts::LookForAdtsFrame(AdtsFrame* adts_frame) { 58 bool EsParserAdts::LookForAdtsFrame(AdtsFrame* adts_frame) {
53 int es_size; 59 int es_size;
54 const uint8_t* es; 60 const uint8_t* es;
55 es_queue_->Peek(&es, &es_size); 61 es_queue_->Peek(&es, &es_size);
56 62
57 int max_offset = es_size - kADTSHeaderMinSize; 63 int max_offset = es_size - kADTSHeaderMinSize;
58 if (max_offset <= 0) 64 if (max_offset <= 0)
59 return false; 65 return false;
60 66
61 for (int offset = 0; offset < max_offset; offset++) { 67 for (int offset = 0; offset < max_offset; offset++) {
62 const uint8_t* cur_buf = &es[offset]; 68 const uint8_t* cur_buf = &es[offset];
63 if (!isAdtsSyncWord(cur_buf)) 69 if (!isAdtsSyncWord(cur_buf))
64 continue; 70 continue;
65 71
66 int frame_size = ExtractAdtsFrameSize(cur_buf); 72 int frame_size = ExtractAdtsFrameSize(cur_buf);
67 if (frame_size < kADTSHeaderMinSize) { 73 if (frame_size < kADTSHeaderMinSize) {
68 // Too short to be an ADTS frame. 74 // Too short to be an ADTS frame.
69 continue; 75 continue;
70 } 76 }
77 int header_size = AdtsHeaderSize(cur_buf);
71 78
72 int remaining_size = es_size - offset; 79 int remaining_size = es_size - offset;
73 if (remaining_size < frame_size) { 80 if (remaining_size < frame_size) {
74 // Not a full frame: will resume when we have more data. 81 // Not a full frame: will resume when we have more data.
75 es_queue_->Pop(offset); 82 es_queue_->Pop(offset);
76 return false; 83 return false;
77 } 84 }
78 85
79 // Check whether there is another frame 86 // Check whether there is another frame
80 // |size| apart from the current one. 87 // |size| apart from the current one.
81 if (remaining_size >= frame_size + 2 && 88 if (remaining_size >= frame_size + 2 &&
82 !isAdtsSyncWord(&cur_buf[frame_size])) { 89 !isAdtsSyncWord(&cur_buf[frame_size])) {
83 continue; 90 continue;
84 } 91 }
85 92
86 es_queue_->Pop(offset); 93 es_queue_->Pop(offset);
87 es_queue_->Peek(&adts_frame->data, &es_size); 94 es_queue_->Peek(&adts_frame->data, &es_size);
88 adts_frame->queue_offset = es_queue_->head(); 95 adts_frame->queue_offset = es_queue_->head();
89 adts_frame->size = frame_size; 96 adts_frame->size = frame_size;
97 adts_frame->header_size = header_size;
90 DVLOG(LOG_LEVEL_ES) 98 DVLOG(LOG_LEVEL_ES)
91 << "ADTS syncword @ pos=" << adts_frame->queue_offset 99 << "ADTS syncword @ pos=" << adts_frame->queue_offset
92 << " frame_size=" << adts_frame->size; 100 << " frame_size=" << adts_frame->size;
93 DVLOG(LOG_LEVEL_ES) 101 DVLOG(LOG_LEVEL_ES)
94 << "ADTS header: " 102 << "ADTS header: "
95 << base::HexEncode(adts_frame->data, kADTSHeaderMinSize); 103 << base::HexEncode(adts_frame->data, kADTSHeaderMinSize);
96 return true; 104 return true;
97 } 105 }
98 106
99 es_queue_->Pop(max_offset); 107 es_queue_->Pop(max_offset);
100 return false; 108 return false;
101 } 109 }
102 110
103 void EsParserAdts::SkipAdtsFrame(const AdtsFrame& adts_frame) { 111 void EsParserAdts::SkipAdtsFrame(const AdtsFrame& adts_frame) {
104 DCHECK_EQ(adts_frame.queue_offset, es_queue_->head()); 112 DCHECK_EQ(adts_frame.queue_offset, es_queue_->head());
105 es_queue_->Pop(adts_frame.size); 113 es_queue_->Pop(adts_frame.size);
106 } 114 }
107 115
108 EsParserAdts::EsParserAdts( 116 EsParserAdts::EsParserAdts(const NewAudioConfigCB& new_audio_config_cb,
109 const NewAudioConfigCB& new_audio_config_cb, 117 const EmitBufferCB& emit_buffer_cb,
110 const EmitBufferCB& emit_buffer_cb, 118 bool sbr_in_mimetype)
111 bool sbr_in_mimetype) 119 : new_audio_config_cb_(new_audio_config_cb),
112 : new_audio_config_cb_(new_audio_config_cb), 120 emit_buffer_cb_(emit_buffer_cb),
113 emit_buffer_cb_(emit_buffer_cb), 121 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
114 sbr_in_mimetype_(sbr_in_mimetype) { 122 get_decrypt_config_cb_(),
123 use_hls_sample_aes_(false),
124 #endif
125 sbr_in_mimetype_(sbr_in_mimetype) {
115 } 126 }
116 127
128 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
129 EsParserAdts::EsParserAdts(const NewAudioConfigCB& new_audio_config_cb,
130 const EmitBufferCB& emit_buffer_cb,
131 const GetDecryptConfigCB& get_decrypt_config_cb,
132 bool use_hls_sample_aes,
133 bool sbr_in_mimetype)
134 : new_audio_config_cb_(new_audio_config_cb),
135 emit_buffer_cb_(emit_buffer_cb),
136 get_decrypt_config_cb_(get_decrypt_config_cb),
137 use_hls_sample_aes_(use_hls_sample_aes),
138 sbr_in_mimetype_(sbr_in_mimetype) {
139 DCHECK_EQ(!get_decrypt_config_cb_.is_null(), use_hls_sample_aes_);
140 }
141 #endif
142
117 EsParserAdts::~EsParserAdts() { 143 EsParserAdts::~EsParserAdts() {
118 } 144 }
119 145
146 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
147 void EsParserAdts::CalculateSubsamplesForAdtsFrame(
148 const AdtsFrame& adts_frame,
149 std::vector<SubsampleEntry>* subsamples) {
150 DCHECK(subsamples);
151 subsamples->clear();
152 int data_size = adts_frame.size - adts_frame.header_size;
153 int residue = data_size % 16;
154 int clear_bytes = adts_frame.header_size;
155 int encrypted_bytes = 0;
156 if (data_size <= 16) {
157 clear_bytes += data_size;
158 residue = 0;
159 } else {
160 clear_bytes += 16;
161 encrypted_bytes = adts_frame.size - clear_bytes - residue;
162 }
163 SubsampleEntry subsample(clear_bytes, encrypted_bytes);
164 subsamples->push_back(subsample);
165 if (residue) {
166 subsample.clear_bytes = residue;
167 subsample.cypher_bytes = 0;
168 subsamples->push_back(subsample);
169 }
170 }
171 #endif
172
120 bool EsParserAdts::ParseFromEsQueue() { 173 bool EsParserAdts::ParseFromEsQueue() {
121 // Look for every ADTS frame in the ES buffer. 174 // Look for every ADTS frame in the ES buffer.
122 AdtsFrame adts_frame; 175 AdtsFrame adts_frame;
123 while (LookForAdtsFrame(&adts_frame)) { 176 while (LookForAdtsFrame(&adts_frame)) {
124 // Update the audio configuration if needed. 177 // Update the audio configuration if needed.
125 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize); 178 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize);
126 if (!UpdateAudioConfiguration(adts_frame.data, adts_frame.size)) 179 if (!UpdateAudioConfiguration(adts_frame.data, adts_frame.size))
127 return false; 180 return false;
128 181
129 // Get the PTS & the duration of this access unit. 182 // Get the PTS & the duration of this access unit.
(...skipping 17 matching lines...) Expand all
147 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId 200 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId
148 // type and allow multiple audio tracks. See https://crbug.com/341581. 201 // type and allow multiple audio tracks. See https://crbug.com/341581.
149 scoped_refptr<StreamParserBuffer> stream_parser_buffer = 202 scoped_refptr<StreamParserBuffer> stream_parser_buffer =
150 StreamParserBuffer::CopyFrom(adts_frame.data, adts_frame.size, 203 StreamParserBuffer::CopyFrom(adts_frame.data, adts_frame.size,
151 is_key_frame, DemuxerStream::AUDIO, 204 is_key_frame, DemuxerStream::AUDIO,
152 kMp2tAudioTrackId); 205 kMp2tAudioTrackId);
153 stream_parser_buffer->set_timestamp(current_pts); 206 stream_parser_buffer->set_timestamp(current_pts);
154 stream_parser_buffer->SetDecodeTimestamp( 207 stream_parser_buffer->SetDecodeTimestamp(
155 DecodeTimestamp::FromPresentationTime(current_pts)); 208 DecodeTimestamp::FromPresentationTime(current_pts));
156 stream_parser_buffer->set_duration(frame_duration); 209 stream_parser_buffer->set_duration(frame_duration);
210 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
211 if (use_hls_sample_aes_) {
212 const DecryptConfig* base_decrypt_config = get_decrypt_config_cb_.Run();
213 RCHECK(base_decrypt_config);
214 std::vector<SubsampleEntry> subsamples;
215 CalculateSubsamplesForAdtsFrame(adts_frame, &subsamples);
216 std::unique_ptr<DecryptConfig> decrypt_config(
217 new DecryptConfig(base_decrypt_config->key_id(),
218 base_decrypt_config->iv(), subsamples));
219 stream_parser_buffer->set_decrypt_config(std::move(decrypt_config));
220 }
221 #endif
157 emit_buffer_cb_.Run(stream_parser_buffer); 222 emit_buffer_cb_.Run(stream_parser_buffer);
158 223
159 // Update the PTS of the next frame. 224 // Update the PTS of the next frame.
160 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame); 225 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame);
161 226
162 // Skip the current frame. 227 // Skip the current frame.
163 SkipAdtsFrame(adts_frame); 228 SkipAdtsFrame(adts_frame);
164 } 229 }
165 230
166 return true; 231 return true;
(...skipping 17 matching lines...) Expand all
184 return false; 249 return false;
185 } 250 }
186 251
187 // The following code is written according to ISO 14496 Part 3 Table 1.11 and 252 // The following code is written according to ISO 14496 Part 3 Table 1.11 and
188 // Table 1.22. (Table 1.11 refers to the capping to 48000, Table 1.22 refers 253 // Table 1.22. (Table 1.11 refers to the capping to 48000, Table 1.22 refers
189 // to SBR doubling the AAC sample rate.) 254 // to SBR doubling the AAC sample rate.)
190 // TODO(damienv) : Extend sample rate cap to 96kHz for Level 5 content. 255 // TODO(damienv) : Extend sample rate cap to 96kHz for Level 5 content.
191 const int extended_samples_per_second = 256 const int extended_samples_per_second =
192 sbr_in_mimetype_ ? std::min(2 * orig_sample_rate, 48000) 257 sbr_in_mimetype_ ? std::min(2 * orig_sample_rate, 48000)
193 : orig_sample_rate; 258 : orig_sample_rate;
194 259 EncryptionScheme scheme = Unencrypted();
260 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
261 if (use_hls_sample_aes_) {
262 scheme = EncryptionScheme(EncryptionScheme::CIPHER_MODE_AES_CBC,
263 EncryptionScheme::Pattern());
264 }
265 #endif
195 AudioDecoderConfig audio_decoder_config( 266 AudioDecoderConfig audio_decoder_config(
196 kCodecAAC, kSampleFormatS16, channel_layout, extended_samples_per_second, 267 kCodecAAC, kSampleFormatS16, channel_layout, extended_samples_per_second,
197 extra_data, Unencrypted()); 268 extra_data, scheme);
198 269
199 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) { 270 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) {
200 DVLOG(1) << "Sampling frequency: " 271 DVLOG(1) << "Sampling frequency: "
201 << audio_decoder_config.samples_per_second() 272 << audio_decoder_config.samples_per_second()
202 << " SBR=" << sbr_in_mimetype_; 273 << " SBR=" << sbr_in_mimetype_;
203 DVLOG(1) << "Channel layout: " 274 DVLOG(1) << "Channel layout: "
204 << ChannelLayoutToString(audio_decoder_config.channel_layout()); 275 << ChannelLayoutToString(audio_decoder_config.channel_layout());
205 276
206 // For AAC audio with SBR (Spectral Band Replication) the sampling rate is 277 // For AAC audio with SBR (Spectral Band Replication) the sampling rate is
207 // doubled above, but AudioTimestampHelper should still use the original 278 // doubled above, but AudioTimestampHelper should still use the original
(...skipping 11 matching lines...) Expand all
219 // Audio config notification. 290 // Audio config notification.
220 last_audio_decoder_config_ = audio_decoder_config; 291 last_audio_decoder_config_ = audio_decoder_config;
221 new_audio_config_cb_.Run(audio_decoder_config); 292 new_audio_config_cb_.Run(audio_decoder_config);
222 } 293 }
223 294
224 return true; 295 return true;
225 } 296 }
226 297
227 } // namespace mp2t 298 } // namespace mp2t
228 } // namespace media 299 } // namespace media
OLDNEW
« no previous file with comments | « media/formats/mp2t/es_parser_adts.h ('k') | media/formats/mp2t/es_parser_h264.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698