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