diff options
Diffstat (limited to 'media/video/ffmpeg_video_decode_engine_unittest.cc')
-rw-r--r-- | media/video/ffmpeg_video_decode_engine_unittest.cc | 228 |
1 files changed, 90 insertions, 138 deletions
diff --git a/media/video/ffmpeg_video_decode_engine_unittest.cc b/media/video/ffmpeg_video_decode_engine_unittest.cc index 261ca45..665fb86 100644 --- a/media/video/ffmpeg_video_decode_engine_unittest.cc +++ b/media/video/ffmpeg_video_decode_engine_unittest.cc @@ -5,9 +5,10 @@ #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" @@ -21,21 +22,12 @@ using ::testing::StrictMock; namespace media { -static const int kWidth = 320; -static const int kHeight = 240; +static const size_t kWidth = 320; +static const size_t 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); } @@ -53,18 +45,12 @@ class FFmpegVideoDecodeEngineTest public VideoDecodeEngine::EventHandler { public: FFmpegVideoDecodeEngineTest() - : config_(kCodecH264, kWidth, kHeight, kSurfaceWidth, kSurfaceHeight, + : config_(kCodecVP8, 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()); @@ -73,6 +59,8 @@ class FFmpegVideoDecodeEngineTest kHeight, kNoTimestamp, kNoTimestamp); + + ReadTestDataFile("vp8-I-frame-320x240", &i_frame_buffer_); } ~FFmpegVideoDecodeEngineTest() { @@ -80,48 +68,20 @@ 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() { - 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))); - + void Decode(const scoped_refptr<Buffer>& buffer) { 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, @@ -150,12 +110,7 @@ class FFmpegVideoDecodeEngineTest 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_; - AVCodec codec_; - scoped_refptr<DataBuffer> buffer_; + scoped_refptr<Buffer> i_frame_buffer_; private: DISALLOW_COPY_AND_ASSIGN(FFmpegVideoDecodeEngineTest); @@ -166,61 +121,36 @@ 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) { - // 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); - + // Specify Theora w/o extra data so that avcodec_open() fails. + VideoDecoderConfig config(kCodecTheora, kWidth, kHeight, kSurfaceWidth, + kSurfaceHeight, kFrameRate.num, kFrameRate.den, + NULL, 0); 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. 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(); + // 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); // Simulate decoding a single frame. - Decode(); + Decode(i_frame_buffer_); // |video_frame_| timestamp is 0 because we set the timestamp based off // the buffer timestamp. @@ -232,19 +162,11 @@ TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_Normal) { TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_0ByteFrame) { Initialize(); - // 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))); + scoped_refptr<Buffer> buffer_a = new DataBuffer(1); EXPECT_CALL(*this, ProduceVideoSample(_)) - .WillOnce(DemuxComplete(test_engine_.get(), buffer_)) - .WillOnce(DemuxComplete(test_engine_.get(), buffer_)); + .WillOnce(DemuxComplete(test_engine_.get(), buffer_a)) + .WillOnce(DemuxComplete(test_engine_.get(), i_frame_buffer_)); EXPECT_CALL(*this, ConsumeVideoFrame(_, _)) .WillOnce(DecodeComplete(this)); test_engine_->ProduceVideoFrame(video_frame_); @@ -255,14 +177,19 @@ TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_0ByteFrame) { TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_DecodeError) { Initialize(); - // Expect a bunch of avcodec calls. - EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_)); - EXPECT_CALL(mock_ffmpeg_, - AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _)) - .WillOnce(Return(-1)); + 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_CALL(*this, ProduceVideoSample(_)) - .WillOnce(DemuxComplete(test_engine_.get(), buffer_)); + .WillOnce(DemuxComplete(test_engine_.get(), buffer)); EXPECT_CALL(*this, OnError()); test_engine_->ProduceVideoFrame(video_frame_); @@ -270,46 +197,71 @@ TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_DecodeError) { TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_LargerWidth) { Initialize(); - ChangeDimensions(kWidth * 2, kHeight); - Decode(); + + // 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()); } TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_SmallerWidth) { Initialize(); - ChangeDimensions(kWidth / 2, kHeight); - Decode(); + + // 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); } TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_LargerHeight) { Initialize(); - ChangeDimensions(kWidth, kHeight * 2); - Decode(); -} -TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_SmallerHeight) { - Initialize(); - ChangeDimensions(kWidth, kHeight / 2); - Decode(); + // 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()); } -TEST_F(FFmpegVideoDecodeEngineTest, GetSurfaceFormat) { +TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_SmallerHeight) { Initialize(); - // 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()); + // 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()); } } // namespace media |