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 10 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |