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

Side by Side Diff: media/filters/ffmpeg_video_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_video_decoder.h" 5 #include "media/filters/ffmpeg_video_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/string_number_conversions.h" 10 #include "base/string_number_conversions.h"
11 #include "media/base/demuxer_stream.h" 11 #include "media/base/demuxer_stream.h"
12 #include "media/base/filter_host.h" 12 #include "media/base/filter_host.h"
13 #include "media/base/limits.h" 13 #include "media/base/limits.h"
14 #include "media/base/media_switches.h" 14 #include "media/base/media_switches.h"
15 #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.
15 #include "media/base/pipeline.h" 16 #include "media/base/pipeline.h"
16 #include "media/base/video_decoder_config.h" 17 #include "media/base/video_decoder_config.h"
17 #include "media/base/video_frame.h" 18 #include "media/base/video_frame.h"
18 #include "media/base/video_util.h" 19 #include "media/base/video_util.h"
19 #include "media/ffmpeg/ffmpeg_common.h" 20 #include "media/ffmpeg/ffmpeg_common.h"
20 21
21 namespace media { 22 namespace media {
22 23
23 // Always try to use three threads for video decoding. There is little reason 24 // Always try to use three threads for video decoding. There is little reason
24 // not to since current day CPUs tend to be multi-core and we measured 25 // not to since current day CPUs tend to be multi-core and we measured
(...skipping 19 matching lines...) Expand all
44 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 45 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
45 std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads)); 46 std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads));
46 if (threads.empty() || !base::StringToInt(threads, &decode_threads)) 47 if (threads.empty() || !base::StringToInt(threads, &decode_threads))
47 return decode_threads; 48 return decode_threads;
48 49
49 decode_threads = std::max(decode_threads, 0); 50 decode_threads = std::max(decode_threads, 0);
50 decode_threads = std::min(decode_threads, kMaxDecodeThreads); 51 decode_threads = std::min(decode_threads, kMaxDecodeThreads);
51 return decode_threads; 52 return decode_threads;
52 } 53 }
53 54
54 FFmpegVideoDecoder::FFmpegVideoDecoder(MessageLoop* message_loop) 55 FFmpegVideoDecoder::FFmpegVideoDecoder(
55 : message_loop_(message_loop), 56 const base::Callback<MessageLoop*()>& message_loop_cb)
57 : message_loop_cb_(message_loop_cb),
58 message_loop_(NULL),
56 state_(kUninitialized), 59 state_(kUninitialized),
57 codec_context_(NULL), 60 codec_context_(NULL),
58 av_frame_(NULL), 61 av_frame_(NULL),
59 frame_rate_numerator_(0), 62 frame_rate_numerator_(0),
60 frame_rate_denominator_(0) { 63 frame_rate_denominator_(0) {
61 } 64 }
62 65
63 FFmpegVideoDecoder::~FFmpegVideoDecoder() { 66 FFmpegVideoDecoder::~FFmpegVideoDecoder() {
64 ReleaseFFmpegResources(); 67 ReleaseFFmpegResources();
65 } 68 }
66 69
67 void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, 70 void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream,
68 const PipelineStatusCB& callback, 71 const PipelineStatusCB& callback,
69 const StatisticsCallback& stats_callback) { 72 const StatisticsCallback& stats_callback) {
73 message_loop_ = message_loop_cb_.Run();
Ami GONE FROM CHROMIUM 2012/03/09 16:15:06 add message_loop_cb_.Reset(); for clarity after th
tommi (sloooow) - chröme 2012/03/11 18:49:36 Done.
70 if (MessageLoop::current() != message_loop_) { 74 if (MessageLoop::current() != message_loop_) {
71 message_loop_->PostTask(FROM_HERE, base::Bind( 75 message_loop_->PostTask(FROM_HERE,
72 &FFmpegVideoDecoder::Initialize, this, 76 base::Bind(&FFmpegVideoDecoder::Initialize, this,
Ami GONE FROM CHROMIUM 2012/03/09 16:15:06 This indentation violates the google style guide.
tommi (sloooow) - chröme 2012/03/11 18:49:36 Done.
73 make_scoped_refptr(demuxer_stream), callback, stats_callback)); 77 make_scoped_refptr(demuxer_stream), callback,
78 stats_callback));
74 return; 79 return;
75 } 80 }
76 81
77 DCHECK(!demuxer_stream_); 82 DCHECK(!demuxer_stream_);
78 83
79 if (!demuxer_stream) { 84 if (!demuxer_stream) {
80 callback.Run(PIPELINE_ERROR_DECODE); 85 callback.Run(PIPELINE_ERROR_DECODE);
81 return; 86 return;
82 } 87 }
83 88
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 state_ = kNormal; 124 state_ = kNormal;
120 av_frame_ = avcodec_alloc_frame(); 125 av_frame_ = avcodec_alloc_frame();
121 natural_size_ = config.natural_size(); 126 natural_size_ = config.natural_size();
122 frame_rate_numerator_ = config.frame_rate_numerator(); 127 frame_rate_numerator_ = config.frame_rate_numerator();
123 frame_rate_denominator_ = config.frame_rate_denominator(); 128 frame_rate_denominator_ = config.frame_rate_denominator();
124 callback.Run(PIPELINE_OK); 129 callback.Run(PIPELINE_OK);
125 } 130 }
126 131
127 void FFmpegVideoDecoder::Stop(const base::Closure& callback) { 132 void FFmpegVideoDecoder::Stop(const base::Closure& callback) {
128 if (MessageLoop::current() != message_loop_) { 133 if (MessageLoop::current() != message_loop_) {
129 message_loop_->PostTask(FROM_HERE, base::Bind( 134 message_loop_->PostTask(FROM_HERE,
130 &FFmpegVideoDecoder::Stop, this, callback)); 135 base::Bind(&FFmpegVideoDecoder::Stop, this, callback));
131 return; 136 return;
132 } 137 }
133 138
134 ReleaseFFmpegResources(); 139 ReleaseFFmpegResources();
135 state_ = kUninitialized; 140 state_ = kUninitialized;
136 callback.Run(); 141 callback.Run();
137 } 142 }
138 143
139 void FFmpegVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { 144 void FFmpegVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) {
140 if (MessageLoop::current() != message_loop_) { 145 if (MessageLoop::current() != message_loop_) {
141 message_loop_->PostTask(FROM_HERE, base::Bind( 146 message_loop_->PostTask(FROM_HERE,
142 &FFmpegVideoDecoder::Seek, this, time, cb)); 147 base::Bind(&FFmpegVideoDecoder::Seek, this, time, cb));
143 return; 148 return;
144 } 149 }
145 150
146 cb.Run(PIPELINE_OK); 151 cb.Run(PIPELINE_OK);
147 } 152 }
148 153
149 void FFmpegVideoDecoder::Pause(const base::Closure& callback) { 154 void FFmpegVideoDecoder::Pause(const base::Closure& callback) {
150 if (MessageLoop::current() != message_loop_) { 155 if (MessageLoop::current() != message_loop_) {
151 message_loop_->PostTask(FROM_HERE, base::Bind( 156 message_loop_->PostTask(FROM_HERE,
152 &FFmpegVideoDecoder::Pause, this, callback)); 157 base::Bind(&FFmpegVideoDecoder::Pause, this, callback));
153 return; 158 return;
154 } 159 }
155 160
156 callback.Run(); 161 callback.Run();
157 } 162 }
158 163
159 void FFmpegVideoDecoder::Flush(const base::Closure& callback) { 164 void FFmpegVideoDecoder::Flush(const base::Closure& callback) {
160 if (MessageLoop::current() != message_loop_) { 165 if (MessageLoop::current() != message_loop_) {
161 message_loop_->PostTask(FROM_HERE, base::Bind( 166 message_loop_->PostTask(FROM_HERE,
162 &FFmpegVideoDecoder::Flush, this, callback)); 167 base::Bind(&FFmpegVideoDecoder::Flush, this, callback));
163 return; 168 return;
164 } 169 }
165 170
166 avcodec_flush_buffers(codec_context_); 171 avcodec_flush_buffers(codec_context_);
167 state_ = kNormal; 172 state_ = kNormal;
168 callback.Run(); 173 callback.Run();
169 } 174 }
170 175
171 void FFmpegVideoDecoder::Read(const ReadCB& callback) { 176 void FFmpegVideoDecoder::Read(const ReadCB& callback) {
172 // Complete operation asynchronously on different stack of execution as per 177 // Complete operation asynchronously on different stack of execution as per
173 // the API contract of VideoDecoder::Read() 178 // the API contract of VideoDecoder::Read()
174 message_loop_->PostTask(FROM_HERE, base::Bind( 179 message_loop_->PostTask(FROM_HERE,
175 &FFmpegVideoDecoder::DoRead, this, callback)); 180 base::Bind(&FFmpegVideoDecoder::DoRead, this, callback));
176 } 181 }
177 182
178 const gfx::Size& FFmpegVideoDecoder::natural_size() { 183 const gfx::Size& FFmpegVideoDecoder::natural_size() {
179 return natural_size_; 184 return natural_size_;
180 } 185 }
181 186
182 void FFmpegVideoDecoder::DoRead(const ReadCB& callback) { 187 void FFmpegVideoDecoder::DoRead(const ReadCB& callback) {
183 DCHECK_EQ(MessageLoop::current(), message_loop_); 188 DCHECK_EQ(MessageLoop::current(), message_loop_);
184 DCHECK(!callback.is_null()); 189 DCHECK(!callback.is_null());
185 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; 190 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
(...skipping 18 matching lines...) Expand all
204 DCHECK_NE(state_, kUninitialized); 209 DCHECK_NE(state_, kUninitialized);
205 DCHECK_NE(state_, kDecodeFinished); 210 DCHECK_NE(state_, kDecodeFinished);
206 DCHECK(!read_cb_.is_null()); 211 DCHECK(!read_cb_.is_null());
207 212
208 demuxer_stream_->Read(base::Bind(&FFmpegVideoDecoder::DecodeBuffer, this)); 213 demuxer_stream_->Read(base::Bind(&FFmpegVideoDecoder::DecodeBuffer, this));
209 } 214 }
210 215
211 void FFmpegVideoDecoder::DecodeBuffer(const scoped_refptr<Buffer>& buffer) { 216 void FFmpegVideoDecoder::DecodeBuffer(const scoped_refptr<Buffer>& buffer) {
212 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read 217 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read
213 // callback on the same execution stack so we can get rid of forced task post. 218 // callback on the same execution stack so we can get rid of forced task post.
214 message_loop_->PostTask(FROM_HERE, base::Bind( 219 message_loop_->PostTask(FROM_HERE,
215 &FFmpegVideoDecoder::DoDecodeBuffer, this, buffer)); 220 base::Bind(&FFmpegVideoDecoder::DoDecodeBuffer, this, buffer));
216 } 221 }
217 222
218 void FFmpegVideoDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& buffer) { 223 void FFmpegVideoDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& buffer) {
219 DCHECK_EQ(MessageLoop::current(), message_loop_); 224 DCHECK_EQ(MessageLoop::current(), message_loop_);
220 DCHECK_NE(state_, kUninitialized); 225 DCHECK_NE(state_, kUninitialized);
221 DCHECK_NE(state_, kDecodeFinished); 226 DCHECK_NE(state_, kDecodeFinished);
222 DCHECK(!read_cb_.is_null()); 227 DCHECK(!read_cb_.is_null());
223 228
224 if (!buffer) { 229 if (!buffer) {
225 DeliverFrame(NULL); 230 DeliverFrame(NULL);
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 scoped_refptr<VideoFrame> FFmpegVideoDecoder::AllocateVideoFrame() { 422 scoped_refptr<VideoFrame> FFmpegVideoDecoder::AllocateVideoFrame() {
418 VideoFrame::Format format = PixelFormatToVideoFormat(codec_context_->pix_fmt); 423 VideoFrame::Format format = PixelFormatToVideoFormat(codec_context_->pix_fmt);
419 size_t width = codec_context_->width; 424 size_t width = codec_context_->width;
420 size_t height = codec_context_->height; 425 size_t height = codec_context_->height;
421 426
422 return VideoFrame::CreateFrame(format, width, height, 427 return VideoFrame::CreateFrame(format, width, height,
423 kNoTimestamp(), kNoTimestamp()); 428 kNoTimestamp(), kNoTimestamp());
424 } 429 }
425 430
426 } // namespace media 431 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698