blob: 85ca34e6f8800ed7804bf59b2bddf3ac6f23577e [file] [log] [blame]
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <deque>
#include "media/base/mock_ffmpeg.h"
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/filters/bitstream_converter.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::DoAll;
using ::testing::Mock;
using ::testing::Return;
using ::testing::ReturnNull;
using ::testing::SetArgumentPointee;
using ::testing::StrEq;
using ::testing::StrictMock;
using ::testing::_;
namespace media {
class BitstreamConverterTest : public testing::Test {
protected:
BitstreamConverterTest() {
// Initialize MockFFmpeg.
MockFFmpeg::set(&mock_ffmpeg_);
memset(&test_stream_context_, 0, sizeof(test_stream_context_));
memset(&test_filter_, 0, sizeof(test_filter_));
memset(&test_packet_, 0, sizeof(test_packet_));
test_packet_.data = kData1;
test_packet_.size = kTestSize1;
}
virtual ~BitstreamConverterTest() {
// Reset MockFFmpeg.
MockFFmpeg::set(NULL);
}
AVCodecContext test_stream_context_;
AVBitStreamFilterContext test_filter_;
AVPacket test_packet_;
StrictMock<MockFFmpeg> mock_ffmpeg_;
static const char kTestFilterName[];
static uint8_t kData1[];
static uint8_t kData2[];
static const int kTestSize1;
static const int kTestSize2;
private:
DISALLOW_COPY_AND_ASSIGN(BitstreamConverterTest);
};
const char BitstreamConverterTest::kTestFilterName[] = "test_filter";
uint8_t BitstreamConverterTest::kData1[] = { 1 };
uint8_t BitstreamConverterTest::kData2[] = { 2 };
const int BitstreamConverterTest::kTestSize1 = 1;
const int BitstreamConverterTest::kTestSize2 = 2;
TEST_F(BitstreamConverterTest, Initialize) {
FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_);
// Test Initialize returns false on a bad initialization, and cleanup is not
// done.
EXPECT_CALL(mock_ffmpeg_, AVBitstreamFilterInit(StrEq(kTestFilterName)))
.WillOnce(ReturnNull());
EXPECT_FALSE(converter.Initialize());
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_ffmpeg_));
// Test Initialize returns true on successful initialization, and cleanup is
// done. The cleanup will be activated when the converter object goes out of
// scope.
EXPECT_CALL(mock_ffmpeg_, AVBitstreamFilterInit(StrEq(kTestFilterName)))
.WillOnce(Return(&test_filter_));
EXPECT_CALL(mock_ffmpeg_, AVBitstreamFilterClose(&test_filter_));
EXPECT_TRUE(converter.Initialize());
}
TEST_F(BitstreamConverterTest, ConvertPacket_NotInitialized) {
FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_);
EXPECT_FALSE(converter.ConvertPacket(&test_packet_));
}
TEST_F(BitstreamConverterTest, ConvertPacket_FailedFilter) {
FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_);
// Inject mock filter instance.
converter.stream_filter_ = &test_filter_;
// Simulate a successful filter call, that allocates a new data buffer.
EXPECT_CALL(mock_ffmpeg_,
AVBitstreamFilterFilter(&test_filter_, &test_stream_context_,
NULL, _, _,
test_packet_.data, test_packet_.size, _))
.WillOnce(Return(AVERROR_UNKNOWN));
EXPECT_FALSE(converter.ConvertPacket(&test_packet_));
// Uninject mock filter instance to avoid cleanup code on destruction of
// converter.
converter.stream_filter_ = NULL;
}
TEST_F(BitstreamConverterTest, ConvertPacket_Success) {
FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_);
// Inject mock filter instance.
converter.stream_filter_ = &test_filter_;
// Ensure our packet doesn't already have a destructor.
ASSERT_TRUE(test_packet_.destruct == NULL);
// Simulate a successful filter call, that allocates a new data buffer.
EXPECT_CALL(mock_ffmpeg_,
AVBitstreamFilterFilter(&test_filter_, &test_stream_context_,
NULL, _, _,
test_packet_.data, test_packet_.size, _))
.WillOnce(DoAll(SetArgumentPointee<3>(&kData2[0]),
SetArgumentPointee<4>(kTestSize2),
Return(0)));
EXPECT_CALL(mock_ffmpeg_, AVFreePacket(&test_packet_));
EXPECT_TRUE(converter.ConvertPacket(&test_packet_));
EXPECT_EQ(kData2, test_packet_.data);
EXPECT_EQ(kTestSize2, test_packet_.size);
EXPECT_TRUE(test_packet_.destruct != NULL);
// Uninject mock filter instance to avoid cleanup code on destruction of
// converter.
converter.stream_filter_ = NULL;
}
TEST_F(BitstreamConverterTest, ConvertPacket_SuccessInPlace) {
FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_);
// Inject mock filter instance.
converter.stream_filter_ = &test_filter_;
// Ensure our packet is in a sane start state.
ASSERT_TRUE(test_packet_.destruct == NULL);
ASSERT_EQ(kData1, test_packet_.data);
ASSERT_EQ(kTestSize1, test_packet_.size);
// Simulate a successful filter call, that reuses the input buffer. We should
// not free the packet here or alter the packet's destructor.
EXPECT_CALL(mock_ffmpeg_,
AVBitstreamFilterFilter(&test_filter_, &test_stream_context_,
NULL, _, _,
test_packet_.data, test_packet_.size, _))
.WillOnce(DoAll(SetArgumentPointee<3>(test_packet_.data),
SetArgumentPointee<4>(test_packet_.size),
Return(0)));
EXPECT_TRUE(converter.ConvertPacket(&test_packet_));
EXPECT_EQ(kData1, test_packet_.data);
EXPECT_EQ(kTestSize1, test_packet_.size);
EXPECT_TRUE(test_packet_.destruct == NULL);
// Uninject mock filter instance to avoid cleanup code on destruction of
// converter.
converter.stream_filter_ = NULL;
}
} // namespace media