| Index: media/filters/ffmpeg_video_decoder_unittest.cc
|
| diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc
|
| index e0d2ca2bc87b3505ef6466c8468b2c0e90ec33b2..ed36a47b0b954990c57ac1bea4d84043dc394f83 100644
|
| --- a/media/filters/ffmpeg_video_decoder_unittest.cc
|
| +++ b/media/filters/ffmpeg_video_decoder_unittest.cc
|
| @@ -46,12 +46,12 @@ class FFmpegVideoDecoderTest : public testing::Test {
|
| public:
|
| FFmpegVideoDecoderTest()
|
| : decoder_(new FFmpegVideoDecoder(&message_loop_)),
|
| - demuxer_(new StrictMock<MockDemuxerStream>()) {
|
| + demuxer_(new StrictMock<MockDemuxerStream>()),
|
| + read_cb_(base::Bind(&FFmpegVideoDecoderTest::FrameReady,
|
| + base::Unretained(this))) {
|
| CHECK(FFmpegGlue::GetInstance());
|
|
|
| decoder_->set_host(&host_);
|
| - decoder_->set_consume_video_frame_callback(base::Bind(
|
| - &FFmpegVideoDecoderTest::ConsumeVideoFrame, base::Unretained(this)));
|
|
|
| // Initialize various test buffers.
|
| frame_buffer_.reset(new uint8[kCodedSize.GetArea()]);
|
| @@ -103,35 +103,6 @@ class FFmpegVideoDecoderTest : public testing::Test {
|
| message_loop_.RunAllPending();
|
| }
|
|
|
| - // Sets up expectations for FFmpegVideoDecodeEngine to preroll after
|
| - // receiving a Seek(). The adjustment on Read() is due to the decoder
|
| - // delaying frame output.
|
| - //
|
| - // TODO(scherkus): this is madness -- there's no reason for a decoder to
|
| - // assume it should preroll anything.
|
| - void ExpectSeekPreroll() {
|
| - EXPECT_CALL(*demuxer_, Read(_))
|
| - .Times(Limits::kMaxVideoFrames + 1)
|
| - .WillRepeatedly(ReturnBuffer(i_frame_buffer_));
|
| - EXPECT_CALL(statistics_callback_, OnStatistics(_))
|
| - .Times(Limits::kMaxVideoFrames);
|
| - EXPECT_CALL(*this, ConsumeVideoFrame(_))
|
| - .Times(Limits::kMaxVideoFrames);
|
| - }
|
| -
|
| - // Sets up expectations for FFmpegVideoDecodeEngine to preroll after
|
| - // receiving a Seek() but for the end of stream case.
|
| - //
|
| - // TODO(scherkus): this is madness -- there's no reason for a decoder to
|
| - // assume it should preroll anything.
|
| - void ExpectSeekPrerollEndOfStream() {
|
| - EXPECT_CALL(*demuxer_, Read(_))
|
| - .Times(Limits::kMaxVideoFrames)
|
| - .WillRepeatedly(ReturnBuffer(end_of_stream_buffer_));
|
| - EXPECT_CALL(statistics_callback_, OnStatistics(_))
|
| - .Times(Limits::kMaxVideoFrames);
|
| - }
|
| -
|
| // Sets up expectations and actions to put FFmpegVideoDecoder in an active
|
| // decoding state.
|
| void EnterDecodingState() {
|
| @@ -145,10 +116,8 @@ class FFmpegVideoDecoderTest : public testing::Test {
|
| // Sets up expectations and actions to put FFmpegVideoDecoder in an end
|
| // of stream state.
|
| void EnterEndOfStreamState() {
|
| - EXPECT_CALL(statistics_callback_, OnStatistics(_));
|
| -
|
| scoped_refptr<VideoFrame> video_frame;
|
| - CallProduceVideoFrame(&video_frame);
|
| + Read(&video_frame);
|
| ASSERT_TRUE(video_frame);
|
| EXPECT_TRUE(video_frame->IsEndOfStream());
|
| }
|
| @@ -165,13 +134,15 @@ class FFmpegVideoDecoderTest : public testing::Test {
|
|
|
| EXPECT_CALL(statistics_callback_, OnStatistics(_));
|
|
|
| - CallProduceVideoFrame(video_frame);
|
| + Read(video_frame);
|
| }
|
|
|
| // Decodes |i_frame_buffer_| and then decodes the data contained in
|
| // the file named |test_file_name|. This function expects both buffers
|
| // to decode to frames that are the same size.
|
| - void DecodeIFrameThenTestFile(const std::string& test_file_name) {
|
| + void DecodeIFrameThenTestFile(const std::string& test_file_name,
|
| + size_t expected_width,
|
| + size_t expected_height) {
|
| Initialize();
|
|
|
| scoped_refptr<VideoFrame> video_frame_a;
|
| @@ -188,27 +159,25 @@ class FFmpegVideoDecoderTest : public testing::Test {
|
| EXPECT_CALL(statistics_callback_, OnStatistics(_))
|
| .Times(2);
|
|
|
| - CallProduceVideoFrame(&video_frame_a);
|
| - CallProduceVideoFrame(&video_frame_b);
|
| + Read(&video_frame_a);
|
| + Read(&video_frame_b);
|
|
|
| - size_t expected_width = static_cast<size_t>(kVisibleRect.width());
|
| - size_t expected_height = static_cast<size_t>(kVisibleRect.height());
|
| + size_t original_width = static_cast<size_t>(kVisibleRect.width());
|
| + size_t original_height = static_cast<size_t>(kVisibleRect.height());
|
|
|
| ASSERT_TRUE(video_frame_a);
|
| ASSERT_TRUE(video_frame_b);
|
| - EXPECT_EQ(expected_width, video_frame_a->width());
|
| - EXPECT_EQ(expected_height, video_frame_a->height());
|
| + EXPECT_EQ(original_width, video_frame_a->width());
|
| + EXPECT_EQ(original_height, video_frame_a->height());
|
| EXPECT_EQ(expected_width, video_frame_b->width());
|
| EXPECT_EQ(expected_height, video_frame_b->height());
|
| }
|
|
|
| - void CallProduceVideoFrame(scoped_refptr<VideoFrame>* video_frame) {
|
| - EXPECT_CALL(*this, ConsumeVideoFrame(_))
|
| + void Read(scoped_refptr<VideoFrame>* video_frame) {
|
| + EXPECT_CALL(*this, FrameReady(_))
|
| .WillOnce(SaveArg<0>(video_frame));
|
|
|
| - decoder_->ProduceVideoFrame(VideoFrame::CreateFrame(
|
| - VideoFrame::YV12, kVisibleRect.width(), kVisibleRect.height(),
|
| - kNoTimestamp, kNoTimestamp));
|
| + decoder_->Read(read_cb_);
|
|
|
| message_loop_.RunAllPending();
|
| }
|
| @@ -227,7 +196,7 @@ class FFmpegVideoDecoderTest : public testing::Test {
|
|
|
| int64 PopTimestamp() {
|
| scoped_refptr<VideoFrame> video_frame;
|
| - CallProduceVideoFrame(&video_frame);
|
| + Read(&video_frame);
|
|
|
| return video_frame->GetTimestamp().InMicroseconds();
|
| }
|
| @@ -244,7 +213,7 @@ class FFmpegVideoDecoderTest : public testing::Test {
|
| read_callback.Run(i_frame_buffer_);
|
| }
|
|
|
| - MOCK_METHOD1(ConsumeVideoFrame, void(scoped_refptr<VideoFrame>));
|
| + MOCK_METHOD1(FrameReady, void(scoped_refptr<VideoFrame>));
|
|
|
| MessageLoop message_loop_;
|
| scoped_refptr<FFmpegVideoDecoder> decoder_;
|
| @@ -253,6 +222,8 @@ class FFmpegVideoDecoderTest : public testing::Test {
|
| StrictMock<MockFilterHost> host_;
|
| VideoDecoderConfig config_;
|
|
|
| + VideoDecoder::ReadCB read_cb_;
|
| +
|
| // Various buffers for testing.
|
| scoped_array<uint8_t> frame_buffer_;
|
| scoped_refptr<Buffer> end_of_stream_buffer_;
|
| @@ -270,7 +241,7 @@ TEST_F(FFmpegVideoDecoderTest, Initialize_Normal) {
|
| Initialize();
|
| }
|
|
|
| -TEST_F(FFmpegVideoDecoderTest, Initialize_FindDecoderFails) {
|
| +TEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedDecoder) {
|
| // Test avcodec_find_decoder() returning NULL.
|
| VideoDecoderConfig config(kUnknownVideoCodec, kVideoFormat,
|
| kCodedSize, kVisibleRect,
|
| @@ -282,6 +253,18 @@ TEST_F(FFmpegVideoDecoderTest, Initialize_FindDecoderFails) {
|
| InitializeWithConfig(config);
|
| }
|
|
|
| +TEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedPixelFormat) {
|
| + // Ensure decoder handles unsupport pixel formats without crashing.
|
| + VideoDecoderConfig config(kCodecVP8, VideoFrame::INVALID,
|
| + kCodedSize, kVisibleRect,
|
| + kFrameRate.num, kFrameRate.den,
|
| + kAspectRatio.num, kAspectRatio.den,
|
| + NULL, 0);
|
| +
|
| + EXPECT_CALL(host_, SetError(PIPELINE_ERROR_DECODE));
|
| + InitializeWithConfig(config);
|
| +}
|
| +
|
| TEST_F(FFmpegVideoDecoderTest, Initialize_OpenDecoderFails) {
|
| // Specify Theora w/o extra data so that avcodec_open() fails.
|
| VideoDecoderConfig config(kCodecTheora, kVideoFormat,
|
| @@ -323,11 +306,11 @@ TEST_F(FFmpegVideoDecoderTest, DecodeFrame_0ByteFrame) {
|
| .WillRepeatedly(ReturnBuffer(end_of_stream_buffer_));
|
|
|
| EXPECT_CALL(statistics_callback_, OnStatistics(_))
|
| - .Times(3);
|
| + .Times(2);
|
|
|
| - CallProduceVideoFrame(&video_frame_a);
|
| - CallProduceVideoFrame(&video_frame_b);
|
| - CallProduceVideoFrame(&video_frame_c);
|
| + Read(&video_frame_a);
|
| + Read(&video_frame_b);
|
| + Read(&video_frame_c);
|
|
|
| ASSERT_TRUE(video_frame_a);
|
| ASSERT_TRUE(video_frame_b);
|
| @@ -345,11 +328,20 @@ TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeError) {
|
| .WillOnce(ReturnBuffer(corrupt_i_frame_buffer_))
|
| .WillRepeatedly(ReturnBuffer(i_frame_buffer_));
|
|
|
| + // The error is only raised on the second decode attempt, so we expect at
|
| + // least one successful decode but we don't expect FrameReady() to be
|
| + // executed as an error is raised instead.
|
| + EXPECT_CALL(statistics_callback_, OnStatistics(_));
|
| + EXPECT_CALL(host_, SetError(PIPELINE_ERROR_DECODE));
|
| +
|
| + // Our read should still get satisfied with end of stream frame during an
|
| + // error.
|
| scoped_refptr<VideoFrame> video_frame;
|
| - CallProduceVideoFrame(&video_frame);
|
| + Read(&video_frame);
|
| + ASSERT_TRUE(video_frame);
|
| + EXPECT_TRUE(video_frame->IsEndOfStream());
|
|
|
| - // XXX: SERIOUSLY? This seems broken to call NULL on decoder error.
|
| - EXPECT_FALSE(video_frame);
|
| + message_loop_.RunAllPending();
|
| }
|
|
|
| // Multi-threaded decoders have different behavior than single-threaded
|
| @@ -368,29 +360,31 @@ TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeErrorAtEndOfStream) {
|
| }
|
|
|
| // Decode |i_frame_buffer_| and then a frame with a larger width and verify
|
| -// the output size didn't change.
|
| -// TODO(acolwell): Fix InvalidRead detected by Valgrind
|
| -//TEST_F(FFmpegVideoDecoderTest, DecodeFrame_LargerWidth) {
|
| -// DecodeIFrameThenTestFile("vp8-I-frame-640x240");
|
| -//}
|
| +// the output size was adjusted.
|
| +//
|
| +// TODO(acolwell): Fix InvalidRead detected by Valgrind http://crbug.com/102789
|
| +TEST_F(FFmpegVideoDecoderTest, DISABLED_DecodeFrame_LargerWidth) {
|
| + DecodeIFrameThenTestFile("vp8-I-frame-640x240", 640, 240);
|
| +}
|
|
|
| // Decode |i_frame_buffer_| and then a frame with a smaller width and verify
|
| -// the output size didn't change.
|
| +// the output size was adjusted.
|
| TEST_F(FFmpegVideoDecoderTest, DecodeFrame_SmallerWidth) {
|
| - DecodeIFrameThenTestFile("vp8-I-frame-160x240");
|
| + DecodeIFrameThenTestFile("vp8-I-frame-160x240", 160, 240);
|
| }
|
|
|
| // Decode |i_frame_buffer_| and then a frame with a larger height and verify
|
| -// the output size didn't change.
|
| -// TODO(acolwell): Fix InvalidRead detected by Valgrind
|
| -//TEST_F(FFmpegVideoDecoderTest, DecodeFrame_LargerHeight) {
|
| -// DecodeIFrameThenTestFile("vp8-I-frame-320x480");
|
| -//}
|
| +// the output size was adjusted.
|
| +//
|
| +// TODO(acolwell): Fix InvalidRead detected by Valgrind http://crbug.com/102789
|
| +TEST_F(FFmpegVideoDecoderTest, DISABLED_DecodeFrame_LargerHeight) {
|
| + DecodeIFrameThenTestFile("vp8-I-frame-320x480", 320, 480);
|
| +}
|
|
|
| // Decode |i_frame_buffer_| and then a frame with a smaller height and verify
|
| -// the output size didn't change.
|
| +// the output size was adjusted.
|
| TEST_F(FFmpegVideoDecoderTest, DecodeFrame_SmallerHeight) {
|
| - DecodeIFrameThenTestFile("vp8-I-frame-320x120");
|
| + DecodeIFrameThenTestFile("vp8-I-frame-320x120", 320, 120);
|
| }
|
|
|
| // Test pausing when decoder has initialized but not decoded.
|
| @@ -428,9 +422,7 @@ TEST_F(FFmpegVideoDecoderTest, Flush_Decoding) {
|
| }
|
|
|
| // Test flushing when decoder has hit end of stream.
|
| -//
|
| -// TODO(scherkus): test is disabled until we clean up buffer recycling.
|
| -TEST_F(FFmpegVideoDecoderTest, DISABLED_Flush_EndOfStream) {
|
| +TEST_F(FFmpegVideoDecoderTest, Flush_EndOfStream) {
|
| Initialize();
|
| EnterDecodingState();
|
| EnterEndOfStreamState();
|
| @@ -440,7 +432,6 @@ TEST_F(FFmpegVideoDecoderTest, DISABLED_Flush_EndOfStream) {
|
| // Test seeking when decoder has initialized but not decoded.
|
| TEST_F(FFmpegVideoDecoderTest, Seek_Initialized) {
|
| Initialize();
|
| - ExpectSeekPreroll();
|
| Seek(1000);
|
| }
|
|
|
| @@ -448,7 +439,6 @@ TEST_F(FFmpegVideoDecoderTest, Seek_Initialized) {
|
| TEST_F(FFmpegVideoDecoderTest, Seek_Decoding) {
|
| Initialize();
|
| EnterDecodingState();
|
| - ExpectSeekPreroll();
|
| Seek(1000);
|
| }
|
|
|
| @@ -457,7 +447,6 @@ TEST_F(FFmpegVideoDecoderTest, Seek_EndOfStream) {
|
| Initialize();
|
| EnterDecodingState();
|
| EnterEndOfStreamState();
|
| - ExpectSeekPrerollEndOfStream();
|
| Seek(1000);
|
| }
|
|
|
|
|