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

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: move some gn defs Created 4 years, 8 months 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 <stddef.h> 7 #include <stddef.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "media/base/audio_timestamp_helper.h" 13 #include "media/base/audio_timestamp_helper.h"
14 #include "media/base/bit_reader.h" 14 #include "media/base/bit_reader.h"
15 #include "media/base/channel_layout.h" 15 #include "media/base/channel_layout.h"
16 #include "media/base/media_util.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 #include "media/formats/mpeg/adts_header_parser.h" 22 #include "media/formats/mpeg/adts_header_parser.h"
22 23
23 namespace media { 24 namespace media {
24 25
25 static int ExtractAdtsFrameSize(const uint8_t* adts_header) { 26 static int ExtractAdtsFrameSize(const uint8_t* adts_header) {
26 return ((static_cast<int>(adts_header[5]) >> 5) | 27 return ((static_cast<int>(adts_header[5]) >> 5) |
27 (static_cast<int>(adts_header[4]) << 3) | 28 (static_cast<int>(adts_header[4]) << 3) |
28 ((static_cast<int>(adts_header[3]) & 0x3) << 11)); 29 ((static_cast<int>(adts_header[3]) & 0x3) << 11));
29 } 30 }
30 31
32 static int AdtsHeaderSize(const uint8_t* adts_header) {
33 // protection absent bit: set to 1 if there is no CRC and 0 if there is CRC
34 return (adts_header[1] & 0x1) ? kADTSHeaderSizeNoCrc : kADTSHeaderSizeWithCrc;
35 }
36
31 // Return true if buf corresponds to an ADTS syncword. 37 // Return true if buf corresponds to an ADTS syncword.
32 // |buf| size must be at least 2. 38 // |buf| size must be at least 2.
33 static bool isAdtsSyncWord(const uint8_t* buf) { 39 static bool isAdtsSyncWord(const uint8_t* buf) {
34 // The first 12 bits must be 1. 40 // The first 12 bits must be 1.
35 // The layer field (2 bits) must be set to 0. 41 // The layer field (2 bits) must be set to 0.
36 return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0); 42 return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0);
37 } 43 }
38 44
39 namespace mp2t { 45 namespace mp2t {
40 46
41 struct EsParserAdts::AdtsFrame { 47 struct EsParserAdts::AdtsFrame {
42 // Pointer to the ES data. 48 // Pointer to the ES data.
43 const uint8_t* data; 49 const uint8_t* data;
44 50
45 // Frame size; 51 // Frame size;
46 int size; 52 int size;
53 int header_size;
47 54
48 // Frame offset in the ES queue. 55 // Frame offset in the ES queue.
49 int64_t queue_offset; 56 int64_t queue_offset;
50 }; 57 };
51 58
52 bool EsParserAdts::LookForAdtsFrame(AdtsFrame* adts_frame) { 59 bool EsParserAdts::LookForAdtsFrame(AdtsFrame* adts_frame) {
53 int es_size; 60 int es_size;
54 const uint8_t* es; 61 const uint8_t* es;
55 es_queue_->Peek(&es, &es_size); 62 es_queue_->Peek(&es, &es_size);
56 63
57 int max_offset = es_size - kADTSHeaderMinSize; 64 int max_offset = es_size - kADTSHeaderMinSize;
58 if (max_offset <= 0) 65 if (max_offset <= 0)
59 return false; 66 return false;
60 67
61 for (int offset = 0; offset < max_offset; offset++) { 68 for (int offset = 0; offset < max_offset; offset++) {
62 const uint8_t* cur_buf = &es[offset]; 69 const uint8_t* cur_buf = &es[offset];
63 if (!isAdtsSyncWord(cur_buf)) 70 if (!isAdtsSyncWord(cur_buf))
64 continue; 71 continue;
65 72
66 int frame_size = ExtractAdtsFrameSize(cur_buf); 73 int frame_size = ExtractAdtsFrameSize(cur_buf);
67 if (frame_size < kADTSHeaderMinSize) { 74 if (frame_size < kADTSHeaderMinSize) {
68 // Too short to be an ADTS frame. 75 // Too short to be an ADTS frame.
69 continue; 76 continue;
70 } 77 }
78 int header_size = AdtsHeaderSize(cur_buf);
71 79
72 int remaining_size = es_size - offset; 80 int remaining_size = es_size - offset;
73 if (remaining_size < frame_size) { 81 if (remaining_size < frame_size) {
74 // Not a full frame: will resume when we have more data. 82 // Not a full frame: will resume when we have more data.
75 es_queue_->Pop(offset); 83 es_queue_->Pop(offset);
76 return false; 84 return false;
77 } 85 }
78 86
79 // Check whether there is another frame 87 // Check whether there is another frame
80 // |size| apart from the current one. 88 // |size| apart from the current one.
81 if (remaining_size >= frame_size + 2 && 89 if (remaining_size >= frame_size + 2 &&
82 !isAdtsSyncWord(&cur_buf[frame_size])) { 90 !isAdtsSyncWord(&cur_buf[frame_size])) {
83 continue; 91 continue;
84 } 92 }
85 93
86 es_queue_->Pop(offset); 94 es_queue_->Pop(offset);
87 es_queue_->Peek(&adts_frame->data, &es_size); 95 es_queue_->Peek(&adts_frame->data, &es_size);
88 adts_frame->queue_offset = es_queue_->head(); 96 adts_frame->queue_offset = es_queue_->head();
89 adts_frame->size = frame_size; 97 adts_frame->size = frame_size;
98 adts_frame->header_size = header_size;
90 DVLOG(LOG_LEVEL_ES) 99 DVLOG(LOG_LEVEL_ES)
91 << "ADTS syncword @ pos=" << adts_frame->queue_offset 100 << "ADTS syncword @ pos=" << adts_frame->queue_offset
92 << " frame_size=" << adts_frame->size; 101 << " frame_size=" << adts_frame->size;
93 DVLOG(LOG_LEVEL_ES) 102 DVLOG(LOG_LEVEL_ES)
94 << "ADTS header: " 103 << "ADTS header: "
95 << base::HexEncode(adts_frame->data, kADTSHeaderMinSize); 104 << base::HexEncode(adts_frame->data, kADTSHeaderMinSize);
96 return true; 105 return true;
97 } 106 }
98 107
99 es_queue_->Pop(max_offset); 108 es_queue_->Pop(max_offset);
100 return false; 109 return false;
101 } 110 }
102 111
103 void EsParserAdts::SkipAdtsFrame(const AdtsFrame& adts_frame) { 112 void EsParserAdts::SkipAdtsFrame(const AdtsFrame& adts_frame) {
104 DCHECK_EQ(adts_frame.queue_offset, es_queue_->head()); 113 DCHECK_EQ(adts_frame.queue_offset, es_queue_->head());
105 es_queue_->Pop(adts_frame.size); 114 es_queue_->Pop(adts_frame.size);
106 } 115 }
107 116
108 EsParserAdts::EsParserAdts( 117 EsParserAdts::EsParserAdts(const NewAudioConfigCB& new_audio_config_cb,
109 const NewAudioConfigCB& new_audio_config_cb, 118 const EmitBufferCB& emit_buffer_cb,
110 const EmitBufferCB& emit_buffer_cb, 119 bool sbr_in_mimetype)
111 bool sbr_in_mimetype) 120 : new_audio_config_cb_(new_audio_config_cb),
112 : new_audio_config_cb_(new_audio_config_cb), 121 emit_buffer_cb_(emit_buffer_cb),
113 emit_buffer_cb_(emit_buffer_cb), 122 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
114 sbr_in_mimetype_(sbr_in_mimetype) { 123 get_decrypt_config_cb_(),
124 use_hls_sample_aes_(false),
125 #endif
126 sbr_in_mimetype_(sbr_in_mimetype) {
115 } 127 }
116 128
129 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
130 EsParserAdts::EsParserAdts(const NewAudioConfigCB& new_audio_config_cb,
131 const EmitBufferCB& emit_buffer_cb,
132 const GetDecryptConfigCB& get_decrypt_config_cb,
133 bool use_hls_sample_aes,
134 bool sbr_in_mimetype)
135 : new_audio_config_cb_(new_audio_config_cb),
136 emit_buffer_cb_(emit_buffer_cb),
137 get_decrypt_config_cb_(get_decrypt_config_cb),
138 use_hls_sample_aes_(use_hls_sample_aes),
ddorwin 2016/04/12 00:40:47 DCHECK_EQ(get_decrypt_config_cb_, use_hls_sample_a
dougsteed 2016/05/08 23:18:44 Done.
139 sbr_in_mimetype_(sbr_in_mimetype) {}
140 #endif
141
117 EsParserAdts::~EsParserAdts() { 142 EsParserAdts::~EsParserAdts() {
118 } 143 }
119 144
145 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
146 void EsParserAdts::CalculateSubsamplesForAdtsFrame(
147 const AdtsFrame& adts_frame,
148 std::vector<SubsampleEntry>* subsamples) {
149 DCHECK(subsamples);
150 subsamples->clear();
151 int data_size = adts_frame.size - adts_frame.header_size;
152 int residue = data_size % 16;
153 int clear_bytes = adts_frame.header_size;
154 int encrypted_bytes = 0;
155 if (data_size <= 16) {
156 clear_bytes += data_size;
157 residue = 0;
158 } else {
159 clear_bytes += 16;
160 encrypted_bytes = adts_frame.size - clear_bytes - residue;
161 }
162 SubsampleEntry subsample(clear_bytes, encrypted_bytes);
163 subsamples->push_back(subsample);
164 if (residue) {
165 subsample.clear_bytes = residue;
166 subsample.cypher_bytes = 0;
167 subsamples->push_back(subsample);
168 }
169 }
170 #endif
171
120 bool EsParserAdts::ParseFromEsQueue() { 172 bool EsParserAdts::ParseFromEsQueue() {
121 // Look for every ADTS frame in the ES buffer. 173 // Look for every ADTS frame in the ES buffer.
122 AdtsFrame adts_frame; 174 AdtsFrame adts_frame;
123 while (LookForAdtsFrame(&adts_frame)) { 175 while (LookForAdtsFrame(&adts_frame)) {
124 // Update the audio configuration if needed. 176 // Update the audio configuration if needed.
125 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize); 177 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize);
126 if (!UpdateAudioConfiguration(adts_frame.data)) 178 if (!UpdateAudioConfiguration(adts_frame.data))
127 return false; 179 return false;
128 180
129 // Get the PTS & the duration of this access unit. 181 // Get the PTS & the duration of this access unit.
(...skipping 19 matching lines...) Expand all
149 scoped_refptr<StreamParserBuffer> stream_parser_buffer = 201 scoped_refptr<StreamParserBuffer> stream_parser_buffer =
150 StreamParserBuffer::CopyFrom( 202 StreamParserBuffer::CopyFrom(
151 adts_frame.data, 203 adts_frame.data,
152 adts_frame.size, 204 adts_frame.size,
153 is_key_frame, 205 is_key_frame,
154 DemuxerStream::AUDIO, 0); 206 DemuxerStream::AUDIO, 0);
155 stream_parser_buffer->set_timestamp(current_pts); 207 stream_parser_buffer->set_timestamp(current_pts);
156 stream_parser_buffer->SetDecodeTimestamp( 208 stream_parser_buffer->SetDecodeTimestamp(
157 DecodeTimestamp::FromPresentationTime(current_pts)); 209 DecodeTimestamp::FromPresentationTime(current_pts));
158 stream_parser_buffer->set_duration(frame_duration); 210 stream_parser_buffer->set_duration(frame_duration);
211 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
212 if (use_hls_sample_aes_) {
213 const DecryptConfig* base_decrypt_config = get_decrypt_config_cb_.Run();
214 RCHECK(base_decrypt_config);
215 std::vector<SubsampleEntry> subsamples;
216 CalculateSubsamplesForAdtsFrame(adts_frame, &subsamples);
217 scoped_ptr<DecryptConfig> decrypt_config(
218 new DecryptConfig(base_decrypt_config->key_id(),
219 base_decrypt_config->iv(), subsamples));
220 stream_parser_buffer->set_decrypt_config(std::move(decrypt_config));
221 }
222 #endif
159 emit_buffer_cb_.Run(stream_parser_buffer); 223 emit_buffer_cb_.Run(stream_parser_buffer);
160 224
161 // Update the PTS of the next frame. 225 // Update the PTS of the next frame.
162 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame); 226 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame);
163 227
164 // Skip the current frame. 228 // Skip the current frame.
165 SkipAdtsFrame(adts_frame); 229 SkipAdtsFrame(adts_frame);
166 } 230 }
167 231
168 return true; 232 return true;
169 } 233 }
170 234
171 void EsParserAdts::Flush() { 235 void EsParserAdts::Flush() {
172 } 236 }
173 237
174 void EsParserAdts::ResetInternal() { 238 void EsParserAdts::ResetInternal() {
175 last_audio_decoder_config_ = AudioDecoderConfig(); 239 last_audio_decoder_config_ = AudioDecoderConfig();
176 } 240 }
177 241
178 bool EsParserAdts::UpdateAudioConfiguration(const uint8_t* adts_header) { 242 bool EsParserAdts::UpdateAudioConfiguration(const uint8_t* adts_header) {
179 AudioDecoderConfig audio_decoder_config; 243 AudioDecoderConfig audio_decoder_config;
180 if (!ParseAdtsHeader(adts_header, sbr_in_mimetype_, &audio_decoder_config)) 244 EncryptionScheme scheme = Unencrypted();
245 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
246 if (use_hls_sample_aes_) {
247 scheme = EncryptionScheme(EncryptionScheme::CIPHER_MODE_AES_CBC,
248 EncryptionScheme::Pattern());
249 }
250 #endif
251 if (!ParseAdtsHeader(adts_header, sbr_in_mimetype_, scheme,
252 &audio_decoder_config))
181 return false; 253 return false;
182 254
183 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) { 255 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) {
184 DVLOG(1) << "Sampling frequency: " 256 DVLOG(1) << "Sampling frequency: "
185 << audio_decoder_config.samples_per_second(); 257 << audio_decoder_config.samples_per_second();
186 DVLOG(1) << "Channel layout: " 258 DVLOG(1) << "Channel layout: "
187 << ChannelLayoutToString(audio_decoder_config.channel_layout()); 259 << ChannelLayoutToString(audio_decoder_config.channel_layout());
188 // Reset the timestamp helper to use a new time scale. 260 // Reset the timestamp helper to use a new time scale.
189 if (audio_timestamp_helper_ && 261 if (audio_timestamp_helper_ &&
190 audio_timestamp_helper_->base_timestamp() != kNoTimestamp()) { 262 audio_timestamp_helper_->base_timestamp() != kNoTimestamp()) {
191 base::TimeDelta base_timestamp = audio_timestamp_helper_->GetTimestamp(); 263 base::TimeDelta base_timestamp = audio_timestamp_helper_->GetTimestamp();
192 audio_timestamp_helper_.reset( 264 audio_timestamp_helper_.reset(
193 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); 265 new AudioTimestampHelper(audio_decoder_config.samples_per_second()));
194 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp); 266 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp);
195 } else { 267 } else {
196 audio_timestamp_helper_.reset( 268 audio_timestamp_helper_.reset(
197 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); 269 new AudioTimestampHelper(audio_decoder_config.samples_per_second()));
198 } 270 }
199 // Audio config notification. 271 // Audio config notification.
200 last_audio_decoder_config_ = audio_decoder_config; 272 last_audio_decoder_config_ = audio_decoder_config;
201 new_audio_config_cb_.Run(audio_decoder_config); 273 new_audio_config_cb_.Run(audio_decoder_config);
202 } 274 }
203 275
204 return true; 276 return true;
205 } 277 }
206 278
207 } // namespace mp2t 279 } // namespace mp2t
208 } // namespace media 280 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698