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 |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "media/formats/mpeg/adts_header_parser.h" | 22 #include "media/formats/mpeg/adts_header_parser.h" |
23 | 23 |
24 namespace media { | 24 namespace media { |
25 | 25 |
26 static int ExtractAdtsFrameSize(const uint8_t* adts_header) { | 26 static int ExtractAdtsFrameSize(const uint8_t* adts_header) { |
27 return ((static_cast<int>(adts_header[5]) >> 5) | | 27 return ((static_cast<int>(adts_header[5]) >> 5) | |
28 (static_cast<int>(adts_header[4]) << 3) | | 28 (static_cast<int>(adts_header[4]) << 3) | |
29 ((static_cast<int>(adts_header[3]) & 0x3) << 11)); | 29 ((static_cast<int>(adts_header[3]) & 0x3) << 11)); |
30 } | 30 } |
31 | 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 |
32 // Return true if buf corresponds to an ADTS syncword. | 37 // Return true if buf corresponds to an ADTS syncword. |
33 // |buf| size must be at least 2. | 38 // |buf| size must be at least 2. |
34 static bool isAdtsSyncWord(const uint8_t* buf) { | 39 static bool isAdtsSyncWord(const uint8_t* buf) { |
35 // The first 12 bits must be 1. | 40 // The first 12 bits must be 1. |
36 // The layer field (2 bits) must be set to 0. | 41 // The layer field (2 bits) must be set to 0. |
37 return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0); | 42 return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0); |
38 } | 43 } |
39 | 44 |
40 namespace mp2t { | 45 namespace mp2t { |
41 | 46 |
42 struct EsParserAdts::AdtsFrame { | 47 struct EsParserAdts::AdtsFrame { |
43 // Pointer to the ES data. | 48 // Pointer to the ES data. |
44 const uint8_t* data; | 49 const uint8_t* data; |
45 | 50 |
46 // Frame size; | 51 // Frame size; |
47 int size; | 52 int size; |
| 53 int header_size; |
48 | 54 |
49 // Frame offset in the ES queue. | 55 // Frame offset in the ES queue. |
50 int64_t queue_offset; | 56 int64_t queue_offset; |
51 }; | 57 }; |
52 | 58 |
53 bool EsParserAdts::LookForAdtsFrame(AdtsFrame* adts_frame) { | 59 bool EsParserAdts::LookForAdtsFrame(AdtsFrame* adts_frame) { |
54 int es_size; | 60 int es_size; |
55 const uint8_t* es; | 61 const uint8_t* es; |
56 es_queue_->Peek(&es, &es_size); | 62 es_queue_->Peek(&es, &es_size); |
57 | 63 |
58 int max_offset = es_size - kADTSHeaderMinSize; | 64 int max_offset = es_size - kADTSHeaderMinSize; |
59 if (max_offset <= 0) | 65 if (max_offset <= 0) |
60 return false; | 66 return false; |
61 | 67 |
62 for (int offset = 0; offset < max_offset; offset++) { | 68 for (int offset = 0; offset < max_offset; offset++) { |
63 const uint8_t* cur_buf = &es[offset]; | 69 const uint8_t* cur_buf = &es[offset]; |
64 if (!isAdtsSyncWord(cur_buf)) | 70 if (!isAdtsSyncWord(cur_buf)) |
65 continue; | 71 continue; |
66 | 72 |
67 int frame_size = ExtractAdtsFrameSize(cur_buf); | 73 int frame_size = ExtractAdtsFrameSize(cur_buf); |
68 if (frame_size < kADTSHeaderMinSize) { | 74 if (frame_size < kADTSHeaderMinSize) { |
69 // Too short to be an ADTS frame. | 75 // Too short to be an ADTS frame. |
70 continue; | 76 continue; |
71 } | 77 } |
| 78 int header_size = AdtsHeaderSize(cur_buf); |
72 | 79 |
73 int remaining_size = es_size - offset; | 80 int remaining_size = es_size - offset; |
74 if (remaining_size < frame_size) { | 81 if (remaining_size < frame_size) { |
75 // Not a full frame: will resume when we have more data. | 82 // Not a full frame: will resume when we have more data. |
76 es_queue_->Pop(offset); | 83 es_queue_->Pop(offset); |
77 return false; | 84 return false; |
78 } | 85 } |
79 | 86 |
80 // Check whether there is another frame | 87 // Check whether there is another frame |
81 // |size| apart from the current one. | 88 // |size| apart from the current one. |
82 if (remaining_size >= frame_size + 2 && | 89 if (remaining_size >= frame_size + 2 && |
83 !isAdtsSyncWord(&cur_buf[frame_size])) { | 90 !isAdtsSyncWord(&cur_buf[frame_size])) { |
84 continue; | 91 continue; |
85 } | 92 } |
86 | 93 |
87 es_queue_->Pop(offset); | 94 es_queue_->Pop(offset); |
88 es_queue_->Peek(&adts_frame->data, &es_size); | 95 es_queue_->Peek(&adts_frame->data, &es_size); |
89 adts_frame->queue_offset = es_queue_->head(); | 96 adts_frame->queue_offset = es_queue_->head(); |
90 adts_frame->size = frame_size; | 97 adts_frame->size = frame_size; |
| 98 adts_frame->header_size = header_size; |
91 DVLOG(LOG_LEVEL_ES) | 99 DVLOG(LOG_LEVEL_ES) |
92 << "ADTS syncword @ pos=" << adts_frame->queue_offset | 100 << "ADTS syncword @ pos=" << adts_frame->queue_offset |
93 << " frame_size=" << adts_frame->size; | 101 << " frame_size=" << adts_frame->size; |
94 DVLOG(LOG_LEVEL_ES) | 102 DVLOG(LOG_LEVEL_ES) |
95 << "ADTS header: " | 103 << "ADTS header: " |
96 << base::HexEncode(adts_frame->data, kADTSHeaderMinSize); | 104 << base::HexEncode(adts_frame->data, kADTSHeaderMinSize); |
97 return true; | 105 return true; |
98 } | 106 } |
99 | 107 |
100 es_queue_->Pop(max_offset); | 108 es_queue_->Pop(max_offset); |
101 return false; | 109 return false; |
102 } | 110 } |
103 | 111 |
104 void EsParserAdts::SkipAdtsFrame(const AdtsFrame& adts_frame) { | 112 void EsParserAdts::SkipAdtsFrame(const AdtsFrame& adts_frame) { |
105 DCHECK_EQ(adts_frame.queue_offset, es_queue_->head()); | 113 DCHECK_EQ(adts_frame.queue_offset, es_queue_->head()); |
106 es_queue_->Pop(adts_frame.size); | 114 es_queue_->Pop(adts_frame.size); |
107 } | 115 } |
108 | 116 |
109 EsParserAdts::EsParserAdts( | 117 EsParserAdts::EsParserAdts(const NewAudioConfigCB& new_audio_config_cb, |
110 const NewAudioConfigCB& new_audio_config_cb, | 118 const EmitBufferCB& emit_buffer_cb, |
111 const EmitBufferCB& emit_buffer_cb, | 119 bool sbr_in_mimetype) |
112 bool sbr_in_mimetype) | 120 : new_audio_config_cb_(new_audio_config_cb), |
113 : new_audio_config_cb_(new_audio_config_cb), | 121 emit_buffer_cb_(emit_buffer_cb), |
114 emit_buffer_cb_(emit_buffer_cb), | 122 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
115 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) { |
116 } | 127 } |
117 | 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), |
| 139 sbr_in_mimetype_(sbr_in_mimetype) {} |
| 140 #endif |
| 141 |
118 EsParserAdts::~EsParserAdts() { | 142 EsParserAdts::~EsParserAdts() { |
119 } | 143 } |
120 | 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 |
121 bool EsParserAdts::ParseFromEsQueue() { | 172 bool EsParserAdts::ParseFromEsQueue() { |
122 // Look for every ADTS frame in the ES buffer. | 173 // Look for every ADTS frame in the ES buffer. |
123 AdtsFrame adts_frame; | 174 AdtsFrame adts_frame; |
124 while (LookForAdtsFrame(&adts_frame)) { | 175 while (LookForAdtsFrame(&adts_frame)) { |
125 // Update the audio configuration if needed. | 176 // Update the audio configuration if needed. |
126 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize); | 177 DCHECK_GE(adts_frame.size, kADTSHeaderMinSize); |
127 if (!UpdateAudioConfiguration(adts_frame.data)) | 178 if (!UpdateAudioConfiguration(adts_frame.data)) |
128 return false; | 179 return false; |
129 | 180 |
130 // 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 Loading... |
150 scoped_refptr<StreamParserBuffer> stream_parser_buffer = | 201 scoped_refptr<StreamParserBuffer> stream_parser_buffer = |
151 StreamParserBuffer::CopyFrom( | 202 StreamParserBuffer::CopyFrom( |
152 adts_frame.data, | 203 adts_frame.data, |
153 adts_frame.size, | 204 adts_frame.size, |
154 is_key_frame, | 205 is_key_frame, |
155 DemuxerStream::AUDIO, 0); | 206 DemuxerStream::AUDIO, 0); |
156 stream_parser_buffer->set_timestamp(current_pts); | 207 stream_parser_buffer->set_timestamp(current_pts); |
157 stream_parser_buffer->SetDecodeTimestamp( | 208 stream_parser_buffer->SetDecodeTimestamp( |
158 DecodeTimestamp::FromPresentationTime(current_pts)); | 209 DecodeTimestamp::FromPresentationTime(current_pts)); |
159 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 |
160 emit_buffer_cb_.Run(stream_parser_buffer); | 223 emit_buffer_cb_.Run(stream_parser_buffer); |
161 | 224 |
162 // Update the PTS of the next frame. | 225 // Update the PTS of the next frame. |
163 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame); | 226 audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame); |
164 | 227 |
165 // Skip the current frame. | 228 // Skip the current frame. |
166 SkipAdtsFrame(adts_frame); | 229 SkipAdtsFrame(adts_frame); |
167 } | 230 } |
168 | 231 |
169 return true; | 232 return true; |
170 } | 233 } |
171 | 234 |
172 void EsParserAdts::Flush() { | 235 void EsParserAdts::Flush() { |
173 } | 236 } |
174 | 237 |
175 void EsParserAdts::ResetInternal() { | 238 void EsParserAdts::ResetInternal() { |
176 last_audio_decoder_config_ = AudioDecoderConfig(); | 239 last_audio_decoder_config_ = AudioDecoderConfig(); |
177 } | 240 } |
178 | 241 |
179 bool EsParserAdts::UpdateAudioConfiguration(const uint8_t* adts_header) { | 242 bool EsParserAdts::UpdateAudioConfiguration(const uint8_t* adts_header) { |
180 AudioDecoderConfig audio_decoder_config; | 243 AudioDecoderConfig audio_decoder_config; |
181 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)) |
182 return false; | 253 return false; |
183 | 254 |
184 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) { | 255 if (!audio_decoder_config.Matches(last_audio_decoder_config_)) { |
185 DVLOG(1) << "Sampling frequency: " | 256 DVLOG(1) << "Sampling frequency: " |
186 << audio_decoder_config.samples_per_second(); | 257 << audio_decoder_config.samples_per_second(); |
187 DVLOG(1) << "Channel layout: " | 258 DVLOG(1) << "Channel layout: " |
188 << ChannelLayoutToString(audio_decoder_config.channel_layout()); | 259 << ChannelLayoutToString(audio_decoder_config.channel_layout()); |
189 // Reset the timestamp helper to use a new time scale. | 260 // Reset the timestamp helper to use a new time scale. |
190 if (audio_timestamp_helper_ && | 261 if (audio_timestamp_helper_ && |
191 audio_timestamp_helper_->base_timestamp() != kNoTimestamp()) { | 262 audio_timestamp_helper_->base_timestamp() != kNoTimestamp()) { |
192 base::TimeDelta base_timestamp = audio_timestamp_helper_->GetTimestamp(); | 263 base::TimeDelta base_timestamp = audio_timestamp_helper_->GetTimestamp(); |
193 audio_timestamp_helper_.reset( | 264 audio_timestamp_helper_.reset( |
194 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); | 265 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); |
195 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp); | 266 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp); |
196 } else { | 267 } else { |
197 audio_timestamp_helper_.reset( | 268 audio_timestamp_helper_.reset( |
198 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); | 269 new AudioTimestampHelper(audio_decoder_config.samples_per_second())); |
199 } | 270 } |
200 // Audio config notification. | 271 // Audio config notification. |
201 last_audio_decoder_config_ = audio_decoder_config; | 272 last_audio_decoder_config_ = audio_decoder_config; |
202 new_audio_config_cb_.Run(audio_decoder_config); | 273 new_audio_config_cb_.Run(audio_decoder_config); |
203 } | 274 } |
204 | 275 |
205 return true; | 276 return true; |
206 } | 277 } |
207 | 278 |
208 } // namespace mp2t | 279 } // namespace mp2t |
209 } // namespace media | 280 } // namespace media |
OLD | NEW |