Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / media / filters / ffmpeg_glue_unittest.cc
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.
4
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"
13
14 using ::testing::_;
15 using ::testing::DoAll;
16 using ::testing::InSequence;
17 using ::testing::Return;
18 using ::testing::SetArgumentPointee;
19 using ::testing::StrictMock;
20
21 namespace media {
22
23 class MockProtocol : public FFmpegURLProtocol {
24  public:
25   MockProtocol() {}
26
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());
32
33  private:
34   DISALLOW_COPY_AND_ASSIGN(MockProtocol);
35 };
36
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);
46   }
47
48   ~FFmpegGlueTest() override {
49     // Ensure |glue_| and |protocol_| are still alive.
50     CHECK(glue_.get());
51     CHECK(protocol_.get());
52
53     // |protocol_| should outlive |glue_|, so ensure it's destructed first.
54     glue_.reset();
55   }
56
57   int ReadPacket(int size, uint8* data) {
58     return glue_->format_context()->pb->read_packet(
59         protocol_.get(), data, size);
60   }
61
62   int64 Seek(int64 offset, int whence) {
63     return glue_->format_context()->pb->seek(protocol_.get(), offset, whence);
64   }
65
66  protected:
67   scoped_ptr<FFmpegGlue> glue_;
68   scoped_ptr< StrictMock<MockProtocol> > protocol_;
69
70  private:
71   DISALLOW_COPY_AND_ASSIGN(FFmpegGlueTest);
72 };
73
74 class FFmpegGlueDestructionTest : public ::testing::Test {
75  public:
76   FFmpegGlueDestructionTest() {}
77
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);
85   }
86
87   ~FFmpegGlueDestructionTest() override {
88     // Ensure Initialize() was called.
89     CHECK(glue_.get());
90     CHECK(protocol_.get());
91
92     // |glue_| should be destroyed before |protocol_|.
93     glue_.reset();
94
95     // |protocol_| should be destroyed before |data_|.
96     protocol_.reset();
97     data_ = NULL;
98   }
99
100  protected:
101   scoped_ptr<FFmpegGlue> glue_;
102
103  private:
104   scoped_ptr<InMemoryUrlProtocol> protocol_;
105   scoped_refptr<DecoderBuffer> data_;
106
107   DISALLOW_COPY_AND_ASSIGN(FFmpegGlueDestructionTest);
108 };
109
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);
114 }
115
116 // Test both successful and unsuccessful reads pass through correctly.
117 TEST_F(FFmpegGlueTest, Read) {
118   const int kBufferSize = 16;
119   uint8 buffer[kBufferSize];
120
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));
129
130   EXPECT_EQ(0, ReadPacket(0, buffer));
131   EXPECT_EQ(kBufferSize, ReadPacket(kBufferSize, buffer));
132   EXPECT_EQ(AVERROR(EIO), ReadPacket(kBufferSize, buffer));
133 }
134
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));
142
143   EXPECT_CALL(*protocol_, SetPosition(16))
144       .WillOnce(Return(true));
145   EXPECT_CALL(*protocol_, GetPosition(_))
146       .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
147
148   EXPECT_EQ(AVERROR(EIO), Seek(-16, SEEK_SET));
149   EXPECT_EQ(8, Seek(16, SEEK_SET));
150
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));
155
156   EXPECT_CALL(*protocol_, GetPosition(_))
157       .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
158   EXPECT_CALL(*protocol_, SetPosition(16))
159       .WillOnce(Return(false));
160
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)));
167
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));
171
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));
176
177   EXPECT_CALL(*protocol_, GetSize(_))
178       .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
179   EXPECT_CALL(*protocol_, SetPosition(8))
180       .WillOnce(Return(false));
181
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)));
188
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));
192
193   // AVSEEK_SIZE should be a straight-through call to GetSize().
194   EXPECT_CALL(*protocol_, GetSize(_))
195       .WillOnce(Return(false));
196
197   EXPECT_CALL(*protocol_, GetSize(_))
198       .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
199
200   EXPECT_EQ(AVERROR(EIO), Seek(0, AVSEEK_SIZE));
201   EXPECT_EQ(16, Seek(0, AVSEEK_SIZE));
202 }
203
204 // Ensure destruction release the appropriate resources when OpenContext() is
205 // never called.
206 TEST_F(FFmpegGlueDestructionTest, WithoutOpen) {
207   Initialize("ten_byte_file");
208 }
209
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());
215 }
216
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());
222 }
223
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());
229 }
230
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);
237
238   AVCodecContext* context = glue_->format_context()->streams[0]->codec;
239   ASSERT_EQ(avcodec_open2(
240       context, avcodec_find_decoder(context->codec_id), NULL), 0);
241 }
242
243 }  // namespace media