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/ffmpeg_audio_decoder.h" | 5 #include "media/filters/ffmpeg_audio_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "media/base/audio_decoder_config.h" | 8 #include "media/base/audio_decoder_config.h" |
9 #include "media/base/data_buffer.h" | 9 #include "media/base/data_buffer.h" |
10 #include "media/base/demuxer.h" | 10 #include "media/base/demuxer.h" |
11 #include "media/base/filter_host.h" | |
12 #include "media/base/pipeline.h" | 11 #include "media/base/pipeline.h" |
13 #include "media/ffmpeg/ffmpeg_common.h" | 12 #include "media/ffmpeg/ffmpeg_common.h" |
14 | 13 |
15 namespace media { | 14 namespace media { |
16 | 15 |
17 // Returns true if the decode result was an error. | 16 // Returns true if the decode result was an error. |
18 static bool IsErrorResult(int result, int decoded_size) { | 17 static bool IsErrorResult(int result, int decoded_size) { |
19 return result < 0 || | 18 return result < 0 || |
20 decoded_size < 0 || | 19 decoded_size < 0 || |
21 decoded_size > AVCODEC_MAX_AUDIO_FRAME_SIZE; | 20 decoded_size > AVCODEC_MAX_AUDIO_FRAME_SIZE; |
(...skipping 30 matching lines...) Expand all Loading... |
52 bits_per_channel_(0), | 51 bits_per_channel_(0), |
53 channel_layout_(CHANNEL_LAYOUT_NONE), | 52 channel_layout_(CHANNEL_LAYOUT_NONE), |
54 samples_per_second_(0), | 53 samples_per_second_(0), |
55 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), | 54 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), |
56 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))) { | 55 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))) { |
57 } | 56 } |
58 | 57 |
59 FFmpegAudioDecoder::~FFmpegAudioDecoder() { | 58 FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
60 av_free(decoded_audio_); | 59 av_free(decoded_audio_); |
61 | 60 |
62 // XXX: should we require Stop() to be called? this might end up getting | 61 // TODO(scherkus): should we require Stop() to be called? this might end up |
63 // called on a random thread due to refcounting. | 62 // getting called on a random thread due to refcounting. |
64 if (codec_context_) { | 63 if (codec_context_) { |
65 av_free(codec_context_->extradata); | 64 av_free(codec_context_->extradata); |
66 avcodec_close(codec_context_); | 65 avcodec_close(codec_context_); |
67 av_free(codec_context_); | 66 av_free(codec_context_); |
68 } | 67 } |
69 } | 68 } |
70 | 69 |
71 void FFmpegAudioDecoder::Flush(const base::Closure& callback) { | |
72 message_loop_->PostTask( | |
73 FROM_HERE, | |
74 base::Bind(&FFmpegAudioDecoder::DoFlush, this, callback)); | |
75 } | |
76 | |
77 void FFmpegAudioDecoder::Initialize( | 70 void FFmpegAudioDecoder::Initialize( |
78 DemuxerStream* stream, | 71 const scoped_refptr<DemuxerStream>& stream, |
79 const PipelineStatusCB& callback, | 72 const PipelineStatusCB& callback, |
80 const StatisticsCallback& stats_callback) { | 73 const StatisticsCallback& stats_callback) { |
81 // TODO(scherkus): change Initialize() signature to pass |stream| as a | |
82 // scoped_refptr<>. | |
83 scoped_refptr<DemuxerStream> ref_stream(stream); | |
84 message_loop_->PostTask( | 74 message_loop_->PostTask( |
85 FROM_HERE, | 75 FROM_HERE, |
86 base::Bind(&FFmpegAudioDecoder::DoInitialize, this, | 76 base::Bind(&FFmpegAudioDecoder::DoInitialize, this, |
87 ref_stream, callback, stats_callback)); | 77 stream, callback, stats_callback)); |
88 } | 78 } |
89 | 79 |
90 void FFmpegAudioDecoder::Read(const ReadCB& callback) { | 80 void FFmpegAudioDecoder::Read(const ReadCB& callback) { |
91 // Complete operation asynchronously on different stack of execution as per | 81 // Complete operation asynchronously on different stack of execution as per |
92 // the API contract of AudioDecoder::Read() | 82 // the API contract of AudioDecoder::Read() |
93 message_loop_->PostTask(FROM_HERE, base::Bind( | 83 message_loop_->PostTask(FROM_HERE, base::Bind( |
94 &FFmpegAudioDecoder::DoRead, this, callback)); | 84 &FFmpegAudioDecoder::DoRead, this, callback)); |
95 } | 85 } |
96 | 86 |
97 int FFmpegAudioDecoder::bits_per_channel() { | 87 int FFmpegAudioDecoder::bits_per_channel() { |
98 return bits_per_channel_; | 88 return bits_per_channel_; |
99 } | 89 } |
100 | 90 |
101 ChannelLayout FFmpegAudioDecoder::channel_layout() { | 91 ChannelLayout FFmpegAudioDecoder::channel_layout() { |
102 return channel_layout_; | 92 return channel_layout_; |
103 } | 93 } |
104 | 94 |
105 int FFmpegAudioDecoder::samples_per_second() { | 95 int FFmpegAudioDecoder::samples_per_second() { |
106 return samples_per_second_; | 96 return samples_per_second_; |
107 } | 97 } |
108 | 98 |
| 99 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { |
| 100 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 101 &FFmpegAudioDecoder::DoReset, this, closure)); |
| 102 } |
| 103 |
109 void FFmpegAudioDecoder::DoInitialize( | 104 void FFmpegAudioDecoder::DoInitialize( |
110 const scoped_refptr<DemuxerStream>& stream, | 105 const scoped_refptr<DemuxerStream>& stream, |
111 const PipelineStatusCB& callback, | 106 const PipelineStatusCB& callback, |
112 const StatisticsCallback& stats_callback) { | 107 const StatisticsCallback& stats_callback) { |
113 demuxer_stream_ = stream; | 108 demuxer_stream_ = stream; |
114 const AudioDecoderConfig& config = stream->audio_decoder_config(); | 109 const AudioDecoderConfig& config = stream->audio_decoder_config(); |
115 stats_callback_ = stats_callback; | 110 stats_callback_ = stats_callback; |
116 | 111 |
117 // TODO(scherkus): this check should go in Pipeline prior to creating | 112 // TODO(scherkus): this check should go in Pipeline prior to creating |
118 // decoder objects. | 113 // decoder objects. |
(...skipping 22 matching lines...) Expand all Loading... |
141 } | 136 } |
142 | 137 |
143 // Success! | 138 // Success! |
144 bits_per_channel_ = config.bits_per_channel(); | 139 bits_per_channel_ = config.bits_per_channel(); |
145 channel_layout_ = config.channel_layout(); | 140 channel_layout_ = config.channel_layout(); |
146 samples_per_second_ = config.samples_per_second(); | 141 samples_per_second_ = config.samples_per_second(); |
147 | 142 |
148 callback.Run(PIPELINE_OK); | 143 callback.Run(PIPELINE_OK); |
149 } | 144 } |
150 | 145 |
151 void FFmpegAudioDecoder::DoFlush(const base::Closure& callback) { | 146 void FFmpegAudioDecoder::DoReset(const base::Closure& closure) { |
152 avcodec_flush_buffers(codec_context_); | 147 avcodec_flush_buffers(codec_context_); |
153 estimated_next_timestamp_ = kNoTimestamp(); | 148 estimated_next_timestamp_ = kNoTimestamp(); |
154 callback.Run(); | 149 closure.Run(); |
155 } | 150 } |
156 | 151 |
157 void FFmpegAudioDecoder::DoRead(const ReadCB& callback) { | 152 void FFmpegAudioDecoder::DoRead(const ReadCB& callback) { |
158 DCHECK_EQ(MessageLoop::current(), message_loop_); | 153 DCHECK_EQ(MessageLoop::current(), message_loop_); |
159 DCHECK(!callback.is_null()); | 154 DCHECK(!callback.is_null()); |
160 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 155 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
161 | 156 |
162 read_cb_ = callback; | 157 read_cb_ = callback; |
163 ReadFromDemuxerStream(); | 158 ReadFromDemuxerStream(); |
164 } | 159 } |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 } | 284 } |
290 | 285 |
291 void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) { | 286 void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) { |
292 // Reset the callback before running to protect against reentrancy. | 287 // Reset the callback before running to protect against reentrancy. |
293 ReadCB read_cb = read_cb_; | 288 ReadCB read_cb = read_cb_; |
294 read_cb_.Reset(); | 289 read_cb_.Reset(); |
295 read_cb.Run(samples); | 290 read_cb.Run(samples); |
296 } | 291 } |
297 | 292 |
298 } // namespace media | 293 } // namespace media |
OLD | NEW |