diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-07 07:12:41 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-07 07:12:41 +0000 |
commit | e8d69ff6b29e372314d6e2677d363b80fed76390 (patch) | |
tree | d3d05ec22beae12ec5c7b9ef9de2b8736152e5d4 /media/video | |
parent | d8593a6d7b3b78cec81810c436762aebcbe7e166 (diff) | |
download | chromium_src-e8d69ff6b29e372314d6e2677d363b80fed76390.zip chromium_src-e8d69ff6b29e372314d6e2677d363b80fed76390.tar.gz chromium_src-e8d69ff6b29e372314d6e2677d363b80fed76390.tar.bz2 |
Collapse FFmpegVideoDecodeEngine into FFmpegVideoDecoder and remove VideoDecodeEngine.
Review URL: http://codereview.chromium.org/8772069
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113358 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/video')
-rw-r--r-- | media/video/ffmpeg_video_decode_engine.cc | 200 | ||||
-rw-r--r-- | media/video/ffmpeg_video_decode_engine.h | 46 | ||||
-rw-r--r-- | media/video/video_decode_engine.h | 45 |
3 files changed, 0 insertions, 291 deletions
diff --git a/media/video/ffmpeg_video_decode_engine.cc b/media/video/ffmpeg_video_decode_engine.cc deleted file mode 100644 index a6bff26..0000000 --- a/media/video/ffmpeg_video_decode_engine.cc +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/video/ffmpeg_video_decode_engine.h" - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/string_number_conversions.h" -#include "media/base/buffers.h" -#include "media/base/media_switches.h" -#include "media/base/video_decoder_config.h" -#include "media/base/video_util.h" -#include "media/ffmpeg/ffmpeg_common.h" - -namespace media { - -FFmpegVideoDecodeEngine::FFmpegVideoDecodeEngine() - : codec_context_(NULL), - av_frame_(NULL), - frame_rate_numerator_(0), - frame_rate_denominator_(0) { -} - -FFmpegVideoDecodeEngine::~FFmpegVideoDecodeEngine() { - Uninitialize(); -} - -bool FFmpegVideoDecodeEngine::Initialize(const VideoDecoderConfig& config) { - frame_rate_numerator_ = config.frame_rate_numerator(); - frame_rate_denominator_ = config.frame_rate_denominator(); - - // Always try to use three threads for video decoding. There is little reason - // not to since current day CPUs tend to be multi-core and we measured - // performance benefits on older machines such as P4s with hyperthreading. - // - // Handling decoding on separate threads also frees up the pipeline thread to - // continue processing. Although it'd be nice to have the option of a single - // decoding thread, FFmpeg treats having one thread the same as having zero - // threads (i.e., avcodec_decode_video() will execute on the calling thread). - // Yet another reason for having two threads :) - static const int kDecodeThreads = 2; - static const int kMaxDecodeThreads = 16; - - // Initialize AVCodecContext structure. - codec_context_ = avcodec_alloc_context(); - VideoDecoderConfigToAVCodecContext(config, codec_context_); - - // Enable motion vector search (potentially slow), strong deblocking filter - // for damaged macroblocks, and set our error detection sensitivity. - codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; - codec_context_->error_recognition = FF_ER_CAREFUL; - - AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); - - // TODO(fbarchard): Improve thread logic based on size / codec. - // TODO(fbarchard): Fix bug affecting video-cookie.html - // 07/21/11(ihf): Still about 20 failures when enabling. - int decode_threads = (codec_context_->codec_id == CODEC_ID_THEORA) ? - 1 : kDecodeThreads; - - const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); - std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads)); - if ((!threads.empty() && - !base::StringToInt(threads, &decode_threads)) || - decode_threads < 0 || decode_threads > kMaxDecodeThreads) { - decode_threads = kDecodeThreads; - } - - codec_context_->thread_count = decode_threads; - - av_frame_ = avcodec_alloc_frame(); - - // Open the codec! - return codec && avcodec_open(codec_context_, codec) >= 0; -} - -void FFmpegVideoDecodeEngine::Uninitialize() { - if (codec_context_) { - av_free(codec_context_->extradata); - avcodec_close(codec_context_); - av_free(codec_context_); - codec_context_ = NULL; - } - if (av_frame_) { - av_free(av_frame_); - av_frame_ = NULL; - } - frame_rate_numerator_ = 0; - frame_rate_denominator_ = 0; -} - -bool FFmpegVideoDecodeEngine::Decode(const scoped_refptr<Buffer>& buffer, - scoped_refptr<VideoFrame>* video_frame) { - DCHECK(video_frame); - - // Create a packet for input data. - // Due to FFmpeg API changes we no longer have const read-only pointers. - AVPacket packet; - av_init_packet(&packet); - packet.data = const_cast<uint8*>(buffer->GetData()); - packet.size = buffer->GetDataSize(); - - // Let FFmpeg handle presentation timestamp reordering. - codec_context_->reordered_opaque = buffer->GetTimestamp().InMicroseconds(); - - // This is for codecs not using get_buffer to initialize - // |av_frame_->reordered_opaque| - av_frame_->reordered_opaque = codec_context_->reordered_opaque; - - int frame_decoded = 0; - int result = avcodec_decode_video2(codec_context_, - av_frame_, - &frame_decoded, - &packet); - // Log the problem if we can't decode a video frame and exit early. - if (result < 0) { - LOG(ERROR) << "Error decoding a video frame with timestamp: " - << buffer->GetTimestamp().InMicroseconds() << " us, duration: " - << buffer->GetDuration().InMicroseconds() << " us, packet size: " - << buffer->GetDataSize() << " bytes"; - *video_frame = NULL; - return false; - } - - // If no frame was produced then signal that more data is required to - // produce more frames. This can happen under two circumstances: - // 1) Decoder was recently initialized/flushed - // 2) End of stream was reached and all internal frames have been output - if (frame_decoded == 0) { - *video_frame = NULL; - return true; - } - - // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675 - // The decoder is in a bad state and not decoding correctly. - // Checking for NULL avoids a crash in CopyPlane(). - if (!av_frame_->data[VideoFrame::kYPlane] || - !av_frame_->data[VideoFrame::kUPlane] || - !av_frame_->data[VideoFrame::kVPlane]) { - LOG(ERROR) << "Video frame was produced yet has invalid frame data."; - *video_frame = NULL; - return false; - } - - // We've got a frame! Make sure we have a place to store it. - *video_frame = AllocateVideoFrame(); - if (!(*video_frame)) { - LOG(ERROR) << "Failed to allocate video frame"; - return false; - } - - // Determine timestamp and calculate the duration based on the repeat picture - // count. According to FFmpeg docs, the total duration can be calculated as - // follows: - // fps = 1 / time_base - // - // duration = (1 / fps) + (repeat_pict) / (2 * fps) - // = (2 + repeat_pict) / (2 * fps) - // = (2 + repeat_pict) / (2 * (1 / time_base)) - DCHECK_LE(av_frame_->repeat_pict, 2); // Sanity check. - AVRational doubled_time_base; - doubled_time_base.num = frame_rate_denominator_; - doubled_time_base.den = frame_rate_numerator_ * 2; - - (*video_frame)->SetTimestamp( - base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque)); - (*video_frame)->SetDuration( - ConvertFromTimeBase(doubled_time_base, 2 + av_frame_->repeat_pict)); - - // Copy the frame data since FFmpeg reuses internal buffers for AVFrame - // output, meaning the data is only valid until the next - // avcodec_decode_video() call. - int y_rows = codec_context_->height; - int uv_rows = codec_context_->height; - if (codec_context_->pix_fmt == PIX_FMT_YUV420P) { - uv_rows /= 2; - } - - CopyYPlane(av_frame_->data[0], av_frame_->linesize[0], y_rows, *video_frame); - CopyUPlane(av_frame_->data[1], av_frame_->linesize[1], uv_rows, *video_frame); - CopyVPlane(av_frame_->data[2], av_frame_->linesize[2], uv_rows, *video_frame); - - return true; -} - -void FFmpegVideoDecodeEngine::Flush() { - avcodec_flush_buffers(codec_context_); -} - -scoped_refptr<VideoFrame> FFmpegVideoDecodeEngine::AllocateVideoFrame() { - VideoFrame::Format format = PixelFormatToVideoFormat(codec_context_->pix_fmt); - size_t width = codec_context_->width; - size_t height = codec_context_->height; - - return VideoFrame::CreateFrame(format, width, height, - kNoTimestamp, kNoTimestamp); -} - -} // namespace media diff --git a/media/video/ffmpeg_video_decode_engine.h b/media/video/ffmpeg_video_decode_engine.h deleted file mode 100644 index 072507a..0000000 --- a/media/video/ffmpeg_video_decode_engine.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_VIDEO_FFMPEG_VIDEO_DECODE_ENGINE_H_ -#define MEDIA_VIDEO_FFMPEG_VIDEO_DECODE_ENGINE_H_ - -#include "base/compiler_specific.h" -#include "media/video/video_decode_engine.h" - -struct AVCodecContext; -struct AVFrame; - -namespace media { - -class MEDIA_EXPORT FFmpegVideoDecodeEngine : public VideoDecodeEngine { - public: - FFmpegVideoDecodeEngine(); - virtual ~FFmpegVideoDecodeEngine(); - - // VideoDecodeEngine implementation. - virtual bool Initialize(const VideoDecoderConfig& config) OVERRIDE; - virtual void Uninitialize() OVERRIDE; - virtual bool Decode(const scoped_refptr<Buffer>& buffer, - scoped_refptr<VideoFrame>* video_frame) OVERRIDE; - virtual void Flush() OVERRIDE; - - private: - // Allocates a video frame based on the current format and dimensions based on - // the current state of |codec_context_|. - scoped_refptr<VideoFrame> AllocateVideoFrame(); - - // FFmpeg structures owned by this object. - AVCodecContext* codec_context_; - AVFrame* av_frame_; - - // Frame rate of the video. - int frame_rate_numerator_; - int frame_rate_denominator_; - - DISALLOW_COPY_AND_ASSIGN(FFmpegVideoDecodeEngine); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_FFMPEG_VIDEO_DECODE_ENGINE_H_ diff --git a/media/video/video_decode_engine.h b/media/video/video_decode_engine.h deleted file mode 100644 index 4599331..0000000 --- a/media/video/video_decode_engine.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_VIDEO_VIDEO_DECODE_ENGINE_H_ -#define MEDIA_VIDEO_VIDEO_DECODE_ENGINE_H_ - -#include "base/memory/ref_counted.h" -#include "media/base/media_export.h" - -namespace media { - -class Buffer; -class VideoDecoderConfig; -class VideoFrame; - -class MEDIA_EXPORT VideoDecodeEngine { - public: - virtual ~VideoDecodeEngine() {} - - // Initialize the engine with specified configuration, returning true if - // successful. - virtual bool Initialize(const VideoDecoderConfig& config) = 0; - - // Uninitialize the engine, freeing all resources. Calls to Flush() or - // Decode() will have no effect afterwards. - virtual void Uninitialize() = 0; - - // Decode the encoded video data and store the result (if any) into - // |video_frame|. Note that a frame may not always be produced if the - // decode engine has insufficient encoded data. In such circumstances, - // additional calls to Decode() may be required. - // - // Returns true if decoding was successful (includes zero length input and end - // of stream), false if a decoding error occurred. - virtual bool Decode(const scoped_refptr<Buffer>& buffer, - scoped_refptr<VideoFrame>* video_frame) = 0; - - // Discard all pending data that has yet to be returned via Decode(). - virtual void Flush() = 0; -}; - -} // namespace media - -#endif // MEDIA_VIDEO_VIDEO_DECODE_ENGINE_H_ |