OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/filters/audio_file_reader.h" | 5 #include "media/filters/audio_file_reader.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <cmath> | 9 #include <cmath> |
10 #include <vector> | |
10 | 11 |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/numerics/safe_math.h" | 13 #include "base/numerics/safe_math.h" |
13 #include "base/time/time.h" | 14 #include "base/time/time.h" |
14 #include "media/base/audio_bus.h" | 15 #include "media/base/audio_bus.h" |
16 #include "media/base/audio_sample_types.h" | |
15 #include "media/ffmpeg/ffmpeg_common.h" | 17 #include "media/ffmpeg/ffmpeg_common.h" |
16 | 18 |
17 namespace media { | 19 namespace media { |
18 | 20 |
19 // AAC(M4A) decoding specific constants. | 21 // AAC(M4A) decoding specific constants. |
20 static const int kAACPrimingFrameCount = 2112; | 22 static const int kAACPrimingFrameCount = 2112; |
21 static const int kAACRemainderFrameCount = 519; | 23 static const int kAACRemainderFrameCount = 519; |
22 | 24 |
23 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) | 25 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) |
24 : stream_index_(0), | 26 : stream_index_(0), |
25 protocol_(protocol), | 27 protocol_(protocol), |
26 audio_codec_(kUnknownAudioCodec), | 28 audio_codec_(kUnknownAudioCodec), |
27 channels_(0), | 29 channels_(0), |
28 sample_rate_(0), | 30 sample_rate_(0), |
29 av_sample_format_(0) {} | 31 av_sample_format_(0) {} |
30 | 32 |
31 AudioFileReader::~AudioFileReader() { | 33 AudioFileReader::~AudioFileReader() { |
32 Close(); | 34 Close(); |
33 } | 35 } |
34 | 36 |
35 bool AudioFileReader::Open() { | 37 bool AudioFileReader::Open() { |
36 if (!OpenDemuxer()) | 38 return OpenDemuxer() && OpenDecoder(); |
37 return false; | |
38 if (!OpenDecoder()) | |
39 return false; | |
40 | |
41 // If the duration is unknown, fail out; this API can not work with streams of | |
42 // unknown duration currently. | |
43 return glue_->format_context()->duration != AV_NOPTS_VALUE; | |
44 } | 39 } |
45 | 40 |
46 bool AudioFileReader::OpenDemuxer() { | 41 bool AudioFileReader::OpenDemuxer() { |
47 glue_.reset(new FFmpegGlue(protocol_)); | 42 glue_.reset(new FFmpegGlue(protocol_)); |
48 AVFormatContext* format_context = glue_->format_context(); | 43 AVFormatContext* format_context = glue_->format_context(); |
49 | 44 |
50 // Open FFmpeg AVFormatContext. | 45 // Open FFmpeg AVFormatContext. |
51 if (!glue_->OpenContext()) { | 46 if (!glue_->OpenContext()) { |
52 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()"; | 47 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()"; |
53 return false; | 48 return false; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
120 } | 115 } |
121 | 116 |
122 // Store initial values to guard against midstream configuration changes. | 117 // Store initial values to guard against midstream configuration changes. |
123 channels_ = codec_context_->channels; | 118 channels_ = codec_context_->channels; |
124 audio_codec_ = CodecIDToAudioCodec(codec_context_->codec_id); | 119 audio_codec_ = CodecIDToAudioCodec(codec_context_->codec_id); |
125 sample_rate_ = codec_context_->sample_rate; | 120 sample_rate_ = codec_context_->sample_rate; |
126 av_sample_format_ = codec_context_->sample_fmt; | 121 av_sample_format_ = codec_context_->sample_fmt; |
127 return true; | 122 return true; |
128 } | 123 } |
129 | 124 |
125 bool AudioFileReader::HasKnownDuration() const { | |
126 return glue_->format_context()->duration != AV_NOPTS_VALUE; | |
127 } | |
128 | |
130 void AudioFileReader::Close() { | 129 void AudioFileReader::Close() { |
131 codec_context_.reset(); | 130 codec_context_.reset(); |
132 glue_.reset(); | 131 glue_.reset(); |
133 } | 132 } |
134 | 133 |
134 #if 0 | |
135 int AudioFileReader::Read(AudioBus* audio_bus) { | 135 int AudioFileReader::Read(AudioBus* audio_bus) { |
136 DCHECK(glue_.get() && codec_context_) << | 136 DCHECK(glue_.get() && codec_context_) << |
137 "AudioFileReader::Read() : reader is not opened!"; | 137 "AudioFileReader::Read() : reader is not opened!"; |
138 | 138 |
139 DCHECK_EQ(audio_bus->channels(), channels()); | 139 DCHECK_EQ(audio_bus->channels(), channels()); |
140 if (audio_bus->channels() != channels()) | 140 if (audio_bus->channels() != channels()) |
141 return 0; | 141 return 0; |
142 | 142 |
143 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); | 143 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); |
144 | 144 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
242 } | 242 } |
243 | 243 |
244 // Zero any remaining frames. | 244 // Zero any remaining frames. |
245 audio_bus->ZeroFramesPartial( | 245 audio_bus->ZeroFramesPartial( |
246 current_frame, audio_bus->frames() - current_frame); | 246 current_frame, audio_bus->frames() - current_frame); |
247 | 247 |
248 // Returns the actual number of sample-frames decoded. | 248 // Returns the actual number of sample-frames decoded. |
249 // Ideally this represents the "true" exact length of the file. | 249 // Ideally this represents the "true" exact length of the file. |
250 return current_frame; | 250 return current_frame; |
251 } | 251 } |
252 #endif | |
253 | |
254 int AudioFileReader::Read( | |
255 std::vector<std::unique_ptr<AudioBus>>& decodedAudioPackets) { | |
256 DCHECK(glue_.get() && codec_context_) | |
257 << "AudioFileReader::Read() : reader is not opened!"; | |
258 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); | |
259 | |
260 // Holds decoded audio. | |
261 std::unique_ptr<AVFrame, ScopedPtrAVFreeFrame> av_frame(av_frame_alloc()); | |
262 | |
263 AVPacket packet; | |
264 size_t total_frames = 0; | |
265 bool continue_decoding = true; | |
266 | |
267 while (continue_decoding && ReadPacket(&packet)) { | |
268 // Make a shallow copy of packet so we can slide packet.data as frames are | |
269 // decoded from the packet; otherwise av_packet_unref() will corrupt memory. | |
270 AVPacket packet_temp = packet; | |
271 do { | |
272 // Reset frame to default values. | |
273 av_frame_unref(av_frame.get()); | |
274 | |
275 int frame_decoded = 0; | |
276 int result = avcodec_decode_audio4(codec_context_.get(), av_frame.get(), | |
277 &frame_decoded, &packet_temp); | |
278 | |
279 if (result < 0) { | |
280 DLOG(WARNING) | |
281 << "AudioFileReader::Read() : error in avcodec_decode_audio4() -" | |
282 << result; | |
283 break; | |
Raymond Toy
2017/02/08 21:30:45
This continues the while loop. Is that what we re
DaleCurtis
2017/02/08 21:47:52
Up to you, but we traditionally ignore one-off aud
Raymond Toy
2017/02/08 22:08:35
Thanks. I'll add some comments to this effect so t
| |
284 } | |
285 | |
286 // Update packet size and data pointer in case we need to call the decoder | |
287 // with the remaining bytes from this packet. | |
288 packet_temp.size -= result; | |
289 packet_temp.data += result; | |
290 | |
291 if (!frame_decoded) | |
292 continue; | |
293 | |
294 // Determine the number of sample-frames we just decoded. Check overflow. | |
295 int frames_read = av_frame->nb_samples; | |
296 total_frames += frames_read; | |
297 | |
298 if (frames_read < 0) { | |
299 continue_decoding = false; | |
300 break; | |
301 } | |
302 | |
303 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS | |
304 int channels = | |
305 av_get_channel_layout_nb_channels(av_frame->channel_layout); | |
306 #else | |
307 int channels = av_frame->channels; | |
308 #endif | |
309 if (av_frame->sample_rate != sample_rate_ || channels != channels_ || | |
310 av_frame->format != av_sample_format_) { | |
311 DLOG(ERROR) << "Unsupported midstream configuration change!" | |
312 << " Sample Rate: " << av_frame->sample_rate << " vs " | |
313 << sample_rate_ << ", Channels: " << channels << " vs " | |
314 << channels_ << ", Sample Format: " << av_frame->format | |
315 << " vs " << av_sample_format_; | |
316 | |
317 // This is an unrecoverable error, so bail out. | |
318 continue_decoding = false; | |
319 break; | |
Raymond Toy
2017/02/08 21:30:44
Is the expectation here that we'll just return wha
DaleCurtis
2017/02/08 21:47:52
Yes.
| |
320 } | |
321 | |
322 // Deinterleave each channel and convert to 32bit floating-point with | |
323 // nominal range -1.0 -> +1.0. If the output is already in float planar | |
324 // format, just copy it into the AudioBus. | |
325 std::unique_ptr<AudioBus> audio_bus = | |
326 AudioBus::Create(channels, frames_read); | |
327 | |
328 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) { | |
329 audio_bus->FromInterleaved<Float32SampleTypeTraits>( | |
330 reinterpret_cast<float*>(av_frame->data[0]), frames_read); | |
331 } else if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP) { | |
332 for (int ch = 0; ch < audio_bus->channels(); ++ch) { | |
333 memcpy(audio_bus->channel(ch), av_frame->extended_data[ch], | |
334 sizeof(float) * frames_read); | |
335 } | |
336 } else { | |
337 audio_bus->FromInterleaved(av_frame->data[0], frames_read, | |
338 bytes_per_sample); | |
339 } | |
340 | |
341 decodedAudioPackets.push_back(std::move(audio_bus)); | |
342 } while (packet_temp.size > 0); | |
343 av_packet_unref(&packet); | |
344 } | |
345 | |
346 return total_frames; | |
347 } | |
252 | 348 |
253 base::TimeDelta AudioFileReader::GetDuration() const { | 349 base::TimeDelta AudioFileReader::GetDuration() const { |
254 const AVRational av_time_base = {1, AV_TIME_BASE}; | 350 const AVRational av_time_base = {1, AV_TIME_BASE}; |
255 | 351 |
256 DCHECK_NE(glue_->format_context()->duration, AV_NOPTS_VALUE); | 352 DCHECK_NE(glue_->format_context()->duration, AV_NOPTS_VALUE); |
257 base::CheckedNumeric<int64_t> estimated_duration_us = | 353 base::CheckedNumeric<int64_t> estimated_duration_us = |
258 glue_->format_context()->duration; | 354 glue_->format_context()->duration; |
259 | 355 |
260 if (audio_codec_ == kCodecAAC) { | 356 if (audio_codec_ == kCodecAAC) { |
261 // For certain AAC-encoded files, FFMPEG's estimated frame count might not | 357 // For certain AAC-encoded files, FFMPEG's estimated frame count might not |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 glue_->format_context(), stream_index_, | 406 glue_->format_context(), stream_index_, |
311 ConvertToTimeBase(GetAVStreamForTesting()->time_base, seek_time), | 407 ConvertToTimeBase(GetAVStreamForTesting()->time_base, seek_time), |
312 AVSEEK_FLAG_BACKWARD) >= 0; | 408 AVSEEK_FLAG_BACKWARD) >= 0; |
313 } | 409 } |
314 | 410 |
315 const AVStream* AudioFileReader::GetAVStreamForTesting() const { | 411 const AVStream* AudioFileReader::GetAVStreamForTesting() const { |
316 return glue_->format_context()->streams[stream_index_]; | 412 return glue_->format_context()->streams[stream_index_]; |
317 } | 413 } |
318 | 414 |
319 } // namespace media | 415 } // namespace media |
OLD | NEW |