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 | 10 |
(...skipping 15 matching lines...) Expand all Loading... | |
26 audio_codec_(kUnknownAudioCodec), | 26 audio_codec_(kUnknownAudioCodec), |
27 channels_(0), | 27 channels_(0), |
28 sample_rate_(0), | 28 sample_rate_(0), |
29 av_sample_format_(0) {} | 29 av_sample_format_(0) {} |
30 | 30 |
31 AudioFileReader::~AudioFileReader() { | 31 AudioFileReader::~AudioFileReader() { |
32 Close(); | 32 Close(); |
33 } | 33 } |
34 | 34 |
35 bool AudioFileReader::Open() { | 35 bool AudioFileReader::Open() { |
36 if (!OpenDemuxer()) | 36 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 } | 37 } |
45 | 38 |
46 bool AudioFileReader::OpenDemuxer() { | 39 bool AudioFileReader::OpenDemuxer() { |
47 glue_.reset(new FFmpegGlue(protocol_)); | 40 glue_.reset(new FFmpegGlue(protocol_)); |
48 AVFormatContext* format_context = glue_->format_context(); | 41 AVFormatContext* format_context = glue_->format_context(); |
49 | 42 |
50 // Open FFmpeg AVFormatContext. | 43 // Open FFmpeg AVFormatContext. |
51 if (!glue_->OpenContext()) { | 44 if (!glue_->OpenContext()) { |
52 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()"; | 45 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()"; |
53 return false; | 46 return false; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
120 } | 113 } |
121 | 114 |
122 // Store initial values to guard against midstream configuration changes. | 115 // Store initial values to guard against midstream configuration changes. |
123 channels_ = codec_context_->channels; | 116 channels_ = codec_context_->channels; |
124 audio_codec_ = CodecIDToAudioCodec(codec_context_->codec_id); | 117 audio_codec_ = CodecIDToAudioCodec(codec_context_->codec_id); |
125 sample_rate_ = codec_context_->sample_rate; | 118 sample_rate_ = codec_context_->sample_rate; |
126 av_sample_format_ = codec_context_->sample_fmt; | 119 av_sample_format_ = codec_context_->sample_fmt; |
127 return true; | 120 return true; |
128 } | 121 } |
129 | 122 |
123 bool AudioFileReader::HasKnownDuration() const { | |
124 return glue_->format_context()->duration != AV_NOPTS_VALUE; | |
125 } | |
126 | |
130 void AudioFileReader::Close() { | 127 void AudioFileReader::Close() { |
131 codec_context_.reset(); | 128 codec_context_.reset(); |
132 glue_.reset(); | 129 glue_.reset(); |
133 } | 130 } |
134 | 131 |
135 int AudioFileReader::Read(AudioBus* audio_bus) { | 132 int AudioFileReader::Read(AudioBus* audio_bus) { |
136 DCHECK(glue_.get() && codec_context_) << | 133 DCHECK(glue_.get() && codec_context_) << |
137 "AudioFileReader::Read() : reader is not opened!"; | 134 "AudioFileReader::Read() : reader is not opened!"; |
138 | 135 |
139 DCHECK_EQ(audio_bus->channels(), channels()); | 136 DCHECK_EQ(audio_bus->channels(), channels()); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 | 240 |
244 // Zero any remaining frames. | 241 // Zero any remaining frames. |
245 audio_bus->ZeroFramesPartial( | 242 audio_bus->ZeroFramesPartial( |
246 current_frame, audio_bus->frames() - current_frame); | 243 current_frame, audio_bus->frames() - current_frame); |
247 | 244 |
248 // Returns the actual number of sample-frames decoded. | 245 // Returns the actual number of sample-frames decoded. |
249 // Ideally this represents the "true" exact length of the file. | 246 // Ideally this represents the "true" exact length of the file. |
250 return current_frame; | 247 return current_frame; |
251 } | 248 } |
252 | 249 |
250 std::unique_ptr<AudioBus> AudioFileReader::StreamingRead() { | |
DaleCurtis
2017/01/25 22:42:25
Needs refactor, so we don't have two copies of the
| |
251 DCHECK(glue_.get() && codec_context_) | |
252 << "AudioFileReader::StreamingRead() : reader is not opened!"; | |
253 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); | |
254 | |
255 // Holds decoded audio. | |
256 std::unique_ptr<AVFrame, ScopedPtrAVFreeFrame> av_frame(av_frame_alloc()); | |
257 | |
258 // Holds a vector of AudioBus' containing each decoded packet. | |
259 std::vector<std::unique_ptr<AudioBus>> decodedAudioPackets; | |
260 | |
261 AVPacket packet; | |
262 int current_frame = 0; | |
263 size_t total_frames = 0; | |
264 bool continue_decoding = true; | |
265 | |
266 while (continue_decoding && ReadPacket(&packet)) { | |
267 // Make a shallow copy of packet so we can slide packet.data as frames are | |
268 // decoded from the packet; otherwise av_packet_unref() will corrupt memory. | |
269 AVPacket packet_temp = packet; | |
270 do { | |
271 // Reset frame to default values. | |
272 av_frame_unref(av_frame.get()); | |
273 | |
274 int frame_decoded = 0; | |
275 int result = avcodec_decode_audio4(codec_context_.get(), av_frame.get(), | |
276 &frame_decoded, &packet_temp); | |
277 | |
278 if (result < 0) { | |
279 DLOG(WARNING) | |
280 << "AudioFileReader::Read() : error in avcodec_decode_audio4() -" | |
281 << result; | |
282 break; | |
283 } | |
284 | |
285 // Update packet size and data pointer in case we need to call the decoder | |
286 // with the remaining bytes from this packet. | |
287 packet_temp.size -= result; | |
288 packet_temp.data += result; | |
289 | |
290 if (!frame_decoded) | |
291 continue; | |
292 | |
293 // Determine the number of sample-frames we just decoded. Check overflow. | |
294 int frames_read = av_frame->nb_samples; | |
295 total_frames += frames_read; | |
296 | |
297 if (frames_read < 0) { | |
298 continue_decoding = false; | |
299 break; | |
300 } | |
301 | |
302 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS | |
303 int channels = | |
304 av_get_channel_layout_nb_channels(av_frame->channel_layout); | |
305 #else | |
306 int channels = av_frame->channels; | |
307 #endif | |
308 if (av_frame->sample_rate != sample_rate_ || channels != channels_ || | |
309 av_frame->format != av_sample_format_) { | |
310 DLOG(ERROR) << "Unsupported midstream configuration change!" | |
311 << " Sample Rate: " << av_frame->sample_rate << " vs " | |
312 << sample_rate_ << ", Channels: " << channels << " vs " | |
313 << channels_ << ", Sample Format: " << av_frame->format | |
314 << " vs " << av_sample_format_; | |
315 | |
316 // This is an unrecoverable error, so bail out. | |
317 continue_decoding = false; | |
318 break; | |
319 } | |
320 | |
321 // Deinterleave each channel and convert to 32bit floating-point with | |
322 // nominal range -1.0 -> +1.0. If the output is already in float planar | |
323 // format, just copy it into the AudioBus. | |
324 std::unique_ptr<AudioBus> audio_bus = | |
325 AudioBus::Create(channels, frames_read); | |
326 | |
327 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) { | |
DaleCurtis
2017/01/25 22:42:25
I believe there's an AudioBus::FromInterleaved met
| |
328 float* decoded_audio_data = reinterpret_cast<float*>(av_frame->data[0]); | |
329 int channels = audio_bus->channels(); | |
330 for (int ch = 0; ch < channels; ++ch) { | |
331 float* bus_data = audio_bus->channel(ch) + current_frame; | |
332 for (int i = 0, offset = ch; i < frames_read; | |
333 ++i, offset += channels) { | |
334 bus_data[i] = decoded_audio_data[offset]; | |
335 } | |
336 } | |
337 } else if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP) { | |
338 for (int ch = 0; ch < audio_bus->channels(); ++ch) { | |
339 memcpy(audio_bus->channel(ch) + current_frame, | |
340 av_frame->extended_data[ch], sizeof(float) * frames_read); | |
341 } | |
342 } else { | |
343 audio_bus->FromInterleavedPartial(av_frame->data[0], current_frame, | |
344 frames_read, bytes_per_sample); | |
345 } | |
346 | |
347 decodedAudioPackets.push_back(std::move(audio_bus)); | |
348 // current_frame += frames_read; | |
349 } while (packet_temp.size > 0); | |
350 av_packet_unref(&packet); | |
351 } | |
352 | |
353 // Concatenate all the decoded chunks into one big bus. | |
354 std::unique_ptr<AudioBus> outputBus = | |
355 AudioBus::Create(channels_, total_frames); | |
356 | |
357 int dest_start_frame = 0; | |
358 for (size_t k = 0; k < decodedAudioPackets.size(); ++k) { | |
359 int frame_count = decodedAudioPackets[k]->frames(); | |
360 decodedAudioPackets[k]->CopyPartialFramesTo( | |
361 0, frame_count, dest_start_frame, outputBus.get()); | |
362 dest_start_frame += frame_count; | |
363 } | |
364 | |
365 return outputBus; | |
366 } | |
367 | |
253 base::TimeDelta AudioFileReader::GetDuration() const { | 368 base::TimeDelta AudioFileReader::GetDuration() const { |
254 const AVRational av_time_base = {1, AV_TIME_BASE}; | 369 const AVRational av_time_base = {1, AV_TIME_BASE}; |
255 | 370 |
256 DCHECK_NE(glue_->format_context()->duration, AV_NOPTS_VALUE); | 371 DCHECK_NE(glue_->format_context()->duration, AV_NOPTS_VALUE); |
257 base::CheckedNumeric<int64_t> estimated_duration_us = | 372 base::CheckedNumeric<int64_t> estimated_duration_us = |
258 glue_->format_context()->duration; | 373 glue_->format_context()->duration; |
259 | 374 |
260 if (audio_codec_ == kCodecAAC) { | 375 if (audio_codec_ == kCodecAAC) { |
261 // For certain AAC-encoded files, FFMPEG's estimated frame count might not | 376 // For certain AAC-encoded files, FFMPEG's estimated frame count might not |
262 // be sufficient to capture the entire audio content that we want. This is | 377 // be sufficient to capture the entire audio content that we want. This is |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 glue_->format_context(), stream_index_, | 425 glue_->format_context(), stream_index_, |
311 ConvertToTimeBase(GetAVStreamForTesting()->time_base, seek_time), | 426 ConvertToTimeBase(GetAVStreamForTesting()->time_base, seek_time), |
312 AVSEEK_FLAG_BACKWARD) >= 0; | 427 AVSEEK_FLAG_BACKWARD) >= 0; |
313 } | 428 } |
314 | 429 |
315 const AVStream* AudioFileReader::GetAVStreamForTesting() const { | 430 const AVStream* AudioFileReader::GetAVStreamForTesting() const { |
316 return glue_->format_context()->streams[stream_index_]; | 431 return glue_->format_context()->streams[stream_index_]; |
317 } | 432 } |
318 | 433 |
319 } // namespace media | 434 } // namespace media |
OLD | NEW |