summaryrefslogtreecommitdiffstats
path: root/media/video
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-16 18:10:42 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-16 18:10:42 +0000
commit92e4afc1fbcb3850b505e5caceabbbcca491974a (patch)
tree8068f2be68df618aade295db81e5be32aeb1b13f /media/video
parent3d143e9b4beec02c615bd47a6a267a0ba24992cd (diff)
downloadchromium_src-92e4afc1fbcb3850b505e5caceabbbcca491974a.zip
chromium_src-92e4afc1fbcb3850b505e5caceabbbcca491974a.tar.gz
chromium_src-92e4afc1fbcb3850b505e5caceabbbcca491974a.tar.bz2
Revert 96974 - Remove mock_ffmpeg and update media unittests.
BUG=92429 TEST=BitstreamConverterTest.*, ChunkDemuxerTest.*, FFmpegDemuxerTest.*, FFmpegGlueTest.*, FFmpegVideoDecoderTest.*, FFmpegH264BitstreamConverterTest.*, FFmpegVideoDecodeEngineTest.* Review URL: http://codereview.chromium.org/7587012 TBR=acolwell@chromium.org Review URL: http://codereview.chromium.org/7658017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96977 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/video')
-rw-r--r--media/video/ffmpeg_video_decode_engine.cc20
-rw-r--r--media/video/ffmpeg_video_decode_engine.h2
-rw-r--r--media/video/ffmpeg_video_decode_engine_unittest.cc228
3 files changed, 159 insertions, 91 deletions
diff --git a/media/video/ffmpeg_video_decode_engine.cc b/media/video/ffmpeg_video_decode_engine.cc
index 0958516..4af73a1 100644
--- a/media/video/ffmpeg_video_decode_engine.cc
+++ b/media/video/ffmpeg_video_decode_engine.cc
@@ -120,7 +120,6 @@ void FFmpegVideoDecodeEngine::Initialize(
kNoTimestamp);
frame_queue_available_.push_back(video_frame);
}
-
codec_context_->thread_count = decode_threads;
if (codec &&
avcodec_open(codec_context_, codec) >= 0 &&
@@ -187,6 +186,7 @@ void FFmpegVideoDecodeEngine::DecodeFrame(scoped_refptr<Buffer> buffer) {
av_frame_.get(),
&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: "
@@ -303,6 +303,24 @@ void FFmpegVideoDecodeEngine::ReadInput() {
event_handler_->ProduceVideoSample(NULL);
}
+VideoFrame::Format FFmpegVideoDecodeEngine::GetSurfaceFormat() const {
+ // J (Motion JPEG) versions of YUV are full range 0..255.
+ // Regular (MPEG) YUV is 16..240.
+ // For now we will ignore the distinction and treat them the same.
+ switch (codec_context_->pix_fmt) {
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_YUVJ420P:
+ return VideoFrame::YV12;
+ case PIX_FMT_YUV422P:
+ case PIX_FMT_YUVJ422P:
+ return VideoFrame::YV16;
+ default:
+ // TODO(scherkus): More formats here?
+ break;
+ }
+ return VideoFrame::INVALID;
+}
+
} // namespace media
// Disable refcounting for this object because this object only lives
diff --git a/media/video/ffmpeg_video_decode_engine.h b/media/video/ffmpeg_video_decode_engine.h
index b7d7661..32eac45 100644
--- a/media/video/ffmpeg_video_decode_engine.h
+++ b/media/video/ffmpeg_video_decode_engine.h
@@ -33,6 +33,8 @@ class FFmpegVideoDecodeEngine : public VideoDecodeEngine {
virtual void Flush();
virtual void Seek();
+ VideoFrame::Format GetSurfaceFormat() const;
+
private:
void DecodeFrame(scoped_refptr<Buffer> buffer);
void ReadInput();
diff --git a/media/video/ffmpeg_video_decode_engine_unittest.cc b/media/video/ffmpeg_video_decode_engine_unittest.cc
index 665fb86..261ca45 100644
--- a/media/video/ffmpeg_video_decode_engine_unittest.cc
+++ b/media/video/ffmpeg_video_decode_engine_unittest.cc
@@ -5,10 +5,9 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "media/base/data_buffer.h"
+#include "media/base/mock_ffmpeg.h"
#include "media/base/mock_task.h"
#include "media/base/pipeline.h"
-#include "media/base/test_data_util.h"
-#include "media/filters/ffmpeg_glue.h"
#include "media/video/ffmpeg_video_decode_engine.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -22,12 +21,21 @@ using ::testing::StrictMock;
namespace media {
-static const size_t kWidth = 320;
-static const size_t kHeight = 240;
+static const int kWidth = 320;
+static const int kHeight = 240;
static const int kSurfaceWidth = 522;
static const int kSurfaceHeight = 288;
static const AVRational kFrameRate = { 100, 1 };
+static void InitializeFrame(uint8_t* data, int width, AVFrame* frame) {
+ frame->data[0] = data;
+ frame->data[1] = data;
+ frame->data[2] = data;
+ frame->linesize[0] = width;
+ frame->linesize[1] = width / 2;
+ frame->linesize[2] = width / 2;
+}
+
ACTION_P(DecodeComplete, decoder) {
decoder->set_video_frame(arg0);
}
@@ -45,12 +53,18 @@ class FFmpegVideoDecodeEngineTest
public VideoDecodeEngine::EventHandler {
public:
FFmpegVideoDecodeEngineTest()
- : config_(kCodecVP8, kWidth, kHeight, kSurfaceWidth, kSurfaceHeight,
+ : config_(kCodecH264, kWidth, kHeight, kSurfaceWidth, kSurfaceHeight,
kFrameRate.num, kFrameRate.den, NULL, 0) {
- CHECK(FFmpegGlue::GetInstance());
// 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_));
+ memset(&codec_, 0, sizeof(codec_));
+
+ buffer_ = new DataBuffer(1);
test_engine_.reset(new FFmpegVideoDecodeEngine());
@@ -59,8 +73,6 @@ class FFmpegVideoDecodeEngineTest
kHeight,
kNoTimestamp,
kNoTimestamp);
-
- ReadTestDataFile("vp8-I-frame-320x240", &i_frame_buffer_);
}
~FFmpegVideoDecodeEngineTest() {
@@ -68,20 +80,48 @@ class FFmpegVideoDecodeEngineTest
}
void Initialize() {
+ 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_, 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);
+
EXPECT_CALL(*this, OnInitializeComplete(_))
.WillOnce(SaveInitializeResult(this));
test_engine_->Initialize(MessageLoop::current(), this, NULL, config_);
EXPECT_TRUE(info_.success);
}
- void Decode(const scoped_refptr<Buffer>& buffer) {
+ void Decode() {
+ EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_));
+ EXPECT_CALL(mock_ffmpeg_,
+ AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(1), // Simulate 1 byte frame.
+ Return(0)));
+
EXPECT_CALL(*this, ProduceVideoSample(_))
- .WillOnce(DemuxComplete(test_engine_.get(), buffer));
+ .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
EXPECT_CALL(*this, ConsumeVideoFrame(_, _))
.WillOnce(DecodeComplete(this));
test_engine_->ProduceVideoFrame(video_frame_);
}
+ void ChangeDimensions(int width, int height) {
+ frame_buffer_.reset(new uint8[width * height]);
+ InitializeFrame(frame_buffer_.get(), width, &yuv_frame_);
+ codec_context_.width = width;
+ codec_context_.height = height;
+ }
+
// VideoDecodeEngine::EventHandler implementation.
MOCK_METHOD2(ConsumeVideoFrame,
void(scoped_refptr<VideoFrame> video_frame,
@@ -110,7 +150,12 @@ class FFmpegVideoDecodeEngineTest
scoped_refptr<VideoFrame> video_frame_;
scoped_ptr<FFmpegVideoDecodeEngine> test_engine_;
scoped_array<uint8_t> frame_buffer_;
- scoped_refptr<Buffer> i_frame_buffer_;
+ StrictMock<MockFFmpeg> mock_ffmpeg_;
+
+ AVFrame yuv_frame_;
+ AVCodecContext codec_context_;
+ AVCodec codec_;
+ scoped_refptr<DataBuffer> buffer_;
private:
DISALLOW_COPY_AND_ASSIGN(FFmpegVideoDecodeEngineTest);
@@ -121,36 +166,61 @@ TEST_F(FFmpegVideoDecodeEngineTest, Initialize_Normal) {
}
TEST_F(FFmpegVideoDecodeEngineTest, Initialize_FindDecoderFails) {
- VideoDecoderConfig config(kUnknown, kWidth, kHeight, kSurfaceWidth,
- kSurfaceHeight, kFrameRate.num, kFrameRate.den,
- NULL, 0);
// Test avcodec_find_decoder() returning NULL.
+ 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);
+
EXPECT_CALL(*this, OnInitializeComplete(_))
.WillOnce(SaveInitializeResult(this));
- test_engine_->Initialize(MessageLoop::current(), this, NULL, config);
+ test_engine_->Initialize(MessageLoop::current(), this, NULL, config_);
EXPECT_FALSE(info_.success);
}
TEST_F(FFmpegVideoDecodeEngineTest, Initialize_OpenDecoderFails) {
- // Specify Theora w/o extra data so that avcodec_open() fails.
- VideoDecoderConfig config(kCodecTheora, kWidth, kHeight, kSurfaceWidth,
- kSurfaceHeight, kFrameRate.num, kFrameRate.den,
- NULL, 0);
+ // Test avcodec_open() failing.
+ 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_, 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);
+
EXPECT_CALL(*this, OnInitializeComplete(_))
.WillOnce(SaveInitializeResult(this));
- test_engine_->Initialize(MessageLoop::current(), this, NULL, config);
+ test_engine_->Initialize(MessageLoop::current(), this, NULL, config_);
EXPECT_FALSE(info_.success);
}
TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_Normal) {
Initialize();
- // We rely on FFmpeg for timestamp and duration reporting.
- const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(0);
- const base::TimeDelta kDuration = base::TimeDelta::FromMicroseconds(10000);
+ // We rely on FFmpeg for timestamp and duration reporting. The one tricky
+ // bit is calculating the duration when |repeat_pict| > 0.
+ const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(123);
+ const base::TimeDelta kDuration = base::TimeDelta::FromMicroseconds(15000);
+ yuv_frame_.repeat_pict = 1;
+ yuv_frame_.reordered_opaque = kTimestamp.InMicroseconds();
// Simulate decoding a single frame.
- Decode(i_frame_buffer_);
+ Decode();
// |video_frame_| timestamp is 0 because we set the timestamp based off
// the buffer timestamp.
@@ -162,11 +232,19 @@ TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_Normal) {
TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_0ByteFrame) {
Initialize();
- scoped_refptr<Buffer> buffer_a = new DataBuffer(1);
+ // Expect a bunch of avcodec calls.
+ EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_))
+ .Times(2);
+ EXPECT_CALL(mock_ffmpeg_,
+ AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(0), // Simulate 0 byte frame.
+ Return(0)))
+ .WillOnce(DoAll(SetArgumentPointee<2>(1), // Simulate 1 byte frame.
+ Return(0)));
EXPECT_CALL(*this, ProduceVideoSample(_))
- .WillOnce(DemuxComplete(test_engine_.get(), buffer_a))
- .WillOnce(DemuxComplete(test_engine_.get(), i_frame_buffer_));
+ .WillOnce(DemuxComplete(test_engine_.get(), buffer_))
+ .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
EXPECT_CALL(*this, ConsumeVideoFrame(_, _))
.WillOnce(DecodeComplete(this));
test_engine_->ProduceVideoFrame(video_frame_);
@@ -177,19 +255,14 @@ TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_0ByteFrame) {
TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_DecodeError) {
Initialize();
- scoped_refptr<DataBuffer> buffer =
- new DataBuffer(i_frame_buffer_->GetDataSize());
- buffer->SetDataSize(i_frame_buffer_->GetDataSize());
-
- uint8* buf = buffer->GetWritableData();
- memcpy(buf, i_frame_buffer_->GetData(), buffer->GetDataSize());
-
- // Corrupt bytes by flipping bits w/ xor.
- for (size_t i = 0; i < buffer->GetDataSize(); i++)
- buf[i] ^= 0xA5;
+ // Expect a bunch of avcodec calls.
+ EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_));
+ EXPECT_CALL(mock_ffmpeg_,
+ AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
+ .WillOnce(Return(-1));
EXPECT_CALL(*this, ProduceVideoSample(_))
- .WillOnce(DemuxComplete(test_engine_.get(), buffer));
+ .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
EXPECT_CALL(*this, OnError());
test_engine_->ProduceVideoFrame(video_frame_);
@@ -197,71 +270,46 @@ TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_DecodeError) {
TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_LargerWidth) {
Initialize();
-
- // Decode a frame and verify the width.
- Decode(i_frame_buffer_);
- EXPECT_EQ(video_frame_->width(), kWidth);
- EXPECT_EQ(video_frame_->height(), kHeight);
-
- // Now decode a frame with a larger width and verify the output size didn't
- // change.
- scoped_refptr<Buffer> buffer;
- ReadTestDataFile("vp8-I-frame-640x240", &buffer);
- Decode(buffer);
-
- EXPECT_EQ(kWidth, video_frame_->width());
- EXPECT_EQ(kHeight, video_frame_->height());
+ ChangeDimensions(kWidth * 2, kHeight);
+ Decode();
}
TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_SmallerWidth) {
Initialize();
-
- // Decode a frame and verify the width.
- Decode(i_frame_buffer_);
- EXPECT_EQ(video_frame_->width(), kWidth);
- EXPECT_EQ(video_frame_->height(), kHeight);
-
- // Now decode a frame with a smaller width and verify the output size didn't
- // change.
- scoped_refptr<Buffer> buffer;
- ReadTestDataFile("vp8-I-frame-160x240", &buffer);
- Decode(buffer);
- EXPECT_EQ(video_frame_->width(), kWidth);
- EXPECT_EQ(video_frame_->height(), kHeight);
+ ChangeDimensions(kWidth / 2, kHeight);
+ Decode();
}
TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_LargerHeight) {
Initialize();
-
- // Decode a frame and verify the width.
- Decode(i_frame_buffer_);
- EXPECT_EQ(video_frame_->width(), kWidth);
- EXPECT_EQ(video_frame_->height(), kHeight);
-
- // Now decode a frame with a larger height and verify the output
- // size didn't change.
- scoped_refptr<Buffer> buffer;
- ReadTestDataFile("vp8-I-frame-320x480", &buffer);
- Decode(buffer);
- EXPECT_EQ(kWidth, video_frame_->width());
- EXPECT_EQ(kHeight, video_frame_->height());
+ ChangeDimensions(kWidth, kHeight * 2);
+ Decode();
}
TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_SmallerHeight) {
Initialize();
+ ChangeDimensions(kWidth, kHeight / 2);
+ Decode();
+}
+
+TEST_F(FFmpegVideoDecodeEngineTest, GetSurfaceFormat) {
+ Initialize();
- // Decode a frame and verify the width.
- Decode(i_frame_buffer_);
- EXPECT_EQ(video_frame_->width(), kWidth);
- EXPECT_EQ(video_frame_->height(), kHeight);
-
- // Now decode a frame with a smaller height and verify the output size
- // didn't change.
- scoped_refptr<Buffer> buffer;
- ReadTestDataFile("vp8-I-frame-320x120", &buffer);
- Decode(buffer);
- EXPECT_EQ(kWidth, video_frame_->width());
- EXPECT_EQ(kHeight, video_frame_->height());
+ // YV12 formats.
+ codec_context_.pix_fmt = PIX_FMT_YUV420P;
+ EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat());
+ codec_context_.pix_fmt = PIX_FMT_YUVJ420P;
+ EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat());
+
+ // YV16 formats.
+ codec_context_.pix_fmt = PIX_FMT_YUV422P;
+ EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat());
+ codec_context_.pix_fmt = PIX_FMT_YUVJ422P;
+ EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat());
+
+ // Invalid value.
+ codec_context_.pix_fmt = PIX_FMT_NONE;
+ EXPECT_EQ(VideoFrame::INVALID, test_engine_->GetSurfaceFormat());
}
} // namespace media