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_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 use_hls_sample_aes_(false), |
124 get_decrypt_config_cb_(), | |
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 bool sbr_in_mimetype, | |
133 bool use_hls_sample_aes, | |
134 const GetDecryptConfigCB& get_decrypt_config_cb) | |
135 : new_audio_config_cb_(new_audio_config_cb), | |
136 emit_buffer_cb_(emit_buffer_cb), | |
137 use_hls_sample_aes_(use_hls_sample_aes), | |
138 get_decrypt_config_cb_(get_decrypt_config_cb), | |
139 sbr_in_mimetype_(sbr_in_mimetype) { | |
ddorwin
2016/05/18 20:06:51
nit: order
dougsteed
2016/05/26 02:33:15
This reflects the declaration order in the .h file
| |
140 DCHECK_EQ(!get_decrypt_config_cb_.is_null(), use_hls_sample_aes_); | |
141 } | |
142 #endif | |
143 | |
117 EsParserAdts::~EsParserAdts() { | 144 EsParserAdts::~EsParserAdts() { |
118 } | 145 } |
119 | 146 |
147 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) | |
148 void EsParserAdts::CalculateSubsamplesForAdtsFrame( | |
149 const AdtsFrame& adts_frame, | |
150 std::vector<SubsampleEntry>* subsamples) { | |
151 DCHECK(subsamples); | |
152 subsamples->clear(); | |
153 int data_size = adts_frame.size - adts_frame.header_size; | |
154 int residue = data_size % 16; | |
155 int clear_bytes = adts_frame.header_size; | |
156 int encrypted_bytes = 0; | |
157 if (data_size <= 16) { | |
158 clear_bytes += data_size; | |
159 residue = 0; | |
160 } else { | |
161 clear_bytes += 16; | |
162 encrypted_bytes = adts_frame.size - clear_bytes - residue; | |
163 } | |
164 SubsampleEntry subsample(clear_bytes, encrypted_bytes); | |
165 subsamples->push_back(subsample); | |
166 if (residue) { | |
167 subsample.clear_bytes = residue; | |
168 subsample.cypher_bytes = 0; | |
169 subsamples->push_back(subsample); | |
170 } | |
171 } | |
172 #endif | |
173 | |
120 bool EsParserAdts::ParseFromEsQueue() { | 174 bool EsParserAdts::ParseFromEsQueue() { |
121 // Look for every ADTS frame in the ES buffer. | 175 // Look for every ADTS frame in the ES buffer. |
122 AdtsFrame adts_frame; | 176 AdtsFrame adts_frame; |
123 while (LookForAdtsFrame(&adts_frame)) { | 177 while (LookForAdtsFrame(&adts_frame)) { |
124 // Update the audio configuration if needed. | 178 // Update the audio configuration if needed. |
125 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize); | 179 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize); |
126 if (!UpdateAudioConfiguration(adts_frame.data)) | 180 if (!UpdateAudioConfiguration(adts_frame.data)) |
127 return false; | 181 return false; |
128 | 182 |
129 // Get the PTS & the duration of this access unit. | 183 // Get the PTS & the duration of this access unit. |
(...skipping 19 matching lines...) Expand all Loading... | |
149 scoped_refptr<StreamParserBuffer> stream_parser_buffer = | 203 scoped_refptr<StreamParserBuffer> stream_parser_buffer = |
150 StreamParserBuffer::CopyFrom( | 204 StreamParserBuffer::CopyFrom( |
151 adts_frame.data, | 205 adts_frame.data, |
152 adts_frame.size, | 206 adts_frame.size, |
153 is_key_frame, | 207 is_key_frame, |
154 DemuxerStream::AUDIO, 0); | 208 DemuxerStream::AUDIO, 0); |
155 stream_parser_buffer->set_timestamp(current_pts); | 209 stream_parser_buffer->set_timestamp(current_pts); |
156 stream_parser_buffer->SetDecodeTimestamp( | 210 stream_parser_buffer->SetDecodeTimestamp( |
157 DecodeTimestamp::FromPresentationTime(current_pts)); | 211 DecodeTimestamp::FromPresentationTime(current_pts)); |
158 stream_parser_buffer->set_duration(frame_duration); | 212 stream_parser_buffer->set_duration(frame_duration); |
213 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) | |
214 if (use_hls_sample_aes_) { | |
215 const DecryptConfig* base_decrypt_config = get_decrypt_config_cb_.Run(); | |
216 RCHECK(base_decrypt_config); | |
217 std::vector<SubsampleEntry> subsamples; | |
218 CalculateSubsamplesForAdtsFrame(adts_frame, &subsamples); | |
219 std::unique_ptr<DecryptConfig> decrypt_config( | |
220 new DecryptConfig(base_decrypt_config->key_id(), | |
221 base_decrypt_config->iv(), subsamples)); | |
222 stream_parser_buffer->set_decrypt_config(std::move(decrypt_config)); | |
223 } | |
224 #endif | |
159 emit_buffer_cb_.Run(stream_parser_buffer); | 225 emit_buffer_cb_.Run(stream_parser_buffer); |
160 | 226 |
161 // Update the PTS of the next frame. | 227 // Update the PTS of the next frame. |
162 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame); | 228 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame); |
163 | 229 |
164 // Skip the current frame. | 230 // Skip the current frame. |
165 SkipAdtsFrame(adts_frame); | 231 SkipAdtsFrame(adts_frame); |
166 } | 232 } |
167 | 233 |
168 return true; | 234 return true; |
169 } | 235 } |
170 | 236 |
171 void EsParserAdts::Flush() { | 237 void EsParserAdts::Flush() { |
172 } | 238 } |
173 | 239 |
174 void EsParserAdts::ResetInternal() { | 240 void EsParserAdts::ResetInternal() { |
175 last_audio_decoder_config_ = AudioDecoderConfig(); | 241 last_audio_decoder_config_ = AudioDecoderConfig(); |
176 } | 242 } |
177 | 243 |
178 bool EsParserAdts::UpdateAudioConfiguration(const uint8_t* adts_header) { | 244 bool EsParserAdts::UpdateAudioConfiguration(const uint8_t* adts_header) { |
179 AudioDecoderConfig audio_decoder_config; | 245 AudioDecoderConfig audio_decoder_config; |
180 if (!ParseAdtsHeader(adts_header, sbr_in_mimetype_, &audio_decoder_config)) | 246 EncryptionScheme scheme = Unencrypted(); |
247 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) | |
248 if (use_hls_sample_aes_) { | |
249 scheme = EncryptionScheme(EncryptionScheme::CIPHER_MODE_AES_CBC, | |
250 EncryptionScheme::Pattern()); | |
251 } | |
252 #endif | |
253 if (!ParseAdtsHeader(adts_header, sbr_in_mimetype_, scheme, | |
254 &audio_decoder_config)) | |
181 return false; | 255 return false; |
182 | 256 |
183 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) { | 257 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) { |
184 DVLOG(1) << "Sampling frequency: " | 258 DVLOG(1) << "Sampling frequency: " |
185 << audio_decoder_config.samples_per_second(); | 259 << audio_decoder_config.samples_per_second(); |
186 DVLOG(1) << "Channel layout: " | 260 DVLOG(1) << "Channel layout: " |
187 << ChannelLayoutToString(audio_decoder_config.channel_layout()); | 261 << ChannelLayoutToString(audio_decoder_config.channel_layout()); |
188 // Reset the timestamp helper to use a new time scale. | 262 // Reset the timestamp helper to use a new time scale. |
189 if (audio_timestamp_helper_ && | 263 if (audio_timestamp_helper_ && |
190 audio_timestamp_helper_->base_timestamp() != kNoTimestamp()) { | 264 audio_timestamp_helper_->base_timestamp() != kNoTimestamp()) { |
191 base::TimeDelta base_timestamp = audio_timestamp_helper_->GetTimestamp(); | 265 base::TimeDelta base_timestamp = audio_timestamp_helper_->GetTimestamp(); |
192 audio_timestamp_helper_.reset( | 266 audio_timestamp_helper_.reset( |
193 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); | 267 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); |
194 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp); | 268 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp); |
195 } else { | 269 } else { |
196 audio_timestamp_helper_.reset( | 270 audio_timestamp_helper_.reset( |
197 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); | 271 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); |
198 } | 272 } |
199 // Audio config notification. | 273 // Audio config notification. |
200 last_audio_decoder_config_ = audio_decoder_config; | 274 last_audio_decoder_config_ = audio_decoder_config; |
201 new_audio_config_cb_.Run(audio_decoder_config); | 275 new_audio_config_cb_.Run(audio_decoder_config); |
202 } | 276 } |
203 | 277 |
204 return true; | 278 return true; |
205 } | 279 } |
206 | 280 |
207 } // namespace mp2t | 281 } // namespace mp2t |
208 } // namespace media | 282 } // namespace media |
OLD | NEW |