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 "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/time.h" | 8 #include "base/time.h" |
9 #include "media/base/audio_bus.h" | 9 #include "media/base/audio_bus.h" |
10 #include "media/ffmpeg/ffmpeg_common.h" | 10 #include "media/ffmpeg/ffmpeg_common.h" |
11 #include "media/filters/ffmpeg_glue.h" | 11 #include "media/filters/ffmpeg_glue.h" |
12 | 12 |
13 namespace media { | 13 namespace media { |
14 | 14 |
15 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) | 15 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) |
16 : codec_context_(NULL), | 16 : codec_context_(NULL), |
17 stream_index_(0), | 17 stream_index_(0), |
18 protocol_(protocol) { | 18 protocol_(protocol), |
19 channels_(0), | |
20 sample_rate_(0), | |
21 av_sample_format_(0) { | |
19 } | 22 } |
20 | 23 |
21 AudioFileReader::~AudioFileReader() { | 24 AudioFileReader::~AudioFileReader() { |
22 Close(); | 25 Close(); |
23 } | 26 } |
24 | 27 |
25 int AudioFileReader::channels() const { | |
26 return codec_context_->channels; | |
27 } | |
28 | |
29 int AudioFileReader::sample_rate() const { | |
30 return codec_context_->sample_rate; | |
31 } | |
32 | |
33 base::TimeDelta AudioFileReader::duration() const { | 28 base::TimeDelta AudioFileReader::duration() const { |
34 const AVRational av_time_base = {1, AV_TIME_BASE}; | 29 const AVRational av_time_base = {1, AV_TIME_BASE}; |
35 | 30 |
36 // Add one microsecond to avoid rounding-down errors which can occur when | 31 // Add one microsecond to avoid rounding-down errors which can occur when |
37 // |duration| has been calculated from an exact number of sample-frames. | 32 // |duration| has been calculated from an exact number of sample-frames. |
38 // One microsecond is much less than the time of a single sample-frame | 33 // One microsecond is much less than the time of a single sample-frame |
39 // at any real-world sample-rate. | 34 // at any real-world sample-rate. |
40 return ConvertFromTimeBase( | 35 return ConvertFromTimeBase( |
41 av_time_base, glue_->format_context()->duration + 1); | 36 av_time_base, glue_->format_context()->duration + 1); |
42 } | 37 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 } | 98 } |
104 | 99 |
105 // Verify the channel layout is supported by Chrome. Acts as a sanity check | 100 // Verify the channel layout is supported by Chrome. Acts as a sanity check |
106 // against invalid files. See http://crbug.com/171962 | 101 // against invalid files. See http://crbug.com/171962 |
107 if (ChannelLayoutToChromeChannelLayout( | 102 if (ChannelLayoutToChromeChannelLayout( |
108 codec_context_->channel_layout, codec_context_->channels) == | 103 codec_context_->channel_layout, codec_context_->channels) == |
109 CHANNEL_LAYOUT_UNSUPPORTED) { | 104 CHANNEL_LAYOUT_UNSUPPORTED) { |
110 return false; | 105 return false; |
111 } | 106 } |
112 | 107 |
108 // Store initial values to guard against mid-frame configuration changes. | |
109 channels_ = codec_context_->channels; | |
110 sample_rate_ = codec_context_->sample_rate; | |
111 av_sample_format_ = codec_context_->sample_fmt; | |
112 | |
113 return true; | 113 return true; |
114 } | 114 } |
115 | 115 |
116 void AudioFileReader::Close() { | 116 void AudioFileReader::Close() { |
117 if (codec_context_) { | 117 if (codec_context_) { |
118 avcodec_close(codec_context_); | 118 avcodec_close(codec_context_); |
119 codec_context_ = NULL; | 119 codec_context_ = NULL; |
120 } | 120 } |
121 } | 121 } |
122 | 122 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
172 if (!frame_decoded) | 172 if (!frame_decoded) |
173 continue; | 173 continue; |
174 | 174 |
175 // Determine the number of sample-frames we just decoded. Check overflow. | 175 // Determine the number of sample-frames we just decoded. Check overflow. |
176 int frames_read = av_frame->nb_samples; | 176 int frames_read = av_frame->nb_samples; |
177 if (frames_read < 0) { | 177 if (frames_read < 0) { |
178 continue_decoding = false; | 178 continue_decoding = false; |
179 break; | 179 break; |
180 } | 180 } |
181 | 181 |
182 if (av_frame->sample_rate != sample_rate_ || | |
183 av_frame->channels != channels_ || | |
184 av_frame->format != av_sample_format_) { | |
185 DLOG(ERROR) << "Unsupported mid-frame configuration change!" | |
scherkus (not reviewing)
2013/02/12 02:16:56
consistent terminology nit: s/mid-frame/mid-stream
DaleCurtis
2013/02/12 02:41:24
Done.
| |
186 << " Sample Rate: " << av_frame->sample_rate << " vs " | |
187 << sample_rate_ | |
188 << ", Channels: " << av_frame->channels << " vs " | |
189 << channels_ | |
190 << ", Sample Format: " << av_frame->format << " vs " | |
191 << av_sample_format_; | |
192 | |
193 // This is an unrecoverable error, so bail out. | |
194 continue_decoding = false; | |
195 break; | |
196 } | |
197 | |
182 // Truncate, if necessary, if the destination isn't big enough. | 198 // Truncate, if necessary, if the destination isn't big enough. |
183 if (current_frame + frames_read > audio_bus->frames()) | 199 if (current_frame + frames_read > audio_bus->frames()) |
184 frames_read = audio_bus->frames() - current_frame; | 200 frames_read = audio_bus->frames() - current_frame; |
185 | 201 |
186 // Deinterleave each channel and convert to 32bit floating-point with | 202 // Deinterleave each channel and convert to 32bit floating-point with |
187 // nominal range -1.0 -> +1.0. If the output is already in float planar | 203 // nominal range -1.0 -> +1.0. If the output is already in float planar |
188 // format, just copy it into the AudioBus. | 204 // format, just copy it into the AudioBus. |
189 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) { | 205 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) { |
190 float* decoded_audio_data = reinterpret_cast<float*>(av_frame->data[0]); | 206 float* decoded_audio_data = reinterpret_cast<float*>(av_frame->data[0]); |
191 int channels = audio_bus->channels(); | 207 int channels = audio_bus->channels(); |
(...skipping 22 matching lines...) Expand all Loading... | |
214 // Zero any remaining frames. | 230 // Zero any remaining frames. |
215 audio_bus->ZeroFramesPartial( | 231 audio_bus->ZeroFramesPartial( |
216 current_frame, audio_bus->frames() - current_frame); | 232 current_frame, audio_bus->frames() - current_frame); |
217 | 233 |
218 // Returns the actual number of sample-frames decoded. | 234 // Returns the actual number of sample-frames decoded. |
219 // Ideally this represents the "true" exact length of the file. | 235 // Ideally this represents the "true" exact length of the file. |
220 return current_frame; | 236 return current_frame; |
221 } | 237 } |
222 | 238 |
223 } // namespace media | 239 } // namespace media |
OLD | NEW |