| 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 |
| 135 int AudioFileReader::Read(AudioBus* audio_bus) { | 134 int AudioFileReader::Read( |
| 136 DCHECK(glue_.get() && codec_context_) << | 135 std::vector<std::unique_ptr<AudioBus>>* decoded_audio_packets) { |
| 137 "AudioFileReader::Read() : reader is not opened!"; | 136 DCHECK(glue_.get() && codec_context_) |
| 138 | 137 << "AudioFileReader::Read() : reader is not opened!"; |
| 139 DCHECK_EQ(audio_bus->channels(), channels()); | |
| 140 if (audio_bus->channels() != channels()) | |
| 141 return 0; | |
| 142 | |
| 143 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); | 138 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); |
| 144 | 139 |
| 145 // Holds decoded audio. | 140 // Holds decoded audio. |
| 146 std::unique_ptr<AVFrame, ScopedPtrAVFreeFrame> av_frame(av_frame_alloc()); | 141 std::unique_ptr<AVFrame, ScopedPtrAVFreeFrame> av_frame(av_frame_alloc()); |
| 147 | 142 |
| 148 // Read until we hit EOF or we've read the requested number of frames. | |
| 149 AVPacket packet; | 143 AVPacket packet; |
| 150 int current_frame = 0; | 144 int total_frames = 0; |
| 151 bool continue_decoding = true; | 145 bool continue_decoding = true; |
| 152 | 146 |
| 153 while (current_frame < audio_bus->frames() && continue_decoding && | 147 while (continue_decoding && ReadPacket(&packet)) { |
| 154 ReadPacket(&packet)) { | |
| 155 // Make a shallow copy of packet so we can slide packet.data as frames are | 148 // Make a shallow copy of packet so we can slide packet.data as frames are |
| 156 // decoded from the packet; otherwise av_packet_unref() will corrupt memory. | 149 // decoded from the packet; otherwise av_packet_unref() will corrupt memory. |
| 157 AVPacket packet_temp = packet; | 150 AVPacket packet_temp = packet; |
| 158 do { | 151 do { |
| 159 // Reset frame to default values. | 152 // Reset frame to default values. |
| 160 av_frame_unref(av_frame.get()); | 153 av_frame_unref(av_frame.get()); |
| 161 | 154 |
| 162 int frame_decoded = 0; | 155 int frame_decoded = 0; |
| 163 int result = avcodec_decode_audio4(codec_context_.get(), av_frame.get(), | 156 int result = avcodec_decode_audio4(codec_context_.get(), av_frame.get(), |
| 164 &frame_decoded, &packet_temp); | 157 &frame_decoded, &packet_temp); |
| 165 | 158 |
| 166 if (result < 0) { | 159 if (result < 0) { |
| 160 // Unable to decode this current packet. We'll skip it and |
| 161 // continue decoding the next packet. |
| 167 DLOG(WARNING) | 162 DLOG(WARNING) |
| 168 << "AudioFileReader::Read() : error in avcodec_decode_audio4() -" | 163 << "AudioFileReader::Read() : error in avcodec_decode_audio4() -" |
| 169 << result; | 164 << result; |
| 170 break; | 165 break; |
| 171 } | 166 } |
| 172 | 167 |
| 173 // Update packet size and data pointer in case we need to call the decoder | 168 // Update packet size and data pointer in case we need to call the decoder |
| 174 // with the remaining bytes from this packet. | 169 // with the remaining bytes from this packet. |
| 175 packet_temp.size -= result; | 170 packet_temp.size -= result; |
| 176 packet_temp.data += result; | 171 packet_temp.data += result; |
| 177 | 172 |
| 178 if (!frame_decoded) | 173 if (!frame_decoded) |
| 179 continue; | 174 continue; |
| 180 | 175 |
| 181 // Determine the number of sample-frames we just decoded. Check overflow. | 176 // Determine the number of sample-frames we just decoded. Check overflow. |
| 182 int frames_read = av_frame->nb_samples; | 177 int frames_read = av_frame->nb_samples; |
| 183 if (frames_read < 0) { | 178 if (frames_read < 0) { |
| 184 continue_decoding = false; | 179 continue_decoding = false; |
| 185 break; | 180 break; |
| 186 } | 181 } |
| 187 | 182 |
| 188 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS | 183 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS |
| 189 int channels = av_get_channel_layout_nb_channels( | 184 int channels = |
| 190 av_frame->channel_layout); | 185 av_get_channel_layout_nb_channels(av_frame->channel_layout); |
| 191 #else | 186 #else |
| 192 int channels = av_frame->channels; | 187 int channels = av_frame->channels; |
| 193 #endif | 188 #endif |
| 194 if (av_frame->sample_rate != sample_rate_ || | 189 if (av_frame->sample_rate != sample_rate_ || channels != channels_ || |
| 195 channels != channels_ || | |
| 196 av_frame->format != av_sample_format_) { | 190 av_frame->format != av_sample_format_) { |
| 197 DLOG(ERROR) << "Unsupported midstream configuration change!" | 191 DLOG(ERROR) << "Unsupported midstream configuration change!" |
| 198 << " Sample Rate: " << av_frame->sample_rate << " vs " | 192 << " Sample Rate: " << av_frame->sample_rate << " vs " |
| 199 << sample_rate_ | 193 << sample_rate_ << ", Channels: " << channels << " vs " |
| 200 << ", Channels: " << channels << " vs " | 194 << channels_ << ", Sample Format: " << av_frame->format |
| 201 << channels_ | 195 << " vs " << av_sample_format_; |
| 202 << ", Sample Format: " << av_frame->format << " vs " | |
| 203 << av_sample_format_; | |
| 204 | 196 |
| 205 // This is an unrecoverable error, so bail out. | 197 // This is an unrecoverable error, so bail out. We'll return |
| 198 // whatever we've decoded up to this point. |
| 206 continue_decoding = false; | 199 continue_decoding = false; |
| 207 break; | 200 break; |
| 208 } | 201 } |
| 209 | 202 |
| 210 // Truncate, if necessary, if the destination isn't big enough. | |
| 211 if (current_frame + frames_read > audio_bus->frames()) { | |
| 212 DLOG(ERROR) << "Truncating decoded data due to output size."; | |
| 213 frames_read = audio_bus->frames() - current_frame; | |
| 214 } | |
| 215 | |
| 216 // Deinterleave each channel and convert to 32bit floating-point with | 203 // Deinterleave each channel and convert to 32bit floating-point with |
| 217 // nominal range -1.0 -> +1.0. If the output is already in float planar | 204 // nominal range -1.0 -> +1.0. If the output is already in float planar |
| 218 // format, just copy it into the AudioBus. | 205 // format, just copy it into the AudioBus. |
| 206 decoded_audio_packets->emplace_back( |
| 207 AudioBus::Create(channels, frames_read)); |
| 208 AudioBus* audio_bus = decoded_audio_packets->back().get(); |
| 209 |
| 219 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) { | 210 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) { |
| 220 float* decoded_audio_data = reinterpret_cast<float*>(av_frame->data[0]); | 211 audio_bus->FromInterleaved<Float32SampleTypeTraits>( |
| 221 int channels = audio_bus->channels(); | 212 reinterpret_cast<float*>(av_frame->data[0]), frames_read); |
| 222 for (int ch = 0; ch < channels; ++ch) { | |
| 223 float* bus_data = audio_bus->channel(ch) + current_frame; | |
| 224 for (int i = 0, offset = ch; i < frames_read; | |
| 225 ++i, offset += channels) { | |
| 226 bus_data[i] = decoded_audio_data[offset]; | |
| 227 } | |
| 228 } | |
| 229 } else if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP) { | 213 } else if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP) { |
| 230 for (int ch = 0; ch < audio_bus->channels(); ++ch) { | 214 for (int ch = 0; ch < audio_bus->channels(); ++ch) { |
| 231 memcpy(audio_bus->channel(ch) + current_frame, | 215 memcpy(audio_bus->channel(ch), av_frame->extended_data[ch], |
| 232 av_frame->extended_data[ch], sizeof(float) * frames_read); | 216 sizeof(float) * frames_read); |
| 233 } | 217 } |
| 234 } else { | 218 } else { |
| 235 audio_bus->FromInterleavedPartial( | 219 audio_bus->FromInterleaved(av_frame->data[0], frames_read, |
| 236 av_frame->data[0], current_frame, frames_read, bytes_per_sample); | 220 bytes_per_sample); |
| 237 } | 221 } |
| 238 | 222 |
| 239 current_frame += frames_read; | 223 total_frames += frames_read; |
| 240 } while (packet_temp.size > 0); | 224 } while (packet_temp.size > 0); |
| 241 av_packet_unref(&packet); | 225 av_packet_unref(&packet); |
| 242 } | 226 } |
| 243 | 227 |
| 244 // Zero any remaining frames. | 228 return total_frames; |
| 245 audio_bus->ZeroFramesPartial( | |
| 246 current_frame, audio_bus->frames() - current_frame); | |
| 247 | |
| 248 // Returns the actual number of sample-frames decoded. | |
| 249 // Ideally this represents the "true" exact length of the file. | |
| 250 return current_frame; | |
| 251 } | 229 } |
| 252 | 230 |
| 253 base::TimeDelta AudioFileReader::GetDuration() const { | 231 base::TimeDelta AudioFileReader::GetDuration() const { |
| 254 const AVRational av_time_base = {1, AV_TIME_BASE}; | 232 const AVRational av_time_base = {1, AV_TIME_BASE}; |
| 255 | 233 |
| 256 DCHECK_NE(glue_->format_context()->duration, AV_NOPTS_VALUE); | 234 DCHECK_NE(glue_->format_context()->duration, AV_NOPTS_VALUE); |
| 257 base::CheckedNumeric<int64_t> estimated_duration_us = | 235 base::CheckedNumeric<int64_t> estimated_duration_us = |
| 258 glue_->format_context()->duration; | 236 glue_->format_context()->duration; |
| 259 | 237 |
| 260 if (audio_codec_ == kCodecAAC) { | 238 if (audio_codec_ == kCodecAAC) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 glue_->format_context(), stream_index_, | 288 glue_->format_context(), stream_index_, |
| 311 ConvertToTimeBase(GetAVStreamForTesting()->time_base, seek_time), | 289 ConvertToTimeBase(GetAVStreamForTesting()->time_base, seek_time), |
| 312 AVSEEK_FLAG_BACKWARD) >= 0; | 290 AVSEEK_FLAG_BACKWARD) >= 0; |
| 313 } | 291 } |
| 314 | 292 |
| 315 const AVStream* AudioFileReader::GetAVStreamForTesting() const { | 293 const AVStream* AudioFileReader::GetAVStreamForTesting() const { |
| 316 return glue_->format_context()->streams[stream_index_]; | 294 return glue_->format_context()->streams[stream_index_]; |
| 317 } | 295 } |
| 318 | 296 |
| 319 } // namespace media | 297 } // namespace media |
| OLD | NEW |