summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-11 22:31:24 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-11 22:31:24 +0000
commit0b5f7e52bab18455a11ea763ae424f30755dc20f (patch)
treeddcfd55906e694285269a2bf683175d2320cab95 /media
parent33cdc9b854044864f7494c23a21f78733a961236 (diff)
downloadchromium_src-0b5f7e52bab18455a11ea763ae424f30755dc20f.zip
chromium_src-0b5f7e52bab18455a11ea763ae424f30755dc20f.tar.gz
chromium_src-0b5f7e52bab18455a11ea763ae424f30755dc20f.tar.bz2
Remove FFmpegVideoDecodeEngine's dependency on AVStream (again).
First step of many towards removing DemuxerStream::QueryInterface, AVStreamProvider, and MediaFormat. This time without memory leaks! BUG=28206 TEST=media_unittests git-svn-id: svn://svn.chromium.org/chrome/trunk/src@77875 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/base/mock_ffmpeg.cc4
-rw-r--r--media/base/mock_ffmpeg.h1
-rw-r--r--media/ffmpeg/ffmpeg_common.cc42
-rw-r--r--media/ffmpeg/ffmpeg_common.h4
-rw-r--r--media/filters/ffmpeg_video_decoder.cc30
-rw-r--r--media/filters/omx_video_decoder.cc28
-rw-r--r--media/tools/omx_test/omx_test.cc31
-rw-r--r--media/video/ffmpeg_video_decode_engine.cc62
-rw-r--r--media/video/ffmpeg_video_decode_engine.h13
-rw-r--r--media/video/ffmpeg_video_decode_engine_unittest.cc90
-rw-r--r--media/video/mft_h264_decode_engine.cc8
-rw-r--r--media/video/mft_h264_decode_engine.h6
-rw-r--r--media/video/omx_video_decode_engine.cc10
-rw-r--r--media/video/omx_video_decode_engine.h6
-rw-r--r--media/video/video_decode_engine.cc59
-rw-r--r--media/video/video_decode_engine.h48
16 files changed, 271 insertions, 171 deletions
diff --git a/media/base/mock_ffmpeg.cc b/media/base/mock_ffmpeg.cc
index ec19b1b..f1e28f9 100644
--- a/media/base/mock_ffmpeg.cc
+++ b/media/base/mock_ffmpeg.cc
@@ -120,6 +120,10 @@ void avcodec_flush_buffers(AVCodecContext* avctx) {
return MockFFmpeg::get()->AVCodecFlushBuffers(avctx);
}
+AVCodecContext* avcodec_alloc_context() {
+ return MockFFmpeg::get()->AVCodecAllocContext();
+}
+
AVFrame* avcodec_alloc_frame() {
return MockFFmpeg::get()->AVCodecAllocFrame();
}
diff --git a/media/base/mock_ffmpeg.h b/media/base/mock_ffmpeg.h
index 89402fe..b004aa4 100644
--- a/media/base/mock_ffmpeg.h
+++ b/media/base/mock_ffmpeg.h
@@ -28,6 +28,7 @@ class MockFFmpeg {
MOCK_METHOD1(AVCodecClose, int(AVCodecContext* avctx));
MOCK_METHOD2(AVCodecThreadInit, int(AVCodecContext* avctx, int threads));
MOCK_METHOD1(AVCodecFlushBuffers, void(AVCodecContext* avctx));
+ MOCK_METHOD0(AVCodecAllocContext, AVCodecContext*());
MOCK_METHOD0(AVCodecAllocFrame, AVFrame*());
MOCK_METHOD4(AVCodecDecodeVideo2,
int(AVCodecContext* avctx, AVFrame* picture,
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc
index 244d2729..dce96a5 100644
--- a/media/ffmpeg/ffmpeg_common.cc
+++ b/media/ffmpeg/ffmpeg_common.cc
@@ -4,8 +4,50 @@
#include "media/ffmpeg/ffmpeg_common.h"
+#include "base/logging.h"
+
namespace media {
// TODO(scherkus): combine ffmpeg_common.h with ffmpeg_util.h
+VideoCodec CodecIDToVideoCodec(CodecID codec_id) {
+ switch (codec_id) {
+ case CODEC_ID_VC1:
+ return kCodecVC1;
+ case CODEC_ID_H264:
+ return kCodecH264;
+ case CODEC_ID_THEORA:
+ return kCodecTheora;
+ case CODEC_ID_MPEG2VIDEO:
+ return kCodecMPEG2;
+ case CODEC_ID_MPEG4:
+ return kCodecMPEG4;
+ case CODEC_ID_VP8:
+ return kCodecVP8;
+ default:
+ NOTREACHED();
+ }
+ return kUnknown;
+}
+
+CodecID VideoCodecToCodecID(VideoCodec video_codec) {
+ switch (video_codec) {
+ case kCodecVC1:
+ return CODEC_ID_VC1;
+ case kCodecH264:
+ return CODEC_ID_H264;
+ case kCodecTheora:
+ return CODEC_ID_THEORA;
+ case kCodecMPEG2:
+ return CODEC_ID_MPEG2VIDEO;
+ case kCodecMPEG4:
+ return CODEC_ID_MPEG4;
+ case kCodecVP8:
+ return CODEC_ID_VP8;
+ default:
+ NOTREACHED();
+ }
+ return CODEC_ID_NONE;
+}
+
} // namespace media
diff --git a/media/ffmpeg/ffmpeg_common.h b/media/ffmpeg/ffmpeg_common.h
index 714a6a1..3b0d0ee 100644
--- a/media/ffmpeg/ffmpeg_common.h
+++ b/media/ffmpeg/ffmpeg_common.h
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/singleton.h"
+#include "media/video/video_decode_engine.h"
// Include FFmpeg header files.
extern "C" {
@@ -48,6 +49,9 @@ class ScopedPtrAVFreePacket {
}
};
+VideoCodec CodecIDToVideoCodec(CodecID codec_id);
+CodecID VideoCodecToCodecID(VideoCodec video_codec);
+
} // namespace media
#endif // MEDIA_FFMPEG_FFMPEG_COMMON_H_
diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc
index 698423b..313d55c 100644
--- a/media/filters/ffmpeg_video_decoder.cc
+++ b/media/filters/ffmpeg_video_decoder.cc
@@ -67,8 +67,8 @@ void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream,
time_base_->den = av_stream->r_frame_rate.num;
time_base_->num = av_stream->r_frame_rate.den;
- int width = av_stream->codec->width;
- int height = av_stream->codec->height;
+ int width = av_stream->codec->coded_width;
+ int height = av_stream->codec->coded_height;
if (width > Limits::kMaxDimension ||
height > Limits::kMaxDimension ||
(width * height) > Limits::kMaxCanvas) {
@@ -77,26 +77,12 @@ void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream,
return;
}
- VideoCodecConfig config;
- switch (av_stream->codec->codec_id) {
- case CODEC_ID_VC1:
- config.codec = kCodecVC1; break;
- case CODEC_ID_H264:
- config.codec = kCodecH264; break;
- case CODEC_ID_THEORA:
- config.codec = kCodecTheora; break;
- case CODEC_ID_MPEG2VIDEO:
- config.codec = kCodecMPEG2; break;
- case CODEC_ID_MPEG4:
- config.codec = kCodecMPEG4; break;
- case CODEC_ID_VP8:
- config.codec = kCodecVP8; break;
- default:
- NOTREACHED();
- }
- config.opaque_context = av_stream;
- config.width = width;
- config.height = height;
+ VideoCodecConfig config(CodecIDToVideoCodec(av_stream->codec->codec_id),
+ width, height,
+ av_stream->r_frame_rate.num,
+ av_stream->r_frame_rate.den,
+ av_stream->codec->extradata,
+ av_stream->codec->extradata_size);
state_ = kInitializing;
decode_engine_->Initialize(message_loop_, this, NULL, config);
}
diff --git a/media/filters/omx_video_decoder.cc b/media/filters/omx_video_decoder.cc
index c8962a3..0dc25f9 100644
--- a/media/filters/omx_video_decoder.cc
+++ b/media/filters/omx_video_decoder.cc
@@ -62,8 +62,8 @@ void OmxVideoDecoder::Initialize(DemuxerStream* demuxer_stream,
}
AVStream* av_stream = av_stream_provider->GetAVStream();
- int width = av_stream->codec->width;
- int height = av_stream->codec->height;
+ int width = av_stream->codec->coded_width;
+ int height = av_stream->codec->coded_height;
if (width > Limits::kMaxDimension ||
height > Limits::kMaxDimension ||
(width * height) > Limits::kMaxCanvas) {
@@ -72,24 +72,12 @@ void OmxVideoDecoder::Initialize(DemuxerStream* demuxer_stream,
return;
}
- VideoCodecConfig config;
- switch (av_stream->codec->codec_id) {
- case CODEC_ID_VC1:
- config.codec = kCodecVC1; break;
- case CODEC_ID_H264:
- config.codec = kCodecH264; break;
- case CODEC_ID_THEORA:
- config.codec = kCodecTheora; break;
- case CODEC_ID_MPEG2VIDEO:
- config.codec = kCodecMPEG2; break;
- case CODEC_ID_MPEG4:
- config.codec = kCodecMPEG4; break;
- default:
- NOTREACHED();
- }
- config.opaque_context = NULL;
- config.width = width;
- config.height = height;
+ VideoCodecConfig config(CodecIDToVideoCodec(av_stream->codec->codec_id),
+ width, height,
+ av_stream->r_frame_rate.num,
+ av_stream->r_frame_rate.den,
+ av_stream->codec->extradata,
+ av_stream->codec->extradata_size);
decode_engine_->Initialize(message_loop_, this, NULL, config);
}
diff --git a/media/tools/omx_test/omx_test.cc b/media/tools/omx_test/omx_test.cc
index 24cf4cc..2821f08 100644
--- a/media/tools/omx_test/omx_test.cc
+++ b/media/tools/omx_test/omx_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -170,26 +170,15 @@ class TestApp : public base::RefCountedThreadSafe<TestApp>,
void Run() {
StartProfiler();
- // Setup the |engine_| with the message loop of the current thread. Also
- // setup codec format and callbacks.
- media::VideoCodecConfig config;
- switch (av_stream_->codec->codec_id) {
- case CODEC_ID_VC1:
- config.codec = media::kCodecVC1; break;
- case CODEC_ID_H264:
- config.codec = media::kCodecH264; break;
- case CODEC_ID_THEORA:
- config.codec = media::kCodecTheora; break;
- case CODEC_ID_MPEG2VIDEO:
- config.codec = media::kCodecMPEG2; break;
- case CODEC_ID_MPEG4:
- config.codec = media::kCodecMPEG4; break;
- default:
- NOTREACHED(); break;
- }
- config.opaque_context = NULL;
- config.width = av_stream_->codec->width;
- config.height = av_stream_->codec->height;
+ media::VideoCodecConfig config(
+ media::CodecIDToVideoCodec(av_stream_->codec->codec_id),
+ av_stream_->codec->coded_width,
+ av_stream_->codec->coded_height,
+ av_stream_->r_frame_rate.num,
+ av_stream_->r_frame_rate.den,
+ av_stream_->codec->extradata,
+ av_stream_->codec->extradata_size);
+
engine_.reset(new OmxVideoDecodeEngine());
engine_->Initialize(&message_loop_, this, NULL, config);
diff --git a/media/video/ffmpeg_video_decode_engine.cc b/media/video/ffmpeg_video_decode_engine.cc
index 786be41..20fc480 100644
--- a/media/video/ffmpeg_video_decode_engine.cc
+++ b/media/video/ffmpeg_video_decode_engine.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -21,8 +21,9 @@ namespace media {
FFmpegVideoDecodeEngine::FFmpegVideoDecodeEngine()
: codec_context_(NULL),
- av_stream_(NULL),
event_handler_(NULL),
+ frame_rate_numerator_(0),
+ frame_rate_denominator_(0),
direct_rendering_(false),
pending_input_buffers_(0),
pending_output_buffers_(0),
@@ -31,6 +32,11 @@ FFmpegVideoDecodeEngine::FFmpegVideoDecodeEngine()
}
FFmpegVideoDecodeEngine::~FFmpegVideoDecodeEngine() {
+ if (codec_context_) {
+ av_free(codec_context_->extradata);
+ avcodec_close(codec_context_);
+ av_free(codec_context_);
+ }
}
void FFmpegVideoDecodeEngine::Initialize(
@@ -52,8 +58,27 @@ void FFmpegVideoDecodeEngine::Initialize(
static const int kDecodeThreads = 2;
static const int kMaxDecodeThreads = 16;
- av_stream_ = static_cast<AVStream*>(config.opaque_context);
- codec_context_ = av_stream_->codec;
+ // Initialize AVCodecContext structure.
+ codec_context_ = avcodec_alloc_context();
+
+ // TODO(scherkus): should video format get passed in via VideoCodecConfig?
+ codec_context_->pix_fmt = PIX_FMT_YUV420P;
+ codec_context_->codec_type = AVMEDIA_TYPE_VIDEO;
+ codec_context_->codec_id = VideoCodecToCodecID(config.codec());
+ codec_context_->coded_width = config.width();
+ codec_context_->coded_height = config.height();
+
+ frame_rate_numerator_ = config.frame_rate_numerator();
+ frame_rate_denominator_ = config.frame_rate_denominator();
+
+ if (config.extra_data() != NULL) {
+ codec_context_->extradata_size = config.extra_data_size();
+ codec_context_->extradata =
+ reinterpret_cast<uint8_t*>(av_malloc(config.extra_data_size()));
+ memcpy(codec_context_->extradata, config.extra_data(),
+ config.extra_data_size());
+ }
+
// 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;
@@ -93,8 +118,8 @@ void FFmpegVideoDecodeEngine::Initialize(
info.provides_buffers = true;
info.stream_info.surface_type = VideoFrame::TYPE_SYSTEM_MEMORY;
info.stream_info.surface_format = GetSurfaceFormat();
- info.stream_info.surface_width = config.width;
- info.stream_info.surface_height = config.height;
+ info.stream_info.surface_width = config.width();
+ info.stream_info.surface_height = config.height();
// If we do not have enough buffers, we will report error too.
bool buffer_allocated = true;
@@ -104,8 +129,8 @@ void FFmpegVideoDecodeEngine::Initialize(
for (size_t i = 0; i < Limits::kMaxVideoFrames; ++i) {
scoped_refptr<VideoFrame> video_frame;
VideoFrame::CreateFrame(VideoFrame::YV12,
- config.width,
- config.height,
+ config.width(),
+ config.height(),
kNoTimestamp,
kNoTimestamp,
&video_frame);
@@ -258,18 +283,15 @@ void FFmpegVideoDecodeEngine::DecodeFrame(scoped_refptr<Buffer> buffer) {
// 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.
- // Even frame rate is fixed, for some streams and codecs, the value of
- // |codec_context_->time_base| and |av_stream_->time_base| are not the
- // inverse of the |av_stream_->r_frame_rate|. They use 1 milli-second as
- // time-base units and use increment of av_packet->pts which is not one.
- // Use the inverse of |av_stream_->r_frame_rate| instead of time_base.
AVRational doubled_time_base;
- doubled_time_base.den = av_stream_->r_frame_rate.num;
- doubled_time_base.num = av_stream_->r_frame_rate.den;
- doubled_time_base.den *= 2;
+ doubled_time_base.num = frame_rate_denominator_;
+ doubled_time_base.den = frame_rate_numerator_ * 2;
base::TimeDelta timestamp =
base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque);
@@ -341,14 +363,6 @@ void FFmpegVideoDecodeEngine::Seek() {
event_handler_->OnSeekComplete();
}
-AVCodecContext* FFmpegVideoDecodeEngine::codec_context() const {
- return codec_context_;
-}
-
-void FFmpegVideoDecodeEngine::SetCodecContextForTest(AVCodecContext* context) {
- codec_context_ = context;
-}
-
void FFmpegVideoDecodeEngine::ReadInput() {
DCHECK_EQ(output_eos_reached_, false);
pending_input_buffers_++;
diff --git a/media/video/ffmpeg_video_decode_engine.h b/media/video/ffmpeg_video_decode_engine.h
index 53baa54..b9e76b7 100644
--- a/media/video/ffmpeg_video_decode_engine.h
+++ b/media/video/ffmpeg_video_decode_engine.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -14,7 +14,6 @@
// FFmpeg types.
struct AVCodecContext;
struct AVFrame;
-struct AVStream;
namespace media {
@@ -36,21 +35,21 @@ class FFmpegVideoDecodeEngine : public VideoDecodeEngine {
virtual void Flush();
virtual void Seek();
- virtual AVCodecContext* codec_context() const;
-
- virtual void SetCodecContextForTest(AVCodecContext* context);
-
VideoFrame::Format GetSurfaceFormat() const;
+
private:
void DecodeFrame(scoped_refptr<Buffer> buffer);
void ReadInput();
void TryToFinishPendingFlush();
AVCodecContext* codec_context_;
- AVStream* av_stream_;
scoped_ptr_malloc<AVFrame, ScopedPtrAVFree> av_frame_;
VideoDecodeEngine::EventHandler* event_handler_;
+ // Frame rate of the video.
+ int frame_rate_numerator_;
+ int frame_rate_denominator_;
+
// Whether direct rendering is used.
bool direct_rendering_;
diff --git a/media/video/ffmpeg_video_decode_engine_unittest.cc b/media/video/ffmpeg_video_decode_engine_unittest.cc
index e3bea41..ca5c48a 100644
--- a/media/video/ffmpeg_video_decode_engine_unittest.cc
+++ b/media/video/ffmpeg_video_decode_engine_unittest.cc
@@ -23,7 +23,7 @@ namespace media {
static const int kWidth = 320;
static const int kHeight = 240;
-static const AVRational kTimeBase = { 1, 100 };
+static const AVRational kFrameRate = { 100, 1 };
static void InitializeFrame(uint8_t* data, int width, AVFrame* frame) {
frame->data[0] = data;
@@ -35,7 +35,7 @@ static void InitializeFrame(uint8_t* data, int width, AVFrame* frame) {
}
ACTION_P(DecodeComplete, decoder) {
- decoder->video_frame_ = arg0;
+ decoder->set_video_frame(arg0);
}
ACTION_P2(DemuxComplete, engine, buffer) {
@@ -43,33 +43,27 @@ ACTION_P2(DemuxComplete, engine, buffer) {
}
ACTION_P(SaveInitializeResult, engine) {
- engine->info_ = arg0;
+ engine->set_video_codec_info(arg0);
}
class FFmpegVideoDecodeEngineTest : public testing::Test,
public VideoDecodeEngine::EventHandler {
- protected:
- FFmpegVideoDecodeEngineTest() {
+ public:
+ FFmpegVideoDecodeEngineTest()
+ : config_(kCodecH264, kWidth, kHeight,
+ kFrameRate.num, kFrameRate.den, NULL, 0) {
+
// Setup FFmpeg structures.
frame_buffer_.reset(new uint8[kWidth * kHeight]);
memset(&yuv_frame_, 0, sizeof(yuv_frame_));
InitializeFrame(frame_buffer_.get(), kWidth, &yuv_frame_);
memset(&codec_context_, 0, sizeof(codec_context_));
- codec_context_.width = kWidth;
- codec_context_.height = kHeight;
- codec_context_.time_base = kTimeBase;
-
memset(&codec_, 0, sizeof(codec_));
- memset(&stream_, 0, sizeof(stream_));
- stream_.codec = &codec_context_;
- stream_.r_frame_rate.num = kTimeBase.den;
- stream_.r_frame_rate.den = kTimeBase.num;
buffer_ = new DataBuffer(1);
test_engine_.reset(new FFmpegVideoDecodeEngine());
- test_engine_->SetCodecContextForTest(&codec_context_);
VideoFrame::CreateFrame(VideoFrame::YV12,
kWidth,
@@ -84,7 +78,9 @@ class FFmpegVideoDecodeEngineTest : public testing::Test,
}
void Initialize() {
- EXPECT_CALL(mock_ffmpeg_, AVCodecFindDecoder(CODEC_ID_NONE))
+ EXPECT_CALL(mock_ffmpeg_, AVCodecAllocContext())
+ .WillOnce(Return(&codec_context_));
+ EXPECT_CALL(mock_ffmpeg_, AVCodecFindDecoder(CODEC_ID_H264))
.WillOnce(Return(&codec_));
EXPECT_CALL(mock_ffmpeg_, AVCodecAllocFrame())
.WillOnce(Return(&yuv_frame_));
@@ -92,13 +88,13 @@ class FFmpegVideoDecodeEngineTest : public testing::Test,
.WillOnce(Return(0));
EXPECT_CALL(mock_ffmpeg_, AVCodecOpen(&codec_context_, &codec_))
.WillOnce(Return(0));
+ EXPECT_CALL(mock_ffmpeg_, AVCodecClose(&codec_context_))
+ .WillOnce(Return(0));
EXPECT_CALL(mock_ffmpeg_, AVFree(&yuv_frame_))
.Times(1);
+ EXPECT_CALL(mock_ffmpeg_, AVFree(&codec_context_))
+ .Times(1);
- config_.codec = kCodecH264;
- config_.opaque_context = &stream_;
- config_.width = kWidth;
- config_.height = kHeight;
EXPECT_CALL(*this, OnInitializeComplete(_))
.WillOnce(SaveInitializeResult(this));
test_engine_->Initialize(MessageLoop::current(), this, NULL, config_);
@@ -126,7 +122,7 @@ class FFmpegVideoDecodeEngineTest : public testing::Test,
codec_context_.height = height;
}
- public:
+ // VideoDecodeEngine::EventHandler implementation.
MOCK_METHOD2(ConsumeVideoFrame,
void(scoped_refptr<VideoFrame> video_frame,
const PipelineStatistics& statistics));
@@ -140,20 +136,30 @@ class FFmpegVideoDecodeEngineTest : public testing::Test,
MOCK_METHOD0(OnError, void());
MOCK_METHOD1(OnFormatChange, void(VideoStreamInfo stream_info));
- scoped_refptr<VideoFrame> video_frame_;
+ // Used by gmock actions.
+ void set_video_frame(scoped_refptr<VideoFrame> video_frame) {
+ video_frame_ = video_frame;
+ }
+
+ void set_video_codec_info(const VideoCodecInfo& info) {
+ info_ = info;
+ }
+
+ protected:
VideoCodecConfig config_;
VideoCodecInfo info_;
- protected:
+ scoped_refptr<VideoFrame> video_frame_;
scoped_ptr<FFmpegVideoDecodeEngine> test_engine_;
scoped_array<uint8_t> frame_buffer_;
StrictMock<MockFFmpeg> mock_ffmpeg_;
AVFrame yuv_frame_;
AVCodecContext codec_context_;
- AVStream stream_;
AVCodec codec_;
scoped_refptr<DataBuffer> buffer_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FFmpegVideoDecodeEngineTest);
};
TEST_F(FFmpegVideoDecodeEngineTest, Initialize_Normal) {
@@ -162,17 +168,19 @@ TEST_F(FFmpegVideoDecodeEngineTest, Initialize_Normal) {
TEST_F(FFmpegVideoDecodeEngineTest, Initialize_FindDecoderFails) {
// Test avcodec_find_decoder() returning NULL.
- EXPECT_CALL(mock_ffmpeg_, AVCodecFindDecoder(CODEC_ID_NONE))
+ EXPECT_CALL(mock_ffmpeg_, AVCodecAllocContext())
+ .WillOnce(Return(&codec_context_));
+ EXPECT_CALL(mock_ffmpeg_, AVCodecFindDecoder(CODEC_ID_H264))
.WillOnce(ReturnNull());
EXPECT_CALL(mock_ffmpeg_, AVCodecAllocFrame())
.WillOnce(Return(&yuv_frame_));
+ EXPECT_CALL(mock_ffmpeg_, AVCodecClose(&codec_context_))
+ .WillOnce(Return(0));
EXPECT_CALL(mock_ffmpeg_, AVFree(&yuv_frame_))
.Times(1);
+ EXPECT_CALL(mock_ffmpeg_, AVFree(&codec_context_))
+ .Times(1);
- config_.codec = kCodecH264;
- config_.opaque_context = &stream_;
- config_.width = kWidth;
- config_.height = kHeight;
EXPECT_CALL(*this, OnInitializeComplete(_))
.WillOnce(SaveInitializeResult(this));
test_engine_->Initialize(MessageLoop::current(), this, NULL, config_);
@@ -182,19 +190,21 @@ TEST_F(FFmpegVideoDecodeEngineTest, Initialize_FindDecoderFails) {
// Note There are 2 threads for FFmpeg-mt.
TEST_F(FFmpegVideoDecodeEngineTest, Initialize_InitThreadFails) {
// Test avcodec_thread_init() failing.
- EXPECT_CALL(mock_ffmpeg_, AVCodecFindDecoder(CODEC_ID_NONE))
+ EXPECT_CALL(mock_ffmpeg_, AVCodecAllocContext())
+ .WillOnce(Return(&codec_context_));
+ EXPECT_CALL(mock_ffmpeg_, AVCodecFindDecoder(CODEC_ID_H264))
.WillOnce(Return(&codec_));
EXPECT_CALL(mock_ffmpeg_, AVCodecAllocFrame())
.WillOnce(Return(&yuv_frame_));
EXPECT_CALL(mock_ffmpeg_, AVCodecThreadInit(&codec_context_, 2))
.WillOnce(Return(-1));
+ EXPECT_CALL(mock_ffmpeg_, AVCodecClose(&codec_context_))
+ .WillOnce(Return(0));
EXPECT_CALL(mock_ffmpeg_, AVFree(&yuv_frame_))
.Times(1);
+ EXPECT_CALL(mock_ffmpeg_, AVFree(&codec_context_))
+ .Times(1);
- config_.codec = kCodecH264;
- config_.opaque_context = &stream_;
- config_.width = kWidth;
- config_.height = kHeight;
EXPECT_CALL(*this, OnInitializeComplete(_))
.WillOnce(SaveInitializeResult(this));
test_engine_->Initialize(MessageLoop::current(), this, NULL, config_);
@@ -203,7 +213,9 @@ TEST_F(FFmpegVideoDecodeEngineTest, Initialize_InitThreadFails) {
TEST_F(FFmpegVideoDecodeEngineTest, Initialize_OpenDecoderFails) {
// Test avcodec_open() failing.
- EXPECT_CALL(mock_ffmpeg_, AVCodecFindDecoder(CODEC_ID_NONE))
+ EXPECT_CALL(mock_ffmpeg_, AVCodecAllocContext())
+ .WillOnce(Return(&codec_context_));
+ EXPECT_CALL(mock_ffmpeg_, AVCodecFindDecoder(CODEC_ID_H264))
.WillOnce(Return(&codec_));
EXPECT_CALL(mock_ffmpeg_, AVCodecAllocFrame())
.WillOnce(Return(&yuv_frame_));
@@ -211,13 +223,13 @@ TEST_F(FFmpegVideoDecodeEngineTest, Initialize_OpenDecoderFails) {
.WillOnce(Return(0));
EXPECT_CALL(mock_ffmpeg_, AVCodecOpen(&codec_context_, &codec_))
.WillOnce(Return(-1));
+ EXPECT_CALL(mock_ffmpeg_, AVCodecClose(&codec_context_))
+ .WillOnce(Return(0));
EXPECT_CALL(mock_ffmpeg_, AVFree(&yuv_frame_))
.Times(1);
+ EXPECT_CALL(mock_ffmpeg_, AVFree(&codec_context_))
+ .Times(1);
- config_.codec = kCodecH264;
- config_.opaque_context = &stream_;
- config_.width = kWidth;
- config_.height = kHeight;
EXPECT_CALL(*this, OnInitializeComplete(_))
.WillOnce(SaveInitializeResult(this));
test_engine_->Initialize(MessageLoop::current(), this, NULL, config_);
@@ -310,6 +322,8 @@ TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_SmallerHeight) {
}
TEST_F(FFmpegVideoDecodeEngineTest, GetSurfaceFormat) {
+ Initialize();
+
// YV12 formats.
codec_context_.pix_fmt = PIX_FMT_YUV420P;
EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat());
diff --git a/media/video/mft_h264_decode_engine.cc b/media/video/mft_h264_decode_engine.cc
index bb3143c..4acfc7f 100644
--- a/media/video/mft_h264_decode_engine.cc
+++ b/media/video/mft_h264_decode_engine.cc
@@ -151,11 +151,12 @@ const GUID ConvertVideoFrameFormatToGuid(VideoFrame::Format format) {
MftH264DecodeEngine::MftH264DecodeEngine(bool use_dxva)
: use_dxva_(use_dxva),
state_(kUninitialized),
+ width_(0),
+ height_(0),
event_handler_(NULL),
context_(NULL) {
memset(&input_stream_info_, 0, sizeof(input_stream_info_));
memset(&output_stream_info_, 0, sizeof(output_stream_info_));
- memset(&config_, 0, sizeof(config_));
memset(&info_, 0, sizeof(info_));
}
@@ -177,7 +178,6 @@ void MftH264DecodeEngine::Initialize(
return;
}
context_ = context;
- config_ = config;
event_handler_ = event_handler;
info_.provides_buffers = true;
@@ -473,8 +473,8 @@ bool MftH264DecodeEngine::SetDecodeEngineOutputMediaType(const GUID subtype) {
hr = MFGetAttributeSize(out_media_type, MF_MT_FRAME_SIZE,
reinterpret_cast<UINT32*>(&info_.stream_info.surface_width),
reinterpret_cast<UINT32*>(&info_.stream_info.surface_height));
- config_.width = info_.stream_info.surface_width;
- config_.height = info_.stream_info.surface_height;
+ width_ = info_.stream_info.surface_width;
+ height_ = info_.stream_info.surface_height;
if (FAILED(hr)) {
LOG(ERROR) << "Failed to SetOutputType to |subtype| or obtain "
<< "width/height " << std::hex << hr;
diff --git a/media/video/mft_h264_decode_engine.h b/media/video/mft_h264_decode_engine.h
index d543631..9ce7935 100644
--- a/media/video/mft_h264_decode_engine.h
+++ b/media/video/mft_h264_decode_engine.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
//
@@ -88,8 +88,10 @@ class MftH264DecodeEngine : public media::VideoDecodeEngine {
State state_;
+ int width_;
+ int height_;
+
VideoDecodeEngine::EventHandler* event_handler_;
- VideoCodecConfig config_;
VideoCodecInfo info_;
VideoDecodeContext* context_;
diff --git a/media/video/omx_video_decode_engine.cc b/media/video/omx_video_decode_engine.cc
index df3f9cf..a6996d3 100644
--- a/media/video/omx_video_decode_engine.cc
+++ b/media/video/omx_video_decode_engine.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -90,8 +90,8 @@ void OmxVideoDecodeEngine::Initialize(
message_loop_ = message_loop;
event_handler_ = event_handler;
- width_ = config.width;
- height_ = config.height;
+ width_ = config.width();
+ height_ = config.height();
// TODO(wjia): Find the right way to determine the codec type.
OmxConfigurator::MediaFormat input_format, output_format;
@@ -115,8 +115,8 @@ void OmxVideoDecodeEngine::Initialize(
uses_egl_image_ ? VideoFrame::TYPE_GL_TEXTURE
: VideoFrame::TYPE_SYSTEM_MEMORY;
info.stream_info.surface_format = GetSurfaceFormat();
- info.stream_info.surface_width = config.width;
- info.stream_info.surface_height = config.height;
+ info.stream_info.surface_width = config.width();
+ info.stream_info.surface_height = config.height();
event_handler_->OnInitializeComplete(info);
}
diff --git a/media/video/omx_video_decode_engine.h b/media/video/omx_video_decode_engine.h
index 9a6c0a7..1609548 100644
--- a/media/video/omx_video_decode_engine.h
+++ b/media/video/omx_video_decode_engine.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -175,8 +175,8 @@ class OmxVideoDecodeEngine : public VideoDecodeEngine {
scoped_refptr<VideoFrame> CreateOmxBufferVideoFrame(
OMX_BUFFERHEADERTYPE* omx_buffer);
- size_t width_;
- size_t height_;
+ int width_;
+ int height_;
MessageLoop* message_loop_;
diff --git a/media/video/video_decode_engine.cc b/media/video/video_decode_engine.cc
index 04f3bea..ca0093f 100644
--- a/media/video/video_decode_engine.cc
+++ b/media/video/video_decode_engine.cc
@@ -1,18 +1,61 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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/video_decode_engine.h"
+#include "base/logging.h"
+
namespace media {
-VideoCodecConfig::VideoCodecConfig()
- : codec(kCodecH264),
- profile(kProfileDoNotCare),
- level(kLevelDoNotCare),
- width(0),
- height(0),
- opaque_context(NULL) {
+VideoCodecConfig::VideoCodecConfig(VideoCodec codec,
+ int width,
+ int height,
+ int frame_rate_numerator,
+ int frame_rate_denominator,
+ uint8* extra_data,
+ size_t extra_data_size)
+ : codec_(codec),
+ width_(width),
+ height_(height),
+ frame_rate_numerator_(frame_rate_numerator),
+ frame_rate_denominator_(frame_rate_denominator),
+ extra_data_size_(extra_data_size) {
+ CHECK(extra_data_size_ == 0 || extra_data);
+ if (extra_data_size_ > 0) {
+ extra_data_.reset(new uint8[extra_data_size_]);
+ memcpy(extra_data_.get(), extra_data, extra_data_size_);
+ }
+}
+
+VideoCodecConfig::~VideoCodecConfig() {}
+
+VideoCodec VideoCodecConfig::codec() const {
+ return codec_;
+}
+
+int VideoCodecConfig::width() const {
+ return width_;
+}
+
+int VideoCodecConfig::height() const {
+ return height_;
+}
+
+int VideoCodecConfig::frame_rate_numerator() const {
+ return frame_rate_numerator_;
+}
+
+int VideoCodecConfig::frame_rate_denominator() const {
+ return frame_rate_denominator_;
+}
+
+uint8* VideoCodecConfig::extra_data() const {
+ return extra_data_.get();
+}
+
+size_t VideoCodecConfig::extra_data_size() const {
+ return extra_data_size_;
}
} // namespace media
diff --git a/media/video/video_decode_engine.h b/media/video/video_decode_engine.h
index 57b76a2..5893b3a 100644
--- a/media/video/video_decode_engine.h
+++ b/media/video/video_decode_engine.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -6,6 +6,7 @@
#define MEDIA_VIDEO_VIDEO_DECODE_ENGINE_H_
#include "base/callback.h"
+#include "base/scoped_ptr.h"
#include "media/base/video_frame.h"
class MessageLoop;
@@ -18,6 +19,7 @@ class VideoDecodeContext;
struct PipelineStatistics;
enum VideoCodec {
+ kUnknown,
kCodecH264,
kCodecVC1,
kCodecMPEG2,
@@ -26,26 +28,38 @@ enum VideoCodec {
kCodecVP8,
};
-static const uint32 kProfileDoNotCare = static_cast<uint32>(-1);
-static const uint32 kLevelDoNotCare = static_cast<uint32>(-1);
-
-struct VideoCodecConfig {
- VideoCodecConfig();
+class VideoCodecConfig {
+ public:
+ VideoCodecConfig(VideoCodec codec, int width, int height,
+ int frame_rate_numerator, int frame_rate_denominator,
+ uint8* extra_data, size_t extra_data_size);
+ ~VideoCodecConfig();
+
+ VideoCodec codec() const;
+ int width() const;
+ int height() const;
+ int frame_rate_numerator() const;
+ int frame_rate_denominator() const;
+ uint8* extra_data() const;
+ size_t extra_data_size() const;
+
+ private:
+ VideoCodec codec_;
- VideoCodec codec;
+ // Container's concept of width and height of this video.
+ int width_;
+ int height_;
- // TODO(jiesun): video profile and level are specific to individual codec.
- // Define enum to.
- uint32 profile;
- uint32 level;
+ // Frame rate in seconds expressed as a fraction.
+ // TODO(scherkus): fairly certain decoders don't require frame rates.
+ int frame_rate_numerator_;
+ int frame_rate_denominator_;
- // Container's concept of width and height of this video.
- int32 width;
- int32 height; // TODO(jiesun): Do we allow height to be negative to
- // indicate output is upside-down?
+ // Optional byte data requied to initialize video decoders.
+ scoped_array<uint8> extra_data_;
+ size_t extra_data_size_;
- // FFMPEG's will use this to pass AVStream. Otherwise, we should remove this.
- void* opaque_context;
+ DISALLOW_COPY_AND_ASSIGN(VideoCodecConfig);
};
struct VideoStreamInfo {