Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / filters / ffmpeg_glue_unittest.cc
blob5b97f3636f2e5658b9b43d92b80091643c3fd874
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/logging.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "media/base/mock_filters.h"
8 #include "media/base/test_data_util.h"
9 #include "media/ffmpeg/ffmpeg_common.h"
10 #include "media/filters/ffmpeg_glue.h"
11 #include "media/filters/in_memory_url_protocol.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 using ::testing::_;
15 using ::testing::DoAll;
16 using ::testing::InSequence;
17 using ::testing::Return;
18 using ::testing::SetArgumentPointee;
19 using ::testing::StrictMock;
21 namespace media {
23 class MockProtocol : public FFmpegURLProtocol {
24 public:
25 MockProtocol() {}
27 MOCK_METHOD2(Read, int(int size, uint8* data));
28 MOCK_METHOD1(GetPosition, bool(int64* position_out));
29 MOCK_METHOD1(SetPosition, bool(int64 position));
30 MOCK_METHOD1(GetSize, bool(int64* size_out));
31 MOCK_METHOD0(IsStreaming, bool());
33 private:
34 DISALLOW_COPY_AND_ASSIGN(MockProtocol);
37 class FFmpegGlueTest : public ::testing::Test {
38 public:
39 FFmpegGlueTest()
40 : protocol_(new StrictMock<MockProtocol>()) {
41 // IsStreaming() is called when opening.
42 EXPECT_CALL(*protocol_.get(), IsStreaming()).WillOnce(Return(true));
43 glue_.reset(new FFmpegGlue(protocol_.get()));
44 CHECK(glue_->format_context());
45 CHECK(glue_->format_context()->pb);
48 ~FFmpegGlueTest() override {
49 // Ensure |glue_| and |protocol_| are still alive.
50 CHECK(glue_.get());
51 CHECK(protocol_.get());
53 // |protocol_| should outlive |glue_|, so ensure it's destructed first.
54 glue_.reset();
57 int ReadPacket(int size, uint8* data) {
58 return glue_->format_context()->pb->read_packet(
59 protocol_.get(), data, size);
62 int64 Seek(int64 offset, int whence) {
63 return glue_->format_context()->pb->seek(protocol_.get(), offset, whence);
66 protected:
67 scoped_ptr<FFmpegGlue> glue_;
68 scoped_ptr< StrictMock<MockProtocol> > protocol_;
70 private:
71 DISALLOW_COPY_AND_ASSIGN(FFmpegGlueTest);
74 class FFmpegGlueDestructionTest : public ::testing::Test {
75 public:
76 FFmpegGlueDestructionTest() {}
78 void Initialize(const char* filename) {
79 data_ = ReadTestDataFile(filename);
80 protocol_.reset(new InMemoryUrlProtocol(
81 data_->data(), data_->data_size(), false));
82 glue_.reset(new FFmpegGlue(protocol_.get()));
83 CHECK(glue_->format_context());
84 CHECK(glue_->format_context()->pb);
87 ~FFmpegGlueDestructionTest() override {
88 // Ensure Initialize() was called.
89 CHECK(glue_.get());
90 CHECK(protocol_.get());
92 // |glue_| should be destroyed before |protocol_|.
93 glue_.reset();
95 // |protocol_| should be destroyed before |data_|.
96 protocol_.reset();
97 data_ = NULL;
100 protected:
101 scoped_ptr<FFmpegGlue> glue_;
103 private:
104 scoped_ptr<InMemoryUrlProtocol> protocol_;
105 scoped_refptr<DecoderBuffer> data_;
107 DISALLOW_COPY_AND_ASSIGN(FFmpegGlueDestructionTest);
110 // Ensure writing has been disabled.
111 TEST_F(FFmpegGlueTest, Write) {
112 ASSERT_FALSE(glue_->format_context()->pb->write_packet);
113 ASSERT_FALSE(glue_->format_context()->pb->write_flag);
116 // Test both successful and unsuccessful reads pass through correctly.
117 TEST_F(FFmpegGlueTest, Read) {
118 const int kBufferSize = 16;
119 uint8 buffer[kBufferSize];
121 // Reads are for the most part straight-through calls to Read().
122 InSequence s;
123 EXPECT_CALL(*protocol_, Read(0, buffer))
124 .WillOnce(Return(0));
125 EXPECT_CALL(*protocol_, Read(kBufferSize, buffer))
126 .WillOnce(Return(kBufferSize));
127 EXPECT_CALL(*protocol_, Read(kBufferSize, buffer))
128 .WillOnce(Return(DataSource::kReadError));
130 EXPECT_EQ(0, ReadPacket(0, buffer));
131 EXPECT_EQ(kBufferSize, ReadPacket(kBufferSize, buffer));
132 EXPECT_EQ(AVERROR(EIO), ReadPacket(kBufferSize, buffer));
135 // Test a variety of seek operations.
136 TEST_F(FFmpegGlueTest, Seek) {
137 // SEEK_SET should be a straight-through call to SetPosition(), which when
138 // successful will return the result from GetPosition().
139 InSequence s;
140 EXPECT_CALL(*protocol_, SetPosition(-16))
141 .WillOnce(Return(false));
143 EXPECT_CALL(*protocol_, SetPosition(16))
144 .WillOnce(Return(true));
145 EXPECT_CALL(*protocol_, GetPosition(_))
146 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
148 EXPECT_EQ(AVERROR(EIO), Seek(-16, SEEK_SET));
149 EXPECT_EQ(8, Seek(16, SEEK_SET));
151 // SEEK_CUR should call GetPosition() first, and if it succeeds add the offset
152 // to the result then call SetPosition()+GetPosition().
153 EXPECT_CALL(*protocol_, GetPosition(_))
154 .WillOnce(Return(false));
156 EXPECT_CALL(*protocol_, GetPosition(_))
157 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
158 EXPECT_CALL(*protocol_, SetPosition(16))
159 .WillOnce(Return(false));
161 EXPECT_CALL(*protocol_, GetPosition(_))
162 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
163 EXPECT_CALL(*protocol_, SetPosition(16))
164 .WillOnce(Return(true));
165 EXPECT_CALL(*protocol_, GetPosition(_))
166 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
168 EXPECT_EQ(AVERROR(EIO), Seek(8, SEEK_CUR));
169 EXPECT_EQ(AVERROR(EIO), Seek(8, SEEK_CUR));
170 EXPECT_EQ(16, Seek(8, SEEK_CUR));
172 // SEEK_END should call GetSize() first, and if it succeeds add the offset
173 // to the result then call SetPosition()+GetPosition().
174 EXPECT_CALL(*protocol_, GetSize(_))
175 .WillOnce(Return(false));
177 EXPECT_CALL(*protocol_, GetSize(_))
178 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
179 EXPECT_CALL(*protocol_, SetPosition(8))
180 .WillOnce(Return(false));
182 EXPECT_CALL(*protocol_, GetSize(_))
183 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
184 EXPECT_CALL(*protocol_, SetPosition(8))
185 .WillOnce(Return(true));
186 EXPECT_CALL(*protocol_, GetPosition(_))
187 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
189 EXPECT_EQ(AVERROR(EIO), Seek(-8, SEEK_END));
190 EXPECT_EQ(AVERROR(EIO), Seek(-8, SEEK_END));
191 EXPECT_EQ(8, Seek(-8, SEEK_END));
193 // AVSEEK_SIZE should be a straight-through call to GetSize().
194 EXPECT_CALL(*protocol_, GetSize(_))
195 .WillOnce(Return(false));
197 EXPECT_CALL(*protocol_, GetSize(_))
198 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
200 EXPECT_EQ(AVERROR(EIO), Seek(0, AVSEEK_SIZE));
201 EXPECT_EQ(16, Seek(0, AVSEEK_SIZE));
204 // Ensure destruction release the appropriate resources when OpenContext() is
205 // never called.
206 TEST_F(FFmpegGlueDestructionTest, WithoutOpen) {
207 Initialize("ten_byte_file");
210 // Ensure destruction releases the appropriate resources when
211 // avformat_open_input() fails.
212 TEST_F(FFmpegGlueDestructionTest, WithOpenFailure) {
213 Initialize("ten_byte_file");
214 ASSERT_FALSE(glue_->OpenContext());
217 // Ensure destruction release the appropriate resources when OpenContext() is
218 // called, but no streams have been opened.
219 TEST_F(FFmpegGlueDestructionTest, WithOpenNoStreams) {
220 Initialize("no_streams.webm");
221 ASSERT_TRUE(glue_->OpenContext());
224 // Ensure destruction release the appropriate resources when OpenContext() is
225 // called and streams exist.
226 TEST_F(FFmpegGlueDestructionTest, WithOpenWithStreams) {
227 Initialize("bear-320x240.webm");
228 ASSERT_TRUE(glue_->OpenContext());
231 // Ensure destruction release the appropriate resources when OpenContext() is
232 // called and streams have been opened.
233 TEST_F(FFmpegGlueDestructionTest, WithOpenWithOpenStreams) {
234 Initialize("bear-320x240.webm");
235 ASSERT_TRUE(glue_->OpenContext());
236 ASSERT_GT(glue_->format_context()->nb_streams, 0u);
238 // Pick the audio stream (1) so this works when the ffmpeg video decoders are
239 // disabled.
240 AVCodecContext* context = glue_->format_context()->streams[1]->codec;
241 ASSERT_EQ(0, avcodec_open2(
242 context, avcodec_find_decoder(context->codec_id), NULL));
245 } // namespace media