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 |