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 <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 channels_(0), | 21 channels_(0), |
22 sample_rate_(0), | 22 sample_rate_(0), |
23 av_sample_format_(0) { | 23 av_sample_format_(0) { |
24 } | 24 } |
25 | 25 |
26 AudioFileReader::~AudioFileReader() { | 26 AudioFileReader::~AudioFileReader() { |
27 Close(); | 27 Close(); |
28 } | 28 } |
29 | 29 |
30 bool AudioFileReader::Open() { | 30 bool AudioFileReader::Open() { |
| 31 if (!OpenDemuxer()) |
| 32 return false; |
| 33 return OpenDecoder(); |
| 34 } |
| 35 |
| 36 bool AudioFileReader::OpenDemuxer() { |
31 glue_.reset(new FFmpegGlue(protocol_)); | 37 glue_.reset(new FFmpegGlue(protocol_)); |
32 AVFormatContext* format_context = glue_->format_context(); | 38 AVFormatContext* format_context = glue_->format_context(); |
33 | 39 |
34 // Open FFmpeg AVFormatContext. | 40 // Open FFmpeg AVFormatContext. |
35 if (!glue_->OpenContext()) { | 41 if (!glue_->OpenContext()) { |
36 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()"; | 42 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()"; |
37 return false; | 43 return false; |
38 } | 44 } |
39 | 45 |
40 // Get the codec context. | 46 // Get the codec context. |
41 codec_context_ = NULL; | 47 codec_context_ = NULL; |
42 for (size_t i = 0; i < format_context->nb_streams; ++i) { | 48 for (size_t i = 0; i < format_context->nb_streams; ++i) { |
43 AVCodecContext* c = format_context->streams[i]->codec; | 49 AVCodecContext* c = format_context->streams[i]->codec; |
44 if (c->codec_type == AVMEDIA_TYPE_AUDIO) { | 50 if (c->codec_type == AVMEDIA_TYPE_AUDIO) { |
45 codec_context_ = c; | 51 codec_context_ = c; |
46 stream_index_ = i; | 52 stream_index_ = i; |
47 break; | 53 break; |
48 } | 54 } |
49 } | 55 } |
50 | 56 |
51 // Get the codec. | 57 // Get the codec. |
52 if (!codec_context_) | 58 if (!codec_context_) |
53 return false; | 59 return false; |
54 | 60 |
55 int result = avformat_find_stream_info(format_context, NULL); | 61 const int result = avformat_find_stream_info(format_context, NULL); |
56 if (result < 0) { | 62 DLOG_IF(WARNING, result < 0) |
57 DLOG(WARNING) | 63 << "AudioFileReader::Open() : error in avformat_find_stream_info()"; |
58 << "AudioFileReader::Open() : error in avformat_find_stream_info()"; | 64 return result >= 0; |
59 return false; | 65 } |
60 } | |
61 | 66 |
| 67 bool AudioFileReader::OpenDecoder() { |
62 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 68 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
63 if (codec) { | 69 if (codec) { |
64 // MP3 decodes to S16P which we don't support, tell it to use S16 instead. | 70 // MP3 decodes to S16P which we don't support, tell it to use S16 instead. |
65 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) | 71 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) |
66 codec_context_->request_sample_fmt = AV_SAMPLE_FMT_S16; | 72 codec_context_->request_sample_fmt = AV_SAMPLE_FMT_S16; |
67 | 73 |
68 if ((result = avcodec_open2(codec_context_, codec, NULL)) < 0) { | 74 const int result = avcodec_open2(codec_context_, codec, NULL); |
| 75 if (result < 0) { |
69 DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -" | 76 DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -" |
70 << " result: " << result; | 77 << " result: " << result; |
71 return false; | 78 return false; |
72 } | 79 } |
73 | 80 |
74 // Ensure avcodec_open2() respected our format request. | 81 // Ensure avcodec_open2() respected our format request. |
75 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) { | 82 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) { |
76 DLOG(ERROR) << "AudioFileReader::Open() : unable to configure a" | 83 DLOG(ERROR) << "AudioFileReader::Open() : unable to configure a" |
77 << " supported sample format - " | 84 << " supported sample format - " |
78 << codec_context_->sample_fmt; | 85 << codec_context_->sample_fmt; |
79 return false; | 86 return false; |
80 } | 87 } |
81 } else { | 88 } else { |
82 DLOG(WARNING) << "AudioFileReader::Open() : could not find codec -" | 89 DLOG(WARNING) << "AudioFileReader::Open() : could not find codec."; |
83 << " result: " << result; | |
84 return false; | 90 return false; |
85 } | 91 } |
86 | 92 |
87 // Verify the channel layout is supported by Chrome. Acts as a sanity check | 93 // Verify the channel layout is supported by Chrome. Acts as a sanity check |
88 // against invalid files. See http://crbug.com/171962 | 94 // against invalid files. See http://crbug.com/171962 |
89 if (ChannelLayoutToChromeChannelLayout( | 95 if (ChannelLayoutToChromeChannelLayout( |
90 codec_context_->channel_layout, codec_context_->channels) == | 96 codec_context_->channel_layout, codec_context_->channels) == |
91 CHANNEL_LAYOUT_UNSUPPORTED) { | 97 CHANNEL_LAYOUT_UNSUPPORTED) { |
92 return false; | 98 return false; |
93 } | 99 } |
94 | 100 |
95 // Store initial values to guard against midstream configuration changes. | 101 // Store initial values to guard against midstream configuration changes. |
96 channels_ = codec_context_->channels; | 102 channels_ = codec_context_->channels; |
97 sample_rate_ = codec_context_->sample_rate; | 103 sample_rate_ = codec_context_->sample_rate; |
98 av_sample_format_ = codec_context_->sample_fmt; | 104 av_sample_format_ = codec_context_->sample_fmt; |
99 | |
100 return true; | 105 return true; |
101 } | 106 } |
102 | 107 |
103 void AudioFileReader::Close() { | 108 void AudioFileReader::Close() { |
104 // |codec_context_| is a stream inside glue_->format_context(), so it is | 109 // |codec_context_| is a stream inside glue_->format_context(), so it is |
105 // closed when |glue_| is disposed. | 110 // closed when |glue_| is disposed. |
106 glue_.reset(); | 111 glue_.reset(); |
107 codec_context_ = NULL; | 112 codec_context_ = NULL; |
108 } | 113 } |
109 | 114 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 // One microsecond is much less than the time of a single sample-frame | 238 // One microsecond is much less than the time of a single sample-frame |
234 // at any real-world sample-rate. | 239 // at any real-world sample-rate. |
235 return ConvertFromTimeBase(av_time_base, | 240 return ConvertFromTimeBase(av_time_base, |
236 glue_->format_context()->duration + 1); | 241 glue_->format_context()->duration + 1); |
237 } | 242 } |
238 | 243 |
239 int AudioFileReader::GetNumberOfFrames() const { | 244 int AudioFileReader::GetNumberOfFrames() const { |
240 return static_cast<int>(ceil(GetDuration().InSecondsF() * sample_rate())); | 245 return static_cast<int>(ceil(GetDuration().InSecondsF() * sample_rate())); |
241 } | 246 } |
242 | 247 |
| 248 bool AudioFileReader::OpenDemuxerForTesting() { |
| 249 return OpenDemuxer(); |
| 250 } |
| 251 |
243 bool AudioFileReader::ReadPacketForTesting(AVPacket* output_packet) { | 252 bool AudioFileReader::ReadPacketForTesting(AVPacket* output_packet) { |
244 return ReadPacket(output_packet); | 253 return ReadPacket(output_packet); |
245 } | 254 } |
246 | 255 |
247 bool AudioFileReader::ReadPacket(AVPacket* output_packet) { | 256 bool AudioFileReader::ReadPacket(AVPacket* output_packet) { |
248 while (av_read_frame(glue_->format_context(), output_packet) >= 0 && | 257 while (av_read_frame(glue_->format_context(), output_packet) >= 0 && |
249 av_dup_packet(output_packet) >= 0) { | 258 av_dup_packet(output_packet) >= 0) { |
250 // Skip packets from other streams. | 259 // Skip packets from other streams. |
251 if (output_packet->stream_index != stream_index_) { | 260 if (output_packet->stream_index != stream_index_) { |
252 av_free_packet(output_packet); | 261 av_free_packet(output_packet); |
253 continue; | 262 continue; |
254 } | 263 } |
255 return true; | 264 return true; |
256 } | 265 } |
257 return false; | 266 return false; |
258 } | 267 } |
259 | 268 |
| 269 bool AudioFileReader::SeekForTesting(base::TimeDelta seek_time) { |
| 270 return av_seek_frame(glue_->format_context(), |
| 271 stream_index_, |
| 272 ConvertToTimeBase(codec_context_->time_base, seek_time), |
| 273 AVSEEK_FLAG_BACKWARD) >= 0; |
| 274 } |
| 275 |
| 276 const AVStream* AudioFileReader::GetAVStreamForTesting() const { |
| 277 return glue_->format_context()->streams[stream_index_]; |
| 278 } |
| 279 |
260 } // namespace media | 280 } // namespace media |
OLD | NEW |