16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (c) 2012 The Chromium Authors. All rights reserved. 26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Use of this source code is governed by a BSD-style license that can be 36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// found in the LICENSE file. 46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <list> 66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <string> 76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <vector> 86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "base/bind.h" 106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "base/callback_helpers.h" 116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "base/memory/singleton.h" 126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "base/message_loop/message_loop.h" 136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "base/strings/string_util.h" 146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/base/decoder_buffer.h" 156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/base/gmock_callback_support.h" 166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/base/limits.h" 176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/base/mock_filters.h" 186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/base/test_data_util.h" 196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/base/test_helpers.h" 206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/base/video_decoder.h" 216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/base/video_frame.h" 226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/base/video_util.h" 236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/ffmpeg/ffmpeg_common.h" 246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/filters/ffmpeg_glue.h" 256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "media/filters/ffmpeg_video_decoder.h" 266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "testing/gmock/include/gmock/gmock.h" 276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing ::testing::_; 296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing ::testing::AtLeast; 306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing ::testing::AtMost; 316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing ::testing::InSequence; 326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing ::testing::IsNull; 336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing ::testing::Return; 346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing ::testing::SaveArg; 356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing ::testing::StrictMock; 366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennnamespace media { 386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const VideoFrame::Format kVideoFormat = VideoFrame::YV12; 406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const gfx::Size kCodedSize(320, 240); 416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const gfx::Rect kVisibleRect(320, 240); 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const gfx::Size kNaturalSize(320, 240); 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennACTION_P(ReturnBuffer, buffer) { 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn arg0.Run(buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer); 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennclass FFmpegVideoDecoderTest : public testing::Test { 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public: 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn FFmpegVideoDecoderTest() 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn : decoder_(new FFmpegVideoDecoder(message_loop_.message_loop_proxy())), 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn decode_cb_(base::Bind(&FFmpegVideoDecoderTest::DecodeDone, 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base::Unretained(this))) { 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn FFmpegGlue::InitializeFFmpeg(); 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Initialize various test buffers. 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn frame_buffer_.reset(new uint8[kCodedSize.GetArea()]); 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn end_of_stream_buffer_ = DecoderBuffer::CreateEOSBuffer(); 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn i_frame_buffer_ = ReadTestDataFile("vp8-I-frame-320x240"); 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn corrupt_i_frame_buffer_ = ReadTestDataFile("vp8-corrupt-I-frame"); 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn virtual ~FFmpegVideoDecoderTest() { 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Destroy(); 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void Initialize() { 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn InitializeWithConfig(TestVideoConfig::Normal()); 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void InitializeWithConfigAndStatus(const VideoDecoderConfig& config, 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PipelineStatus status) { 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn decoder_->Initialize(config, false, NewExpectedStatusCB(status), 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base::Bind(&FFmpegVideoDecoderTest::FrameReady, 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base::Unretained(this))); 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn message_loop_.RunUntilIdle(); 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void InitializeWithConfig(const VideoDecoderConfig& config) { 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn InitializeWithConfigAndStatus(config, PIPELINE_OK); 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void Reinitialize() { 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn InitializeWithConfig(TestVideoConfig::Large()); 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void Reset() { 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn decoder_->Reset(NewExpectedClosure()); 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn message_loop_.RunUntilIdle(); 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void Destroy() { 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn decoder_.reset(); 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn message_loop_.RunUntilIdle(); 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Sets up expectations and actions to put FFmpegVideoDecoder in an active 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // decoding state. 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void EnterDecodingState() { 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(i_frame_buffer_)); 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ASSERT_EQ(1U, output_frames_.size()); 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Sets up expectations and actions to put FFmpegVideoDecoder in an end 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // of stream state. 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void EnterEndOfStreamState() { 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(end_of_stream_buffer_)); 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ASSERT_FALSE(output_frames_.empty()); 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn typedef std::vector<scoped_refptr<DecoderBuffer> > InputBuffers; 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn typedef std::vector<scoped_refptr<VideoFrame> > OutputFrames; 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Decodes all buffers in |input_buffers| and push all successfully decoded 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // output frames into |output_frames|. 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Returns the last decode status returned by the decoder. 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn VideoDecoder::Status DecodeMultipleFrames(const InputBuffers& input_buffers) { 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (InputBuffers::const_iterator iter = input_buffers.begin(); 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn iter != input_buffers.end(); 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ++iter) { 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn VideoDecoder::Status status = Decode(*iter); 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn switch (status) { 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn case VideoDecoder::kOk: 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn case VideoDecoder::kAborted: 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn NOTREACHED(); 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn case VideoDecoder::kDecodeError: 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn case VideoDecoder::kDecryptError: 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn DCHECK(output_frames_.empty()); 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return status; 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return VideoDecoder::kOk; 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Decodes the single compressed frame in |buffer| and writes the 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // uncompressed output to |video_frame|. This method works with single 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // and multithreaded decoders. End of stream buffers are used to trigger 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // the frame to be returned in the multithreaded decoder case. 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn VideoDecoder::Status DecodeSingleFrame( 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const scoped_refptr<DecoderBuffer>& buffer) { 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn InputBuffers input_buffers; 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn input_buffers.push_back(buffer); 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn input_buffers.push_back(end_of_stream_buffer_); 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return DecodeMultipleFrames(input_buffers); 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Decodes |i_frame_buffer_| and then decodes the data contained in 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // the file named |test_file_name|. This function expects both buffers 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // to decode to frames that are the same size. 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void DecodeIFrameThenTestFile(const std::string& test_file_name, 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int expected_width, 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int expected_height) { 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Initialize(); 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name); 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn InputBuffers input_buffers; 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn input_buffers.push_back(i_frame_buffer_); 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn input_buffers.push_back(buffer); 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn input_buffers.push_back(end_of_stream_buffer_); 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn VideoDecoder::Status status = 1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn DecodeMultipleFrames(input_buffers); 1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXPECT_EQ(VideoDecoder::kOk, status); 1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ASSERT_EQ(2U, output_frames_.size()); 1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn gfx::Size original_size = kVisibleRect.size(); 1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXPECT_EQ(original_size.width(), 1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn output_frames_[0]->visible_rect().size().width()); 1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXPECT_EQ(original_size.height(), 1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn output_frames_[0]->visible_rect().size().height()); 1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXPECT_EQ(expected_width, 1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn output_frames_[1]->visible_rect().size().width()); 1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXPECT_EQ(expected_height, 1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn output_frames_[1]->visible_rect().size().height()); 1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn VideoDecoder::Status Decode(const scoped_refptr<DecoderBuffer>& buffer) { 1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn VideoDecoder::Status status; 1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXPECT_CALL(*this, DecodeDone(_)).WillOnce(SaveArg<0>(&status)); 1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn decoder_->Decode(buffer, decode_cb_); 1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn message_loop_.RunUntilIdle(); 1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return status; 1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void FrameReady(const scoped_refptr<VideoFrame>& frame) { 1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn DCHECK(!frame->end_of_stream()); 1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn output_frames_.push_back(frame); 1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MOCK_METHOD1(DecodeDone, void(VideoDecoder::Status)); 1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base::MessageLoop message_loop_; 1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scoped_ptr<FFmpegVideoDecoder> decoder_; 2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn VideoDecoder::DecodeCB decode_cb_; 2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Various buffers for testing. 2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scoped_ptr<uint8_t[]> frame_buffer_; 2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scoped_refptr<DecoderBuffer> end_of_stream_buffer_; 2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scoped_refptr<DecoderBuffer> i_frame_buffer_; 2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scoped_refptr<DecoderBuffer> corrupt_i_frame_buffer_; 2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn OutputFrames output_frames_; 2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn private: 2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn DISALLOW_COPY_AND_ASSIGN(FFmpegVideoDecoderTest); 2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}; 2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennTEST_F(FFmpegVideoDecoderTest, Initialize_Normal) { 2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Initialize(); 2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennTEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedDecoder) { 2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Test avcodec_find_decoder() returning NULL. 2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn InitializeWithConfigAndStatus(TestVideoConfig::Invalid(), 2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn DECODER_ERROR_NOT_SUPPORTED); 2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennTEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedPixelFormat) { 2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Ensure decoder handles unsupported pixel formats without crashing. 2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, 2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn VideoFrame::UNKNOWN, 2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn kCodedSize, kVisibleRect, kNaturalSize, 2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn NULL, 0, false); 2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn InitializeWithConfigAndStatus(config, DECODER_ERROR_NOT_SUPPORTED); 2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennTEST_F(FFmpegVideoDecoderTest, Initialize_OpenDecoderFails) { 235 // Specify Theora w/o extra data so that avcodec_open2() fails. 236 VideoDecoderConfig config(kCodecTheora, VIDEO_CODEC_PROFILE_UNKNOWN, 237 kVideoFormat, 238 kCodedSize, kVisibleRect, kNaturalSize, 239 NULL, 0, false); 240 InitializeWithConfigAndStatus(config, DECODER_ERROR_NOT_SUPPORTED); 241} 242 243TEST_F(FFmpegVideoDecoderTest, Initialize_AspectRatioNumeratorZero) { 244 gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 0, 1); 245 VideoDecoderConfig config(kCodecVP8, 246 VP8PROFILE_ANY, 247 kVideoFormat, 248 kCodedSize, 249 kVisibleRect, 250 natural_size, 251 NULL, 252 0, 253 false); 254 InitializeWithConfigAndStatus(config, DECODER_ERROR_NOT_SUPPORTED); 255} 256 257TEST_F(FFmpegVideoDecoderTest, Initialize_AspectRatioDenominatorZero) { 258 gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 1, 0); 259 VideoDecoderConfig config(kCodecVP8, 260 VP8PROFILE_ANY, 261 kVideoFormat, 262 kCodedSize, 263 kVisibleRect, 264 natural_size, 265 NULL, 266 0, 267 false); 268 InitializeWithConfigAndStatus(config, DECODER_ERROR_NOT_SUPPORTED); 269} 270 271TEST_F(FFmpegVideoDecoderTest, Initialize_AspectRatioNumeratorNegative) { 272 gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), -1, 1); 273 VideoDecoderConfig config(kCodecVP8, 274 VP8PROFILE_ANY, 275 kVideoFormat, 276 kCodedSize, 277 kVisibleRect, 278 natural_size, 279 NULL, 280 0, 281 false); 282 InitializeWithConfigAndStatus(config, DECODER_ERROR_NOT_SUPPORTED); 283} 284 285TEST_F(FFmpegVideoDecoderTest, Initialize_AspectRatioDenominatorNegative) { 286 gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 1, -1); 287 VideoDecoderConfig config(kCodecVP8, 288 VP8PROFILE_ANY, 289 kVideoFormat, 290 kCodedSize, 291 kVisibleRect, 292 natural_size, 293 NULL, 294 0, 295 false); 296 InitializeWithConfigAndStatus(config, DECODER_ERROR_NOT_SUPPORTED); 297} 298 299TEST_F(FFmpegVideoDecoderTest, Initialize_AspectRatioNumeratorTooLarge) { 300 int width = kVisibleRect.size().width(); 301 int num = ceil(static_cast<double>(limits::kMaxDimension + 1) / width); 302 gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), num, 1); 303 VideoDecoderConfig config(kCodecVP8, 304 VP8PROFILE_ANY, 305 kVideoFormat, 306 kCodedSize, 307 kVisibleRect, 308 natural_size, 309 NULL, 310 0, 311 false); 312 InitializeWithConfigAndStatus(config, DECODER_ERROR_NOT_SUPPORTED); 313} 314 315TEST_F(FFmpegVideoDecoderTest, Initialize_AspectRatioDenominatorTooLarge) { 316 int den = kVisibleRect.size().width() + 1; 317 gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 1, den); 318 VideoDecoderConfig config(kCodecVP8, 319 VP8PROFILE_ANY, 320 kVideoFormat, 321 kCodedSize, 322 kVisibleRect, 323 natural_size, 324 NULL, 325 0, 326 false); 327 InitializeWithConfigAndStatus(config, DECODER_ERROR_NOT_SUPPORTED); 328} 329 330TEST_F(FFmpegVideoDecoderTest, Reinitialize_Normal) { 331 Initialize(); 332 Reinitialize(); 333} 334 335TEST_F(FFmpegVideoDecoderTest, Reinitialize_Failure) { 336 Initialize(); 337 InitializeWithConfigAndStatus(TestVideoConfig::Invalid(), 338 DECODER_ERROR_NOT_SUPPORTED); 339} 340 341TEST_F(FFmpegVideoDecoderTest, Reinitialize_AfterDecodeFrame) { 342 Initialize(); 343 EnterDecodingState(); 344 Reinitialize(); 345} 346 347TEST_F(FFmpegVideoDecoderTest, Reinitialize_AfterReset) { 348 Initialize(); 349 EnterDecodingState(); 350 Reset(); 351 Reinitialize(); 352} 353 354TEST_F(FFmpegVideoDecoderTest, DecodeFrame_Normal) { 355 Initialize(); 356 357 // Simulate decoding a single frame. 358 EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(i_frame_buffer_)); 359 ASSERT_EQ(1U, output_frames_.size()); 360} 361 362// Verify current behavior for 0 byte frames. FFmpeg simply ignores 363// the 0 byte frames. 364TEST_F(FFmpegVideoDecoderTest, DecodeFrame_0ByteFrame) { 365 Initialize(); 366 367 scoped_refptr<DecoderBuffer> zero_byte_buffer = new DecoderBuffer(0); 368 369 InputBuffers input_buffers; 370 input_buffers.push_back(i_frame_buffer_); 371 input_buffers.push_back(zero_byte_buffer); 372 input_buffers.push_back(i_frame_buffer_); 373 input_buffers.push_back(end_of_stream_buffer_); 374 375 VideoDecoder::Status status = DecodeMultipleFrames(input_buffers); 376 377 EXPECT_EQ(VideoDecoder::kOk, status); 378 ASSERT_EQ(2U, output_frames_.size()); 379} 380 381TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeError) { 382 Initialize(); 383 384 // The error is only raised on the second decode attempt, so we expect at 385 // least one successful decode but we don't expect valid frame to be decoded. 386 // During the second decode attempt an error is raised. 387 EXPECT_EQ(VideoDecoder::kOk, Decode(corrupt_i_frame_buffer_)); 388 EXPECT_TRUE(output_frames_.empty()); 389 EXPECT_EQ(VideoDecoder::kDecodeError, Decode(i_frame_buffer_)); 390 EXPECT_TRUE(output_frames_.empty()); 391 392 // After a decode error occurred, all following decodes will return 393 // kDecodeError. 394 EXPECT_EQ(VideoDecoder::kDecodeError, Decode(i_frame_buffer_)); 395 EXPECT_TRUE(output_frames_.empty()); 396} 397 398// Multi-threaded decoders have different behavior than single-threaded 399// decoders at the end of the stream. Multithreaded decoders hide errors 400// that happen on the last |codec_context_->thread_count| frames to avoid 401// prematurely signalling EOS. This test just exposes that behavior so we can 402// detect if it changes. 403TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeErrorAtEndOfStream) { 404 Initialize(); 405 406 EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(corrupt_i_frame_buffer_)); 407} 408 409// Decode |i_frame_buffer_| and then a frame with a larger width and verify 410// the output size was adjusted. 411TEST_F(FFmpegVideoDecoderTest, DecodeFrame_LargerWidth) { 412 DecodeIFrameThenTestFile("vp8-I-frame-640x240", 640, 240); 413} 414 415// Decode |i_frame_buffer_| and then a frame with a smaller width and verify 416// the output size was adjusted. 417TEST_F(FFmpegVideoDecoderTest, DecodeFrame_SmallerWidth) { 418 DecodeIFrameThenTestFile("vp8-I-frame-160x240", 160, 240); 419} 420 421// Decode |i_frame_buffer_| and then a frame with a larger height and verify 422// the output size was adjusted. 423TEST_F(FFmpegVideoDecoderTest, DecodeFrame_LargerHeight) { 424 DecodeIFrameThenTestFile("vp8-I-frame-320x480", 320, 480); 425} 426 427// Decode |i_frame_buffer_| and then a frame with a smaller height and verify 428// the output size was adjusted. 429TEST_F(FFmpegVideoDecoderTest, DecodeFrame_SmallerHeight) { 430 DecodeIFrameThenTestFile("vp8-I-frame-320x120", 320, 120); 431} 432 433// Test resetting when decoder has initialized but not decoded. 434TEST_F(FFmpegVideoDecoderTest, Reset_Initialized) { 435 Initialize(); 436 Reset(); 437} 438 439// Test resetting when decoder has decoded single frame. 440TEST_F(FFmpegVideoDecoderTest, Reset_Decoding) { 441 Initialize(); 442 EnterDecodingState(); 443 Reset(); 444} 445 446// Test resetting when decoder has hit end of stream. 447TEST_F(FFmpegVideoDecoderTest, Reset_EndOfStream) { 448 Initialize(); 449 EnterDecodingState(); 450 EnterEndOfStreamState(); 451 Reset(); 452} 453 454// Test destruction when decoder has initialized but not decoded. 455TEST_F(FFmpegVideoDecoderTest, Destroy_Initialized) { 456 Initialize(); 457 Destroy(); 458} 459 460// Test destruction when decoder has decoded single frame. 461TEST_F(FFmpegVideoDecoderTest, Destroy_Decoding) { 462 Initialize(); 463 EnterDecodingState(); 464 Destroy(); 465} 466 467// Test destruction when decoder has hit end of stream. 468TEST_F(FFmpegVideoDecoderTest, Destroy_EndOfStream) { 469 Initialize(); 470 EnterDecodingState(); 471 EnterEndOfStreamState(); 472 Destroy(); 473} 474 475} // namespace media 476