| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/video/ffmpeg_video_decode_engine.h" | 5 #include "media/video/ffmpeg_video_decode_engine.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/string_number_conversions.h" | 8 #include "base/string_number_conversions.h" |
| 9 #include "base/task.h" | 9 #include "base/task.h" |
| 10 #include "media/base/buffers.h" | 10 #include "media/base/buffers.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 // performance benefits on older machines such as P4s with hyperthreading. | 43 // performance benefits on older machines such as P4s with hyperthreading. |
| 44 // | 44 // |
| 45 // Handling decoding on separate threads also frees up the pipeline thread to | 45 // Handling decoding on separate threads also frees up the pipeline thread to |
| 46 // continue processing. Although it'd be nice to have the option of a single | 46 // continue processing. Although it'd be nice to have the option of a single |
| 47 // decoding thread, FFmpeg treats having one thread the same as having zero | 47 // decoding thread, FFmpeg treats having one thread the same as having zero |
| 48 // threads (i.e., avcodec_decode_video() will execute on the calling thread). | 48 // threads (i.e., avcodec_decode_video() will execute on the calling thread). |
| 49 // Yet another reason for having two threads :) | 49 // Yet another reason for having two threads :) |
| 50 static const int kDecodeThreads = 2; | 50 static const int kDecodeThreads = 2; |
| 51 static const int kMaxDecodeThreads = 16; | 51 static const int kMaxDecodeThreads = 16; |
| 52 | 52 |
| 53 av_stream_ = static_cast<AVStream*>(config.opaque_context_); | 53 av_stream_ = static_cast<AVStream*>(config.opaque_context); |
| 54 codec_context_ = av_stream_->codec; | 54 codec_context_ = av_stream_->codec; |
| 55 // Enable motion vector search (potentially slow), strong deblocking filter | 55 // Enable motion vector search (potentially slow), strong deblocking filter |
| 56 // for damaged macroblocks, and set our error detection sensitivity. | 56 // for damaged macroblocks, and set our error detection sensitivity. |
| 57 codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; | 57 codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; |
| 58 codec_context_->error_recognition = FF_ER_CAREFUL; | 58 codec_context_->error_recognition = FF_ER_CAREFUL; |
| 59 | 59 |
| 60 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 60 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
| 61 | 61 |
| 62 if (codec) { | 62 if (codec) { |
| 63 #ifdef FF_THREAD_FRAME // Only defined in FFMPEG-MT. | 63 #ifdef FF_THREAD_FRAME // Only defined in FFMPEG-MT. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 80 !base::StringToInt(threads, &decode_threads)) || | 80 !base::StringToInt(threads, &decode_threads)) || |
| 81 decode_threads < 0 || decode_threads > kMaxDecodeThreads) { | 81 decode_threads < 0 || decode_threads > kMaxDecodeThreads) { |
| 82 decode_threads = kDecodeThreads; | 82 decode_threads = kDecodeThreads; |
| 83 } | 83 } |
| 84 | 84 |
| 85 // We don't allocate AVFrame on the stack since different versions of FFmpeg | 85 // We don't allocate AVFrame on the stack since different versions of FFmpeg |
| 86 // may change the size of AVFrame, causing stack corruption. The solution is | 86 // may change the size of AVFrame, causing stack corruption. The solution is |
| 87 // to let FFmpeg allocate the structure via avcodec_alloc_frame(). | 87 // to let FFmpeg allocate the structure via avcodec_alloc_frame(). |
| 88 av_frame_.reset(avcodec_alloc_frame()); | 88 av_frame_.reset(avcodec_alloc_frame()); |
| 89 VideoCodecInfo info; | 89 VideoCodecInfo info; |
| 90 info.success_ = false; | 90 info.success = false; |
| 91 info.provides_buffers_ = true; | 91 info.provides_buffers = true; |
| 92 info.stream_info_.surface_type_ = VideoFrame::TYPE_SYSTEM_MEMORY; | 92 info.stream_info.surface_type = VideoFrame::TYPE_SYSTEM_MEMORY; |
| 93 info.stream_info_.surface_format_ = GetSurfaceFormat(); | 93 info.stream_info.surface_format = GetSurfaceFormat(); |
| 94 info.stream_info_.surface_width_ = config.width_; | 94 info.stream_info.surface_width = config.width; |
| 95 info.stream_info_.surface_height_ = config.height_; | 95 info.stream_info.surface_height = config.height; |
| 96 | 96 |
| 97 // If we do not have enough buffers, we will report error too. | 97 // If we do not have enough buffers, we will report error too. |
| 98 bool buffer_allocated = true; | 98 bool buffer_allocated = true; |
| 99 frame_queue_available_.clear(); | 99 frame_queue_available_.clear(); |
| 100 if (!direct_rendering_) { | 100 if (!direct_rendering_) { |
| 101 // Create output buffer pool when direct rendering is not used. | 101 // Create output buffer pool when direct rendering is not used. |
| 102 for (size_t i = 0; i < Limits::kMaxVideoFrames; ++i) { | 102 for (size_t i = 0; i < Limits::kMaxVideoFrames; ++i) { |
| 103 scoped_refptr<VideoFrame> video_frame; | 103 scoped_refptr<VideoFrame> video_frame; |
| 104 VideoFrame::CreateFrame(VideoFrame::YV12, | 104 VideoFrame::CreateFrame(VideoFrame::YV12, |
| 105 config.width_, | 105 config.width, |
| 106 config.height_, | 106 config.height, |
| 107 StreamSample::kInvalidTimestamp, | 107 StreamSample::kInvalidTimestamp, |
| 108 StreamSample::kInvalidTimestamp, | 108 StreamSample::kInvalidTimestamp, |
| 109 &video_frame); | 109 &video_frame); |
| 110 if (!video_frame.get()) { | 110 if (!video_frame.get()) { |
| 111 buffer_allocated = false; | 111 buffer_allocated = false; |
| 112 break; | 112 break; |
| 113 } | 113 } |
| 114 frame_queue_available_.push_back(video_frame); | 114 frame_queue_available_.push_back(video_frame); |
| 115 } | 115 } |
| 116 } | 116 } |
| 117 | 117 |
| 118 if (codec && | 118 if (codec && |
| 119 avcodec_thread_init(codec_context_, decode_threads) >= 0 && | 119 avcodec_thread_init(codec_context_, decode_threads) >= 0 && |
| 120 avcodec_open(codec_context_, codec) >= 0 && | 120 avcodec_open(codec_context_, codec) >= 0 && |
| 121 av_frame_.get() && | 121 av_frame_.get() && |
| 122 buffer_allocated) { | 122 buffer_allocated) { |
| 123 info.success_ = true; | 123 info.success = true; |
| 124 } | 124 } |
| 125 event_handler_ = event_handler; | 125 event_handler_ = event_handler; |
| 126 event_handler_->OnInitializeComplete(info); | 126 event_handler_->OnInitializeComplete(info); |
| 127 } | 127 } |
| 128 | 128 |
| 129 // TODO(fbarchard): Find way to remove this memcpy of the entire image. | 129 // TODO(fbarchard): Find way to remove this memcpy of the entire image. |
| 130 static void CopyPlane(size_t plane, | 130 static void CopyPlane(size_t plane, |
| 131 scoped_refptr<VideoFrame> video_frame, | 131 scoped_refptr<VideoFrame> video_frame, |
| 132 const AVFrame* frame) { | 132 const AVFrame* frame) { |
| 133 DCHECK_EQ(video_frame->width() % 2, 0u); | 133 DCHECK_EQ(video_frame->width() % 2, 0u); |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 // TODO(scherkus): More formats here? | 355 // TODO(scherkus): More formats here? |
| 356 return VideoFrame::INVALID; | 356 return VideoFrame::INVALID; |
| 357 } | 357 } |
| 358 } | 358 } |
| 359 | 359 |
| 360 } // namespace media | 360 } // namespace media |
| 361 | 361 |
| 362 // Disable refcounting for this object because this object only lives | 362 // Disable refcounting for this object because this object only lives |
| 363 // on the video decoder thread and there's no need to refcount it. | 363 // on the video decoder thread and there's no need to refcount it. |
| 364 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::FFmpegVideoDecodeEngine); | 364 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::FFmpegVideoDecodeEngine); |
| OLD | NEW |