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

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

Issue 9632024: Create video and audio decoder threads on demand. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Switched to base::Bind() and reverted gyp change+new files Created 8 years, 9 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
OLDNEW
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/message_loop_factory.h"
scherkus (not reviewing) 2012/03/09 20:01:16 not needed
tommi (sloooow) - chröme 2012/03/11 18:49:36 Done.
11 #include "media/base/pipeline.h" 12 #include "media/base/pipeline.h"
12 #include "media/ffmpeg/ffmpeg_common.h" 13 #include "media/ffmpeg/ffmpeg_common.h"
13 14
14 namespace media { 15 namespace media {
15 16
16 // Returns true if the decode result was an error. 17 // Returns true if the decode result was an error.
17 static bool IsErrorResult(int result, int decoded_size) { 18 static bool IsErrorResult(int result, int decoded_size) {
18 return result < 0 || 19 return result < 0 ||
19 decoded_size < 0 || 20 decoded_size < 0 ||
20 decoded_size > AVCODEC_MAX_AUDIO_FRAME_SIZE; 21 decoded_size > AVCODEC_MAX_AUDIO_FRAME_SIZE;
(...skipping 17 matching lines...) Expand all
38 // Returns true if the decode result was end of stream. 39 // Returns true if the decode result was end of stream.
39 static bool IsEndOfStream(int result, int decoded_size, Buffer* input) { 40 static bool IsEndOfStream(int result, int decoded_size, Buffer* input) {
40 // Three conditions to meet to declare end of stream for this decoder: 41 // Three conditions to meet to declare end of stream for this decoder:
41 // 1. FFmpeg didn't read anything. 42 // 1. FFmpeg didn't read anything.
42 // 2. FFmpeg didn't output anything. 43 // 2. FFmpeg didn't output anything.
43 // 3. An end of stream buffer is received. 44 // 3. An end of stream buffer is received.
44 return result == 0 && decoded_size == 0 && input->IsEndOfStream(); 45 return result == 0 && decoded_size == 0 && input->IsEndOfStream();
45 } 46 }
46 47
47 48
48 FFmpegAudioDecoder::FFmpegAudioDecoder(MessageLoop* message_loop) 49 FFmpegAudioDecoder::FFmpegAudioDecoder(
49 : message_loop_(message_loop), 50 const base::Callback<MessageLoop*()>& message_loop_cb)
51 : message_loop_cb_(message_loop_cb),
52 message_loop_(NULL),
50 codec_context_(NULL), 53 codec_context_(NULL),
51 bits_per_channel_(0), 54 bits_per_channel_(0),
52 channel_layout_(CHANNEL_LAYOUT_NONE), 55 channel_layout_(CHANNEL_LAYOUT_NONE),
53 samples_per_second_(0), 56 samples_per_second_(0),
54 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), 57 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE),
55 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))) { 58 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))) {
56 } 59 }
57 60
58 FFmpegAudioDecoder::~FFmpegAudioDecoder() { 61 FFmpegAudioDecoder::~FFmpegAudioDecoder() {
59 av_free(decoded_audio_); 62 av_free(decoded_audio_);
60 63
61 // TODO(scherkus): should we require Stop() to be called? this might end up 64 // TODO(scherkus): should we require Stop() to be called? this might end up
62 // getting called on a random thread due to refcounting. 65 // getting called on a random thread due to refcounting.
63 if (codec_context_) { 66 if (codec_context_) {
64 av_free(codec_context_->extradata); 67 av_free(codec_context_->extradata);
65 avcodec_close(codec_context_); 68 avcodec_close(codec_context_);
66 av_free(codec_context_); 69 av_free(codec_context_);
67 } 70 }
68 } 71 }
69 72
70 void FFmpegAudioDecoder::Initialize( 73 void FFmpegAudioDecoder::Initialize(
71 const scoped_refptr<DemuxerStream>& stream, 74 const scoped_refptr<DemuxerStream>& stream,
72 const PipelineStatusCB& callback, 75 const PipelineStatusCB& callback,
73 const StatisticsCallback& stats_callback) { 76 const StatisticsCallback& stats_callback) {
74 message_loop_->PostTask( 77 message_loop_ = message_loop_cb_.Run();
75 FROM_HERE, 78 message_loop_->PostTask(FROM_HERE,
scherkus (not reviewing) 2012/03/09 20:01:16 style -- I'd do the following: message_loop_->Pos
tommi (sloooow) - chröme 2012/03/11 18:49:36 Done.
76 base::Bind(&FFmpegAudioDecoder::DoInitialize, this, 79 base::Bind(&FFmpegAudioDecoder::DoInitialize, this,
77 stream, callback, stats_callback)); 80 stream, callback, stats_callback));
78 } 81 }
79 82
80 void FFmpegAudioDecoder::Read(const ReadCB& callback) { 83 void FFmpegAudioDecoder::Read(const ReadCB& callback) {
81 // Complete operation asynchronously on different stack of execution as per 84 // Complete operation asynchronously on different stack of execution as per
82 // the API contract of AudioDecoder::Read() 85 // the API contract of AudioDecoder::Read()
83 message_loop_->PostTask(FROM_HERE, base::Bind( 86 message_loop_->PostTask(FROM_HERE,
scherkus (not reviewing) 2012/03/09 20:01:16 ditto here + below (i.e., revert these edits)
tommi (sloooow) - chröme 2012/03/11 18:49:36 Done.
84 &FFmpegAudioDecoder::DoRead, this, callback)); 87 base::Bind(&FFmpegAudioDecoder::DoRead, this, callback));
85 } 88 }
86 89
87 int FFmpegAudioDecoder::bits_per_channel() { 90 int FFmpegAudioDecoder::bits_per_channel() {
88 return bits_per_channel_; 91 return bits_per_channel_;
89 } 92 }
90 93
91 ChannelLayout FFmpegAudioDecoder::channel_layout() { 94 ChannelLayout FFmpegAudioDecoder::channel_layout() {
92 return channel_layout_; 95 return channel_layout_;
93 } 96 }
94 97
95 int FFmpegAudioDecoder::samples_per_second() { 98 int FFmpegAudioDecoder::samples_per_second() {
96 return samples_per_second_; 99 return samples_per_second_;
97 } 100 }
98 101
99 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { 102 void FFmpegAudioDecoder::Reset(const base::Closure& closure) {
100 message_loop_->PostTask(FROM_HERE, base::Bind( 103 message_loop_->PostTask(FROM_HERE,
101 &FFmpegAudioDecoder::DoReset, this, closure)); 104 base::Bind(&FFmpegAudioDecoder::DoReset, this, closure));
102 } 105 }
103 106
104 void FFmpegAudioDecoder::DoInitialize( 107 void FFmpegAudioDecoder::DoInitialize(
105 const scoped_refptr<DemuxerStream>& stream, 108 const scoped_refptr<DemuxerStream>& stream,
106 const PipelineStatusCB& callback, 109 const PipelineStatusCB& callback,
107 const StatisticsCallback& stats_callback) { 110 const StatisticsCallback& stats_callback) {
108 demuxer_stream_ = stream; 111 demuxer_stream_ = stream;
109 const AudioDecoderConfig& config = stream->audio_decoder_config(); 112 const AudioDecoderConfig& config = stream->audio_decoder_config();
110 stats_callback_ = stats_callback; 113 stats_callback_ = stats_callback;
111 114
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 245
243 void FFmpegAudioDecoder::ReadFromDemuxerStream() { 246 void FFmpegAudioDecoder::ReadFromDemuxerStream() {
244 DCHECK(!read_cb_.is_null()); 247 DCHECK(!read_cb_.is_null());
245 248
246 demuxer_stream_->Read(base::Bind(&FFmpegAudioDecoder::DecodeBuffer, this)); 249 demuxer_stream_->Read(base::Bind(&FFmpegAudioDecoder::DecodeBuffer, this));
247 } 250 }
248 251
249 void FFmpegAudioDecoder::DecodeBuffer(const scoped_refptr<Buffer>& buffer) { 252 void FFmpegAudioDecoder::DecodeBuffer(const scoped_refptr<Buffer>& buffer) {
250 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read 253 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read
251 // callback on the same execution stack so we can get rid of forced task post. 254 // callback on the same execution stack so we can get rid of forced task post.
252 message_loop_->PostTask(FROM_HERE, base::Bind( 255 message_loop_->PostTask(FROM_HERE,
253 &FFmpegAudioDecoder::DoDecodeBuffer, this, buffer)); 256 base::Bind(&FFmpegAudioDecoder::DoDecodeBuffer, this, buffer));
254 } 257 }
255 258
256 void FFmpegAudioDecoder::UpdateDurationAndTimestamp( 259 void FFmpegAudioDecoder::UpdateDurationAndTimestamp(
257 const Buffer* input, 260 const Buffer* input,
258 DataBuffer* output) { 261 DataBuffer* output) {
259 // Always calculate duration based on the actual number of samples decoded. 262 // Always calculate duration based on the actual number of samples decoded.
260 base::TimeDelta duration = CalculateDuration(output->GetDataSize()); 263 base::TimeDelta duration = CalculateDuration(output->GetDataSize());
261 output->SetDuration(duration); 264 output->SetDuration(duration);
262 265
263 // Use the incoming timestamp if it's valid. 266 // Use the incoming timestamp if it's valid.
(...skipping 20 matching lines...) Expand all
284 } 287 }
285 288
286 void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) { 289 void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) {
287 // Reset the callback before running to protect against reentrancy. 290 // Reset the callback before running to protect against reentrancy.
288 ReadCB read_cb = read_cb_; 291 ReadCB read_cb = read_cb_;
289 read_cb_.Reset(); 292 read_cb_.Reset();
290 read_cb.Run(samples); 293 read_cb.Run(samples);
291 } 294 }
292 295
293 } // namespace media 296 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698