Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Side by Side Diff: media/filters/ffmpeg_audio_decoder.cc

Issue 7867051: Introduce AudioDecoderConfig to migrate away from GetAVStream(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: samples_per_second Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/ffmpeg_audio_decoder.h ('k') | media/filters/ffmpeg_audio_decoder_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/data_buffer.h" 8 #include "media/base/data_buffer.h"
9 #include "media/base/demuxer.h" 9 #include "media/base/demuxer.h"
10 #include "media/base/filter_host.h" 10 #include "media/base/filter_host.h"
11 #include "media/base/limits.h"
12 #include "media/ffmpeg/ffmpeg_common.h" 11 #include "media/ffmpeg/ffmpeg_common.h"
13 12
14 namespace media { 13 namespace media {
15 14
16 // Returns true if the decode result was an error. 15 // Returns true if the decode result was an error.
17 static bool IsErrorResult(int result, int decoded_size) { 16 static bool IsErrorResult(int result, int decoded_size) {
18 return result < 0 || 17 return result < 0 ||
19 decoded_size < 0 || 18 decoded_size < 0 ||
20 decoded_size > AVCODEC_MAX_AUDIO_FRAME_SIZE; 19 decoded_size > AVCODEC_MAX_AUDIO_FRAME_SIZE;
21 } 20 }
(...skipping 21 matching lines...) Expand all
43 // 3. An end of stream buffer is received. 42 // 3. An end of stream buffer is received.
44 return result == 0 && decoded_size == 0 && input->IsEndOfStream(); 43 return result == 0 && decoded_size == 0 && input->IsEndOfStream();
45 } 44 }
46 45
47 46
48 FFmpegAudioDecoder::FFmpegAudioDecoder(MessageLoop* message_loop) 47 FFmpegAudioDecoder::FFmpegAudioDecoder(MessageLoop* message_loop)
49 : message_loop_(message_loop), 48 : message_loop_(message_loop),
50 codec_context_(NULL), 49 codec_context_(NULL),
51 bits_per_channel_(0), 50 bits_per_channel_(0),
52 channel_layout_(CHANNEL_LAYOUT_NONE), 51 channel_layout_(CHANNEL_LAYOUT_NONE),
53 sample_rate_(0), 52 samples_per_second_(0),
54 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), 53 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE),
55 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))), 54 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))),
56 pending_reads_(0) { 55 pending_reads_(0) {
57 } 56 }
58 57
59 FFmpegAudioDecoder::~FFmpegAudioDecoder() { 58 FFmpegAudioDecoder::~FFmpegAudioDecoder() {
60 av_free(decoded_audio_); 59 av_free(decoded_audio_);
60
61 // XXX: should we require Stop() to be called? this might end up getting
62 // called on a random thread due to refcounting.
63 if (codec_context_) {
64 av_free(codec_context_->extradata);
65 avcodec_close(codec_context_);
66 av_free(codec_context_);
67 }
61 } 68 }
62 69
63 void FFmpegAudioDecoder::Flush(FilterCallback* callback) { 70 void FFmpegAudioDecoder::Flush(FilterCallback* callback) {
64 message_loop_->PostTask( 71 message_loop_->PostTask(
65 FROM_HERE, 72 FROM_HERE,
66 NewRunnableMethod(this, &FFmpegAudioDecoder::DoFlush, callback)); 73 NewRunnableMethod(this, &FFmpegAudioDecoder::DoFlush, callback));
67 } 74 }
68 75
69 void FFmpegAudioDecoder::Initialize( 76 void FFmpegAudioDecoder::Initialize(
70 DemuxerStream* stream, 77 DemuxerStream* stream,
(...skipping 16 matching lines...) Expand all
87 } 94 }
88 95
89 int FFmpegAudioDecoder::bits_per_channel() { 96 int FFmpegAudioDecoder::bits_per_channel() {
90 return bits_per_channel_; 97 return bits_per_channel_;
91 } 98 }
92 99
93 ChannelLayout FFmpegAudioDecoder::channel_layout() { 100 ChannelLayout FFmpegAudioDecoder::channel_layout() {
94 return channel_layout_; 101 return channel_layout_;
95 } 102 }
96 103
97 int FFmpegAudioDecoder::sample_rate() { 104 int FFmpegAudioDecoder::samples_per_second() {
98 return sample_rate_; 105 return samples_per_second_;
99 } 106 }
100 107
101 void FFmpegAudioDecoder::DoInitialize( 108 void FFmpegAudioDecoder::DoInitialize(
102 const scoped_refptr<DemuxerStream>& stream, 109 const scoped_refptr<DemuxerStream>& stream,
103 FilterCallback* callback, 110 FilterCallback* callback,
104 StatisticsCallback* stats_callback) { 111 StatisticsCallback* stats_callback) {
105 scoped_ptr<FilterCallback> c(callback); 112 scoped_ptr<FilterCallback> c(callback);
106 113
107 demuxer_stream_ = stream; 114 demuxer_stream_ = stream;
108 AVStream* av_stream = demuxer_stream_->GetAVStream(); 115 const AudioDecoderConfig& config = stream->audio_decoder_config();
109 CHECK(av_stream);
110
111 stats_callback_.reset(stats_callback); 116 stats_callback_.reset(stats_callback);
112 117
113 // Grab the AVStream's codec context and make sure we have sensible values. 118 // TODO(scherkus): this check should go in PipelineImpl prior to creating
114 codec_context_ = av_stream->codec; 119 // decoder objects.
115 int bps = av_get_bits_per_sample_fmt(codec_context_->sample_fmt); 120 if (!config.IsValidConfig()) {
116 if (codec_context_->channels <= 0 ||
117 codec_context_->channels > Limits::kMaxChannels ||
118 (codec_context_->channel_layout == 0 && codec_context_->channels > 2) ||
119 bps <= 0 || bps > Limits::kMaxBitsPerSample ||
120 codec_context_->sample_rate <= 0 ||
121 codec_context_->sample_rate > Limits::kMaxSampleRate) {
122 DLOG(ERROR) << "Invalid audio stream -" 121 DLOG(ERROR) << "Invalid audio stream -"
123 << " channels: " << codec_context_->channels 122 << " codec: " << config.codec()
124 << " channel layout:" << codec_context_->channel_layout 123 << " channel layout: " << config.channel_layout()
125 << " bps: " << bps 124 << " bits per channel: " << config.bits_per_channel()
126 << " sample rate: " << codec_context_->sample_rate; 125 << " samples per second: " << config.samples_per_second();
127 126
128 host()->SetError(PIPELINE_ERROR_DECODE); 127 host()->SetError(DECODER_ERROR_NOT_SUPPORTED);
129 callback->Run(); 128 callback->Run();
130 return; 129 return;
131 } 130 }
132 131
133 // Serialize calls to avcodec_open(). 132 // Initialize AVCodecContext structure.
133 codec_context_ = avcodec_alloc_context();
134 AudioDecoderConfigToAVCodecContext(config, codec_context_);
135
134 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); 136 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
135 if (!codec || avcodec_open(codec_context_, codec) < 0) { 137 if (!codec || avcodec_open(codec_context_, codec) < 0) {
136 DLOG(ERROR) << "Could not initialize audio decoder: " 138 DLOG(ERROR) << "Could not initialize audio decoder: "
137 << codec_context_->codec_id; 139 << codec_context_->codec_id;
138 140
139 host()->SetError(PIPELINE_ERROR_DECODE); 141 host()->SetError(DECODER_ERROR_NOT_SUPPORTED);
140 callback->Run(); 142 callback->Run();
141 return; 143 return;
142 } 144 }
143 145
144 // Success! 146 // Success!
145 bits_per_channel_ = av_get_bits_per_sample_fmt(codec_context_->sample_fmt); 147 bits_per_channel_ = config.bits_per_channel();
146 channel_layout_ = 148 channel_layout_ = config.channel_layout();
147 ChannelLayoutToChromeChannelLayout(codec_context_->channel_layout, 149 samples_per_second_ = config.samples_per_second();
148 codec_context_->channels);
149 sample_rate_ = codec_context_->sample_rate;
150 150
151 callback->Run(); 151 callback->Run();
152 } 152 }
153 153
154 void FFmpegAudioDecoder::DoFlush(FilterCallback* callback) { 154 void FFmpegAudioDecoder::DoFlush(FilterCallback* callback) {
155 avcodec_flush_buffers(codec_context_); 155 avcodec_flush_buffers(codec_context_);
156 estimated_next_timestamp_ = kNoTimestamp; 156 estimated_next_timestamp_ = kNoTimestamp;
157 157
158 callback->Run(); 158 callback->Run();
159 delete callback; 159 delete callback;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 // Otherwise use an estimated timestamp and attempt to update the estimation 279 // Otherwise use an estimated timestamp and attempt to update the estimation
280 // as long as it's valid. 280 // as long as it's valid.
281 output->SetTimestamp(estimated_next_timestamp_); 281 output->SetTimestamp(estimated_next_timestamp_);
282 if (estimated_next_timestamp_ != kNoTimestamp) { 282 if (estimated_next_timestamp_ != kNoTimestamp) {
283 estimated_next_timestamp_ += duration; 283 estimated_next_timestamp_ += duration;
284 } 284 }
285 } 285 }
286 286
287 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(int size) { 287 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(int size) {
288 int64 denominator = ChannelLayoutToChannelCount(channel_layout_) * 288 int64 denominator = ChannelLayoutToChannelCount(channel_layout_) *
289 bits_per_channel_ / 8 * sample_rate_; 289 bits_per_channel_ / 8 * samples_per_second_;
290 double microseconds = size / 290 double microseconds = size /
291 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); 291 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond));
292 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); 292 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds));
293 } 293 }
294 294
295 } // namespace media 295 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_audio_decoder.h ('k') | media/filters/ffmpeg_audio_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698