Chromium Code Reviews| 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 |