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

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

Issue 10855051: Use enum instead of string in MessageLoopFactory::GetMessageLoop* (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Resolve comments. Created 8 years, 4 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 <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback_helpers.h" 11 #include "base/callback_helpers.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/message_loop.h" 13 #include "base/location.h"
14 #include "base/message_loop_proxy.h"
14 #include "base/string_number_conversions.h" 15 #include "base/string_number_conversions.h"
15 #include "media/base/decoder_buffer.h" 16 #include "media/base/decoder_buffer.h"
16 #include "media/base/demuxer_stream.h" 17 #include "media/base/demuxer_stream.h"
17 #include "media/base/limits.h" 18 #include "media/base/limits.h"
18 #include "media/base/media_switches.h" 19 #include "media/base/media_switches.h"
19 #include "media/base/pipeline.h" 20 #include "media/base/pipeline.h"
20 #include "media/base/video_decoder_config.h" 21 #include "media/base/video_decoder_config.h"
21 #include "media/base/video_frame.h" 22 #include "media/base/video_frame.h"
22 #include "media/base/video_util.h" 23 #include "media/base/video_util.h"
23 #include "media/ffmpeg/ffmpeg_common.h" 24 #include "media/ffmpeg/ffmpeg_common.h"
(...skipping 22 matching lines...) Expand all
46 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 47 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
47 std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads)); 48 std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads));
48 if (threads.empty() || !base::StringToInt(threads, &decode_threads)) 49 if (threads.empty() || !base::StringToInt(threads, &decode_threads))
49 return decode_threads; 50 return decode_threads;
50 51
51 decode_threads = std::max(decode_threads, 0); 52 decode_threads = std::max(decode_threads, 0);
52 decode_threads = std::min(decode_threads, kMaxDecodeThreads); 53 decode_threads = std::min(decode_threads, kMaxDecodeThreads);
53 return decode_threads; 54 return decode_threads;
54 } 55 }
55 56
56 FFmpegVideoDecoder::FFmpegVideoDecoder( 57 FFmpegVideoDecoder::FFmpegVideoDecoder(const MessageLoopCB& message_loop_cb,
57 const base::Callback<MessageLoop*()>& message_loop_cb, 58 Decryptor* decryptor)
58 Decryptor* decryptor)
59 : message_loop_factory_cb_(message_loop_cb), 59 : message_loop_factory_cb_(message_loop_cb),
60 message_loop_(NULL), 60 message_loop_(NULL),
61 state_(kUninitialized), 61 state_(kUninitialized),
62 codec_context_(NULL), 62 codec_context_(NULL),
63 av_frame_(NULL), 63 av_frame_(NULL),
64 decryptor_(decryptor) { 64 decryptor_(decryptor) {
65 } 65 }
66 66
67 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context, 67 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context,
68 AVFrame* frame) { 68 AVFrame* frame) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 frame->opaque = NULL; 132 frame->opaque = NULL;
133 } 133 }
134 134
135 void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, 135 void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
136 const PipelineStatusCB& status_cb, 136 const PipelineStatusCB& status_cb,
137 const StatisticsCB& statistics_cb) { 137 const StatisticsCB& statistics_cb) {
138 // Ensure FFmpeg has been initialized 138 // Ensure FFmpeg has been initialized
139 FFmpegGlue::GetInstance(); 139 FFmpegGlue::GetInstance();
140 140
141 if (!message_loop_) { 141 if (!message_loop_) {
142 message_loop_ = message_loop_factory_cb_.Run(); 142 message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run();
143 message_loop_factory_cb_.Reset();
144
145 message_loop_->PostTask(FROM_HERE, base::Bind( 143 message_loop_->PostTask(FROM_HERE, base::Bind(
146 &FFmpegVideoDecoder::Initialize, this, 144 &FFmpegVideoDecoder::Initialize, this,
147 stream, status_cb, statistics_cb)); 145 stream, status_cb, statistics_cb));
148 return; 146 return;
149 } 147 }
150 148
151 DCHECK_EQ(MessageLoop::current(), message_loop_); 149 DCHECK(message_loop_->BelongsToCurrentThread());
152 DCHECK(!demuxer_stream_); 150 DCHECK(!demuxer_stream_);
153 151
154 if (!stream) { 152 if (!stream) {
155 status_cb.Run(PIPELINE_ERROR_DECODE); 153 status_cb.Run(PIPELINE_ERROR_DECODE);
156 return; 154 return;
157 } 155 }
158 156
159 demuxer_stream_ = stream; 157 demuxer_stream_ = stream;
160 statistics_cb_ = statistics_cb; 158 statistics_cb_ = statistics_cb;
161 159
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 } 199 }
202 200
203 void FFmpegVideoDecoder::Read(const ReadCB& read_cb) { 201 void FFmpegVideoDecoder::Read(const ReadCB& read_cb) {
204 // Complete operation asynchronously on different stack of execution as per 202 // Complete operation asynchronously on different stack of execution as per
205 // the API contract of VideoDecoder::Read() 203 // the API contract of VideoDecoder::Read()
206 message_loop_->PostTask(FROM_HERE, base::Bind( 204 message_loop_->PostTask(FROM_HERE, base::Bind(
207 &FFmpegVideoDecoder::DoRead, this, read_cb)); 205 &FFmpegVideoDecoder::DoRead, this, read_cb));
208 } 206 }
209 207
210 void FFmpegVideoDecoder::Reset(const base::Closure& closure) { 208 void FFmpegVideoDecoder::Reset(const base::Closure& closure) {
211 if (MessageLoop::current() != message_loop_) { 209 if (!message_loop_->BelongsToCurrentThread()) {
212 message_loop_->PostTask(FROM_HERE, base::Bind( 210 message_loop_->PostTask(FROM_HERE, base::Bind(
213 &FFmpegVideoDecoder::Reset, this, closure)); 211 &FFmpegVideoDecoder::Reset, this, closure));
214 return; 212 return;
215 } 213 }
216 214
217 reset_cb_ = closure; 215 reset_cb_ = closure;
218 216
219 // Defer the reset if a read is pending. 217 // Defer the reset if a read is pending.
220 if (!read_cb_.is_null()) 218 if (!read_cb_.is_null())
221 return; 219 return;
222 220
223 DoReset(); 221 DoReset();
224 } 222 }
225 223
226 void FFmpegVideoDecoder::DoReset() { 224 void FFmpegVideoDecoder::DoReset() {
227 DCHECK(read_cb_.is_null()); 225 DCHECK(read_cb_.is_null());
228 226
229 avcodec_flush_buffers(codec_context_); 227 avcodec_flush_buffers(codec_context_);
230 state_ = kNormal; 228 state_ = kNormal;
231 reset_cb_.Run(); 229 reset_cb_.Run();
232 reset_cb_.Reset(); 230 reset_cb_.Reset();
233 } 231 }
234 232
235 void FFmpegVideoDecoder::Stop(const base::Closure& closure) { 233 void FFmpegVideoDecoder::Stop(const base::Closure& closure) {
236 if (MessageLoop::current() != message_loop_) { 234 if (!message_loop_->BelongsToCurrentThread()) {
237 message_loop_->PostTask(FROM_HERE, base::Bind( 235 message_loop_->PostTask(FROM_HERE, base::Bind(
238 &FFmpegVideoDecoder::Stop, this, closure)); 236 &FFmpegVideoDecoder::Stop, this, closure));
239 return; 237 return;
240 } 238 }
241 239
242 if (decryptor_) 240 if (decryptor_)
243 decryptor_->Stop(); 241 decryptor_->Stop();
244 242
245 stop_cb_ = closure; 243 stop_cb_ = closure;
246 244
247 // Defer stopping if a read is pending. 245 // Defer stopping if a read is pending.
248 if (!read_cb_.is_null()) 246 if (!read_cb_.is_null())
249 return; 247 return;
250 248
251 DoStop(); 249 DoStop();
252 } 250 }
253 251
254 void FFmpegVideoDecoder::DoStop() { 252 void FFmpegVideoDecoder::DoStop() {
255 ReleaseFFmpegResources(); 253 ReleaseFFmpegResources();
256 state_ = kUninitialized; 254 state_ = kUninitialized;
257 base::ResetAndReturn(&stop_cb_).Run(); 255 base::ResetAndReturn(&stop_cb_).Run();
258 } 256 }
259 257
260 FFmpegVideoDecoder::~FFmpegVideoDecoder() { 258 FFmpegVideoDecoder::~FFmpegVideoDecoder() {
261 ReleaseFFmpegResources(); 259 ReleaseFFmpegResources();
262 } 260 }
263 261
264 void FFmpegVideoDecoder::DoRead(const ReadCB& read_cb) { 262 void FFmpegVideoDecoder::DoRead(const ReadCB& read_cb) {
265 DCHECK_EQ(MessageLoop::current(), message_loop_); 263 DCHECK(message_loop_->BelongsToCurrentThread());
266 DCHECK(!read_cb.is_null()); 264 DCHECK(!read_cb.is_null());
267 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; 265 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
268 266
269 // This can happen during shutdown after Stop() has been called. 267 // This can happen during shutdown after Stop() has been called.
270 if (state_ == kUninitialized) { 268 if (state_ == kUninitialized) {
271 return; 269 return;
272 } 270 }
273 271
274 // Return empty frames if decoding has finished. 272 // Return empty frames if decoding has finished.
275 if (state_ == kDecodeFinished) { 273 if (state_ == kDecodeFinished) {
(...skipping 21 matching lines...) Expand all
297 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; 295 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status;
298 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read 296 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read
299 // callback on the same execution stack so we can get rid of forced task post. 297 // callback on the same execution stack so we can get rid of forced task post.
300 message_loop_->PostTask(FROM_HERE, base::Bind( 298 message_loop_->PostTask(FROM_HERE, base::Bind(
301 &FFmpegVideoDecoder::DoDecryptOrDecodeBuffer, this, status, buffer)); 299 &FFmpegVideoDecoder::DoDecryptOrDecodeBuffer, this, status, buffer));
302 } 300 }
303 301
304 void FFmpegVideoDecoder::DoDecryptOrDecodeBuffer( 302 void FFmpegVideoDecoder::DoDecryptOrDecodeBuffer(
305 DemuxerStream::Status status, 303 DemuxerStream::Status status,
306 const scoped_refptr<DecoderBuffer>& buffer) { 304 const scoped_refptr<DecoderBuffer>& buffer) {
307 DCHECK_EQ(MessageLoop::current(), message_loop_); 305 DCHECK(message_loop_->BelongsToCurrentThread());
308 DCHECK_NE(state_, kUninitialized); 306 DCHECK_NE(state_, kUninitialized);
309 DCHECK_NE(state_, kDecodeFinished); 307 DCHECK_NE(state_, kDecodeFinished);
310 DCHECK(!read_cb_.is_null()); 308 DCHECK(!read_cb_.is_null());
311 309
312 if (!stop_cb_.is_null()) { 310 if (!stop_cb_.is_null()) {
313 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 311 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
314 DoStop(); 312 DoStop();
315 return; 313 return;
316 } 314 }
317 315
(...skipping 24 matching lines...) Expand all
342 void FFmpegVideoDecoder::BufferDecrypted( 340 void FFmpegVideoDecoder::BufferDecrypted(
343 Decryptor::Status decrypt_status, 341 Decryptor::Status decrypt_status,
344 const scoped_refptr<DecoderBuffer>& buffer) { 342 const scoped_refptr<DecoderBuffer>& buffer) {
345 message_loop_->PostTask(FROM_HERE, base::Bind( 343 message_loop_->PostTask(FROM_HERE, base::Bind(
346 &FFmpegVideoDecoder::DoBufferDecrypted, this, decrypt_status, buffer)); 344 &FFmpegVideoDecoder::DoBufferDecrypted, this, decrypt_status, buffer));
347 } 345 }
348 346
349 void FFmpegVideoDecoder::DoBufferDecrypted( 347 void FFmpegVideoDecoder::DoBufferDecrypted(
350 Decryptor::Status decrypt_status, 348 Decryptor::Status decrypt_status,
351 const scoped_refptr<DecoderBuffer>& buffer) { 349 const scoped_refptr<DecoderBuffer>& buffer) {
352 DCHECK_EQ(MessageLoop::current(), message_loop_); 350 DCHECK(message_loop_->BelongsToCurrentThread());
353 DCHECK_NE(state_, kUninitialized); 351 DCHECK_NE(state_, kUninitialized);
354 DCHECK_NE(state_, kDecodeFinished); 352 DCHECK_NE(state_, kDecodeFinished);
355 DCHECK(!read_cb_.is_null()); 353 DCHECK(!read_cb_.is_null());
356 354
357 if (!reset_cb_.is_null()) { 355 if (!reset_cb_.is_null()) {
358 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 356 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
359 DoReset(); 357 DoReset();
360 return; 358 return;
361 } 359 }
362 360
363 if (decrypt_status == Decryptor::kNoKey || 361 if (decrypt_status == Decryptor::kNoKey ||
364 decrypt_status == Decryptor::kError) { 362 decrypt_status == Decryptor::kError) {
365 state_ = kDecodeFinished; 363 state_ = kDecodeFinished;
366 base::ResetAndReturn(&read_cb_).Run(kDecryptError, NULL); 364 base::ResetAndReturn(&read_cb_).Run(kDecryptError, NULL);
367 return; 365 return;
368 } 366 }
369 367
370 DCHECK_EQ(Decryptor::kSuccess, decrypt_status); 368 DCHECK_EQ(Decryptor::kSuccess, decrypt_status);
371 DCHECK(buffer); 369 DCHECK(buffer);
372 DCHECK(buffer->GetDataSize()); 370 DCHECK(buffer->GetDataSize());
373 DCHECK(!buffer->GetDecryptConfig()); 371 DCHECK(!buffer->GetDecryptConfig());
374 DecodeBuffer(buffer); 372 DecodeBuffer(buffer);
375 } 373 }
376 374
377 void FFmpegVideoDecoder::DecodeBuffer( 375 void FFmpegVideoDecoder::DecodeBuffer(
378 const scoped_refptr<DecoderBuffer>& buffer) { 376 const scoped_refptr<DecoderBuffer>& buffer) {
379 DCHECK_EQ(MessageLoop::current(), message_loop_); 377 DCHECK(message_loop_->BelongsToCurrentThread());
380 DCHECK_NE(state_, kUninitialized); 378 DCHECK_NE(state_, kUninitialized);
381 DCHECK_NE(state_, kDecodeFinished); 379 DCHECK_NE(state_, kDecodeFinished);
382 DCHECK(reset_cb_.is_null()); 380 DCHECK(reset_cb_.is_null());
383 DCHECK(!read_cb_.is_null()); 381 DCHECK(!read_cb_.is_null());
384 DCHECK(buffer); 382 DCHECK(buffer);
385 383
386 // During decode, because reads are issued asynchronously, it is possible to 384 // During decode, because reads are issued asynchronously, it is possible to
387 // receive multiple end of stream buffers since each read is acked. When the 385 // receive multiple end of stream buffers since each read is acked. When the
388 // first end of stream buffer is read, FFmpeg may still have frames queued 386 // first end of stream buffer is read, FFmpeg may still have frames queued
389 // up in the decoder so we need to go through the decode loop until it stops 387 // up in the decoder so we need to go through the decode loop until it stops
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 av_free(codec_context_); 517 av_free(codec_context_);
520 codec_context_ = NULL; 518 codec_context_ = NULL;
521 } 519 }
522 if (av_frame_) { 520 if (av_frame_) {
523 av_free(av_frame_); 521 av_free(av_frame_);
524 av_frame_ = NULL; 522 av_frame_ = NULL;
525 } 523 }
526 } 524 }
527 525
528 } // namespace media 526 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698