Chromium Code Reviews| 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_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" |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 #include "media/base/video_decoder_config.h" | 21 #include "media/base/video_decoder_config.h" |
| 22 #include "media/base/video_frame.h" | 22 #include "media/base/video_frame.h" |
| 23 #include "media/base/video_util.h" | 23 #include "media/base/video_util.h" |
| 24 #include "media/ffmpeg/ffmpeg_common.h" | 24 #include "media/ffmpeg/ffmpeg_common.h" |
| 25 #include "media/filters/ffmpeg_glue.h" | 25 #include "media/filters/ffmpeg_glue.h" |
| 26 | 26 |
| 27 namespace media { | 27 namespace media { |
| 28 | 28 |
| 29 // Always try to use three threads for video decoding. There is little reason | 29 // Always try to use three threads for video decoding. There is little reason |
| 30 // not to since current day CPUs tend to be multi-core and we measured | 30 // not to since current day CPUs tend to be multi-core and we measured |
| 31 // performance benefits on older machines such as P4s with hyperthreading. | 31 // performance benefits on older machines such as P4s with hyperthreading. |
|
Ami GONE FROM CHROMIUM
2014/01/28 07:17:10
Oh, wow, this is some vintage comment.
(since it w
| |
| 32 // | 32 // |
| 33 // Handling decoding on separate threads also frees up the pipeline thread to | 33 // Handling decoding on separate threads also frees up the pipeline thread to |
| 34 // continue processing. Although it'd be nice to have the option of a single | 34 // continue processing. Although it'd be nice to have the option of a single |
| 35 // decoding thread, FFmpeg treats having one thread the same as having zero | 35 // decoding thread, FFmpeg treats having one thread the same as having zero |
| 36 // threads (i.e., avcodec_decode_video() will execute on the calling thread). | 36 // threads (i.e., avcodec_decode_video() will execute on the calling thread). |
| 37 // Yet another reason for having two threads :) | 37 // Yet another reason for having two threads :) |
| 38 static const int kDecodeThreads = 2; | 38 static const int kDecodeThreads = 2; |
| 39 static const int kMaxDecodeThreads = 16; | 39 static const int kMaxDecodeThreads = 16; |
| 40 | 40 |
| 41 // Returns the number of threads given the FFmpeg CodecID. Also inspects the | 41 // Returns the number of threads given the FFmpeg CodecID. Also inspects the |
| 42 // command line for a valid --video-threads flag. | 42 // command line for a valid --video-threads flag. |
| 43 static int GetThreadCount(AVCodecID codec_id) { | 43 static int GetThreadCount(AVCodecID codec_id) { |
| 44 // Refer to http://crbug.com/93932 for tsan suppressions on decoding. | 44 // Refer to http://crbug.com/93932 for tsan suppressions on decoding. |
| 45 int decode_threads = kDecodeThreads; | 45 int decode_threads = kDecodeThreads; |
| 46 | 46 |
| 47 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | 47 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
| 48 std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads)); | 48 std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads)); |
| 49 if (threads.empty() || !base::StringToInt(threads, &decode_threads)) | 49 if (threads.empty() || !base::StringToInt(threads, &decode_threads)) |
| 50 return decode_threads; | 50 return decode_threads; |
| 51 | 51 |
| 52 decode_threads = std::max(decode_threads, 0); | 52 decode_threads = std::max(decode_threads, 0); |
| 53 decode_threads = std::min(decode_threads, kMaxDecodeThreads); | 53 decode_threads = std::min(decode_threads, kMaxDecodeThreads); |
| 54 return decode_threads; | 54 return decode_threads; |
| 55 } | 55 } |
| 56 | 56 |
| 57 FFmpegVideoDecoder::FFmpegVideoDecoder( | 57 FFmpegVideoDecoder::FFmpegVideoDecoder( |
| 58 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 58 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 59 ThreadingMode threading_mode) | |
| 59 : task_runner_(task_runner), | 60 : task_runner_(task_runner), |
| 61 threading_mode_(threading_mode), | |
| 60 weak_factory_(this), | 62 weak_factory_(this), |
| 61 state_(kUninitialized) { | 63 state_(kUninitialized) { |
| 62 } | 64 } |
| 63 | 65 |
| 64 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context, | 66 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context, |
| 65 AVFrame* frame) { | 67 AVFrame* frame) { |
| 66 // Don't use |codec_context_| here! With threaded decoding, | 68 // Don't use |codec_context_| here! With threaded decoding, |
| 67 // it will contain unsynchronized width/height/pix_fmt values, | 69 // it will contain unsynchronized width/height/pix_fmt values, |
| 68 // whereas |codec_context| contains the current threads's | 70 // whereas |codec_context| contains the current threads's |
| 69 // updated width/height/pix_fmt, which can change for adaptive | 71 // updated width/height/pix_fmt, which can change for adaptive |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 362 ReleaseFFmpegResources(); | 364 ReleaseFFmpegResources(); |
| 363 | 365 |
| 364 // Initialize AVCodecContext structure. | 366 // Initialize AVCodecContext structure. |
| 365 codec_context_.reset(avcodec_alloc_context3(NULL)); | 367 codec_context_.reset(avcodec_alloc_context3(NULL)); |
| 366 VideoDecoderConfigToAVCodecContext(config_, codec_context_.get()); | 368 VideoDecoderConfigToAVCodecContext(config_, codec_context_.get()); |
| 367 | 369 |
| 368 // Enable motion vector search (potentially slow), strong deblocking filter | 370 // Enable motion vector search (potentially slow), strong deblocking filter |
| 369 // for damaged macroblocks, and set our error detection sensitivity. | 371 // for damaged macroblocks, and set our error detection sensitivity. |
| 370 codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; | 372 codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; |
| 371 codec_context_->thread_count = GetThreadCount(codec_context_->codec_id); | 373 codec_context_->thread_count = GetThreadCount(codec_context_->codec_id); |
| 374 codec_context_->thread_type = | |
| 375 threading_mode_ == THREADING_SLICE ? FF_THREAD_SLICE : FF_THREAD_FRAME; | |
| 372 codec_context_->opaque = this; | 376 codec_context_->opaque = this; |
| 373 codec_context_->flags |= CODEC_FLAG_EMU_EDGE; | 377 codec_context_->flags |= CODEC_FLAG_EMU_EDGE; |
| 374 codec_context_->get_buffer = GetVideoBufferImpl; | 378 codec_context_->get_buffer = GetVideoBufferImpl; |
| 375 codec_context_->release_buffer = ReleaseVideoBufferImpl; | 379 codec_context_->release_buffer = ReleaseVideoBufferImpl; |
| 376 | 380 |
| 377 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 381 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
| 378 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { | 382 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { |
| 379 ReleaseFFmpegResources(); | 383 ReleaseFFmpegResources(); |
| 380 return false; | 384 return false; |
| 381 } | 385 } |
| 382 | 386 |
| 383 av_frame_.reset(av_frame_alloc()); | 387 av_frame_.reset(av_frame_alloc()); |
| 384 return true; | 388 return true; |
| 385 } | 389 } |
| 386 | 390 |
| 387 } // namespace media | 391 } // namespace media |
| OLD | NEW |