Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: media/filters/ffmpeg_demuxer_unittest.cc

Issue 7587012: Remove mock_ffmpeg and update media unittests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <deque> 5 #include <deque>
6 6
7 #include "base/file_path.h"
8 #include "base/path_service.h"
7 #include "base/threading/thread.h" 9 #include "base/threading/thread.h"
8 #include "media/base/filters.h" 10 #include "media/base/filters.h"
11 #include "media/base/media.h"
9 #include "media/base/mock_callback.h" 12 #include "media/base/mock_callback.h"
10 #include "media/base/mock_ffmpeg.h"
11 #include "media/base/mock_filter_host.h" 13 #include "media/base/mock_filter_host.h"
12 #include "media/base/mock_filters.h" 14 #include "media/base/mock_filters.h"
13 #include "media/base/mock_reader.h" 15 #include "media/base/mock_reader.h"
14 #include "media/ffmpeg/ffmpeg_common.h" 16 #include "media/ffmpeg/ffmpeg_common.h"
15 #include "media/filters/ffmpeg_demuxer.h" 17 #include "media/filters/ffmpeg_demuxer.h"
18 #include "media/filters/file_data_source.h"
16 #include "testing/gtest/include/gtest/gtest.h" 19 #include "testing/gtest/include/gtest/gtest.h"
17 20
18 using ::testing::AnyNumber; 21 using ::testing::AnyNumber;
19 using ::testing::DoAll; 22 using ::testing::DoAll;
20 using ::testing::InSequence; 23 using ::testing::InSequence;
21 using ::testing::Invoke; 24 using ::testing::Invoke;
22 using ::testing::NotNull; 25 using ::testing::NotNull;
23 using ::testing::Return; 26 using ::testing::Return;
24 using ::testing::SetArgumentPointee; 27 using ::testing::SaveArg;
28 using ::testing::SetArgPointee;
25 using ::testing::StrictMock; 29 using ::testing::StrictMock;
26 using ::testing::WithArgs; 30 using ::testing::WithArgs;
27 using ::testing::_; 31 using ::testing::_;
28 32
29 namespace media { 33 namespace media {
30 34
31 // Fixture class to facilitate writing tests. Takes care of setting up the 35 // Fixture class to facilitate writing tests. Takes care of setting up the
32 // FFmpeg, pipeline and filter host mocks. 36 // FFmpeg, pipeline and filter host mocks.
33 class FFmpegDemuxerTest : public testing::Test { 37 class FFmpegDemuxerTest : public testing::Test {
34 protected: 38 protected:
35 // These constants refer to the stream ordering inside AVFormatContext. We
36 // simulate media with a data stream, audio stream and video stream. Having
37 // the data stream first forces the audio and video streams to get remapped
38 // from indices {1,2} to {0,1} respectively, which covers an important test
39 // case.
40 enum AVStreamIndex {
41 AV_STREAM_DATA,
42 AV_STREAM_VIDEO,
43 AV_STREAM_AUDIO,
44 AV_STREAM_MAX,
45 };
46
47 // These constants refer to the stream ordering inside an initialized
48 // FFmpegDemuxer based on the ordering of the AVStreamIndex constants.
49 enum DemuxerStreamIndex {
50 DS_STREAM_VIDEO,
51 DS_STREAM_AUDIO,
52 DS_STREAM_MAX,
53 };
54
55 static const int kDurations[];
56 static const int kChannels;
57 static const int kSampleRate;
58 static const int kWidth;
59 static const int kHeight;
60
61 static const size_t kDataSize;
62 static const uint8 kAudioData[];
63 static const uint8 kVideoData[];
64 static const uint8* kNullData;
65 39
66 FFmpegDemuxerTest() { 40 FFmpegDemuxerTest() {
41 EXPECT_TRUE(InitializeMediaLibraryForTesting());
42
67 // Create an FFmpegDemuxer. 43 // Create an FFmpegDemuxer.
68 demuxer_ = new FFmpegDemuxer(&message_loop_); 44 demuxer_ = new FFmpegDemuxer(&message_loop_);
69 demuxer_->disable_first_seek_hack_for_testing(); 45 demuxer_->disable_first_seek_hack_for_testing();
70 46
71 // Inject a filter host and message loop and prepare a data source. 47 // Inject a filter host and message loop and prepare a data source.
72 demuxer_->set_host(&host_); 48 demuxer_->set_host(&host_);
73 data_source_ = new StrictMock<MockDataSource>();
74 49
75 EXPECT_CALL(*data_source_, Stop(NotNull())) 50 EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber());
76 .WillRepeatedly(Invoke(&RunStopFilterCallback)); 51 EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber());
77 52 EXPECT_CALL(host_, SetCurrentReadPosition(_))
78 // Initialize FFmpeg fixtures. 53 .WillRepeatedly(SaveArg<0>(&current_read_position_));
79 memset(&format_context_, 0, sizeof(format_context_));
80 memset(&input_format_, 0, sizeof(input_format_));
81 memset(&streams_, 0, sizeof(streams_));
82 memset(&codecs_, 0, sizeof(codecs_));
83
84 // Initialize AVCodecContext structures.
85 codecs_[AV_STREAM_DATA].codec_type = AVMEDIA_TYPE_DATA;
86 codecs_[AV_STREAM_DATA].codec_id = CODEC_ID_NONE;
87
88 codecs_[AV_STREAM_VIDEO].codec_type = AVMEDIA_TYPE_VIDEO;
89 codecs_[AV_STREAM_VIDEO].codec_id = CODEC_ID_THEORA;
90 codecs_[AV_STREAM_VIDEO].width = kWidth;
91 codecs_[AV_STREAM_VIDEO].height = kHeight;
92
93 codecs_[AV_STREAM_AUDIO].codec_type = AVMEDIA_TYPE_AUDIO;
94 codecs_[AV_STREAM_AUDIO].codec_id = CODEC_ID_VORBIS;
95 codecs_[AV_STREAM_AUDIO].channels = kChannels;
96 codecs_[AV_STREAM_AUDIO].sample_rate = kSampleRate;
97
98 input_format_.name = "foo";
99 format_context_.iformat = &input_format_;
100
101 // Initialize AVStream and AVFormatContext structures. We set the time base
102 // of the streams such that duration is reported in microseconds.
103 format_context_.nb_streams = AV_STREAM_MAX;
104 format_context_.streams = new AVStream*[AV_STREAM_MAX];
105 for (size_t i = 0; i < AV_STREAM_MAX; ++i) {
106 format_context_.streams[i] = &streams_[i];
107 streams_[i].codec = &codecs_[i];
108 streams_[i].duration = kDurations[i];
109 streams_[i].time_base.den = 1 * base::Time::kMicrosecondsPerSecond;
110 streams_[i].time_base.num = 1;
111 }
112 } 54 }
113 55
114 virtual ~FFmpegDemuxerTest() { 56 virtual ~FFmpegDemuxerTest() {
115 // Call Stop() to shut down internal threads. 57 // Call Stop() to shut down internal threads.
116 demuxer_->Stop(NewExpectedCallback()); 58 demuxer_->Stop(NewExpectedCallback());
117 59
118 // Finish up any remaining tasks. 60 // Finish up any remaining tasks.
119 message_loop_.RunAllPending(); 61 message_loop_.RunAllPending();
120 // Release the reference to the demuxer. 62 // Release the reference to the demuxer.
121 demuxer_ = NULL; 63 demuxer_ = NULL;
122
123 if (format_context_.streams) {
124 delete[] format_context_.streams;
125 format_context_.streams = NULL;
126 format_context_.nb_streams = 0;
127 }
128 } 64 }
129 65
130 // Sets up MockFFmpeg to allow FFmpegDemuxer to successfully initialize. 66 scoped_refptr<DataSource> CreateDataSource(const std::string& name) {
131 void InitializeDemuxerMocks() { 67 FilePath file_path;
132 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL)) 68 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
scherkus (not reviewing) 2011/08/11 01:26:29 can we use the ReadTestData functions here?
acolwell GONE FROM CHROMIUM 2011/08/11 23:54:40 No because we don't have an in-memory DataSource i
133 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0))); 69
134 EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_)) 70 file_path = file_path.Append(FILE_PATH_LITERAL("media"))
135 .WillOnce(Return(0)); 71 .Append(FILE_PATH_LITERAL("test"))
136 EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_)); 72 .Append(FILE_PATH_LITERAL("data"))
73 .AppendASCII(name);
74
75 scoped_refptr<FileDataSource> data_source = new FileDataSource();
76
77 EXPECT_EQ(PIPELINE_OK, data_source->Initialize(file_path.MaybeAsASCII()));
78
79 return data_source.get();
137 } 80 }
138 81
139 // Initializes both MockFFmpeg and FFmpegDemuxer. 82 MOCK_METHOD1(CheckPoint, void(int v));
140 void InitializeDemuxer() {
141 InitializeDemuxerMocks();
142 83
143 // Since we ignore data streams, the duration should be equal to the longest 84 // Initializes FFmpegDemuxer.
144 // supported stream's duration (audio, in this case). 85 void InitializeDemuxer(const scoped_refptr<DataSource>& data_source) {
145 base::TimeDelta expected_duration = 86 EXPECT_CALL(host_, SetDuration(_));
146 base::TimeDelta::FromMicroseconds(kDurations[AV_STREAM_AUDIO]); 87 demuxer_->Initialize(data_source, NewExpectedStatusCB(PIPELINE_OK));
147 EXPECT_CALL(host_, SetDuration(expected_duration)); 88 message_loop_.RunAllPending();
89 }
148 90
149 demuxer_->Initialize(data_source_.get(), 91 void ValidateBuffer(const tracked_objects::Location& location,
scherkus (not reviewing) 2011/08/11 01:26:29 docs? what does this do exactly?
acolwell GONE FROM CHROMIUM 2011/08/11 23:54:40 Done. It just makes sure the buffer has the expect
150 NewExpectedStatusCB(PIPELINE_OK)); 92 const scoped_refptr<Buffer>& buffer,
151 message_loop_.RunAllPending(); 93 size_t size, int64 timestampInMicroseconds) {
94 std::string location_str;
95 location.Write(true, false, &location_str);
96 location_str += "\n";
97 SCOPED_TRACE(location_str);
98 EXPECT_TRUE(buffer.get() != NULL);
99 EXPECT_EQ(size, buffer->GetDataSize());
100 EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds),
101 buffer->GetTimestamp());
152 } 102 }
153 103
154 // Fixture members. 104 // Fixture members.
155 scoped_refptr<FFmpegDemuxer> demuxer_; 105 scoped_refptr<FFmpegDemuxer> demuxer_;
156 scoped_refptr<StrictMock<MockDataSource> > data_source_;
157 StrictMock<MockFilterHost> host_; 106 StrictMock<MockFilterHost> host_;
158 MessageLoop message_loop_; 107 MessageLoop message_loop_;
159 108
160 // FFmpeg fixtures. 109 int64 current_read_position_;
161 AVFormatContext format_context_;
162 AVInputFormat input_format_;
163 AVCodecContext codecs_[AV_STREAM_MAX];
164 AVStream streams_[AV_STREAM_MAX];
165 MockFFmpeg mock_ffmpeg_;
166 110
167 private: 111 private:
168 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); 112 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
169 }; 113 };
170 114
171 // These durations are picked so that the demuxer chooses the longest supported
172 // stream, which would be 30 in this case for the audio stream.
173 const int FFmpegDemuxerTest::kDurations[AV_STREAM_MAX] = {100, 20, 30};
174 const int FFmpegDemuxerTest::kChannels = 2;
175 const int FFmpegDemuxerTest::kSampleRate = 44100;
176 const int FFmpegDemuxerTest::kWidth = 1280;
177 const int FFmpegDemuxerTest::kHeight = 720;
178
179 const size_t FFmpegDemuxerTest::kDataSize = 4;
180 const uint8 FFmpegDemuxerTest::kAudioData[kDataSize] = {0, 1, 2, 3};
181 const uint8 FFmpegDemuxerTest::kVideoData[kDataSize] = {4, 5, 6, 7};
182 const uint8* FFmpegDemuxerTest::kNullData = NULL;
183
184 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { 115 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
185 // Simulate av_open_input_file() failing. 116 // Simulate av_open_input_file() failing.
186 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL)) 117 EXPECT_CALL(host_, SetCurrentReadPosition(_));
187 .WillOnce(Return(-1)); 118 demuxer_->Initialize(CreateDataSource("ten_byte_file"),
119 NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
188 120
189 demuxer_->Initialize(data_source_.get(),
190 NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
191 message_loop_.RunAllPending(); 121 message_loop_.RunAllPending();
192 } 122 }
193 123
194 TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) { 124 // TODO(acolwell): Uncomment this test when we discover a file that passes
195 // Simulate av_find_stream_info() failing. 125 // av_open_input_file(), but has av_find_stream_info() fail.
196 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL)) 126 //
197 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0))); 127 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
198 EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_)) 128 // demuxer_->Initialize(
199 .WillOnce(Return(AVERROR(EIO))); 129 // CreateDataSource("find_stream_info_fail.webm"),
200 EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_)); 130 // NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
201 131 // message_loop_.RunAllPending();
202 demuxer_->Initialize( 132 //}
203 data_source_.get(),
204 NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
205 message_loop_.RunAllPending();
206 }
207 133
208 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { 134 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
209 // Simulate media with no parseable streams. 135 // Open a file with no parseable streams.
210 { 136 EXPECT_CALL(host_, SetCurrentReadPosition(_));
211 SCOPED_TRACE("");
212 InitializeDemuxerMocks();
213 }
214 format_context_.nb_streams = 0;
215
216 demuxer_->Initialize( 137 demuxer_->Initialize(
217 data_source_.get(), 138 CreateDataSource("no_streams.webm"),
218 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); 139 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
219 message_loop_.RunAllPending(); 140 message_loop_.RunAllPending();
220 } 141 }
221 142
222 TEST_F(FFmpegDemuxerTest, Initialize_DataStreamOnly) { 143 // TODO(acolwell): Find a subtitle only file so we can uncomment this test.
223 // Simulate media with a data stream but no audio or video streams. 144 //
224 { 145 //TEST_F(FFmpegDemuxerTest, Initialize_DataStreamOnly) {
225 SCOPED_TRACE(""); 146 // demuxer_->Initialize(
226 InitializeDemuxerMocks(); 147 // CreateDataSource("subtitles_only.mp4"),,
227 } 148 // NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
228 EXPECT_EQ(format_context_.streams[0], &streams_[AV_STREAM_DATA]); 149 // message_loop_.RunAllPending();
229 format_context_.nb_streams = 1; 150 //}
230
231 demuxer_->Initialize(
232 data_source_.get(),
233 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
234 message_loop_.RunAllPending();
235 }
236 151
237 TEST_F(FFmpegDemuxerTest, Initialize_Successful) { 152 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
238 { 153 InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
239 SCOPED_TRACE("");
240 InitializeDemuxer();
241 }
242 154
243 // First stream should be video and support the FFmpegDemuxerStream interface. 155 // First stream should be video and support the FFmpegDemuxerStream interface.
244 scoped_refptr<DemuxerStream> stream = 156 scoped_refptr<DemuxerStream> stream =
245 demuxer_->GetStream(DemuxerStream::VIDEO); 157 demuxer_->GetStream(DemuxerStream::VIDEO);
246 ASSERT_TRUE(stream); 158 ASSERT_TRUE(stream);
247 EXPECT_EQ(DemuxerStream::VIDEO, stream->type()); 159 EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
248 EXPECT_EQ(&streams_[AV_STREAM_VIDEO], stream->GetAVStream()); 160 ASSERT_TRUE(stream->GetAVStream());
249 161
250 // Other stream should be audio and support the FFmpegDemuxerStream interface. 162 // Other stream should be audio and support the FFmpegDemuxerStream interface.
251 stream = demuxer_->GetStream(DemuxerStream::AUDIO); 163 stream = demuxer_->GetStream(DemuxerStream::AUDIO);
252 ASSERT_TRUE(stream); 164 ASSERT_TRUE(stream);
253 EXPECT_EQ(DemuxerStream::AUDIO, stream->type()); 165 EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
254 EXPECT_EQ(&streams_[AV_STREAM_AUDIO], stream->GetAVStream()); 166 ASSERT_TRUE(stream->GetAVStream());
255 } 167 }
256 168
257 TEST_F(FFmpegDemuxerTest, Read_DiscardUninteresting) { 169 TEST_F(FFmpegDemuxerTest, Read_Audio) {
258 // We test that on a successful audio packet read, that the packet is 170 // We test that on a successful audio packet read.
259 // duplicated (FFmpeg memory management safety), and a copy of it ends up in 171 InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
260 // the DemuxerStream.
261 {
262 SCOPED_TRACE("");
263 InitializeDemuxer();
264 }
265
266 // Ignore all AVFreePacket() calls. We check this elsewhere.
267 EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
268
269 // The demuxer will read a data packet which will get immediately freed,
270 // followed by a read error to end the reading.
271 InSequence s;
272 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
273 .WillOnce(CreatePacketNoCount(AV_STREAM_DATA, kNullData, 0));
274 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
275 .WillOnce(Return(AVERROR(EIO)));
276 172
277 // Attempt a read from the audio stream and run the message loop until done. 173 // Attempt a read from the audio stream and run the message loop until done.
278 scoped_refptr<DemuxerStream> audio = 174 scoped_refptr<DemuxerStream> audio =
279 demuxer_->GetStream(DemuxerStream::AUDIO); 175 demuxer_->GetStream(DemuxerStream::AUDIO);
280 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 176 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
281 reader->Read(audio); 177 reader->Read(audio);
282 message_loop_.RunAllPending(); 178 message_loop_.RunAllPending();
179 EXPECT_TRUE(reader->called());
180 ValidateBuffer(FROM_HERE, reader->buffer(), 29, 0);
283 181
284 EXPECT_TRUE(reader->called()); 182 reader->Reset();
285 ASSERT_TRUE(reader->buffer());
286 EXPECT_TRUE(reader->buffer()->IsEndOfStream());
287 }
288
289 TEST_F(FFmpegDemuxerTest, Read_Audio) {
290 // We test that on a successful audio packet read, that the packet is
291 // duplicated (FFmpeg memory management safety), and a copy of it ends up in
292 // the DemuxerStream.
293 {
294 SCOPED_TRACE("");
295 InitializeDemuxer();
296 }
297
298 // Ignore all AVFreePacket() calls. We check this via valgrind.
299 EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
300
301 // The demuxer will read a data packet which will get immediately freed,
302 // followed by reading an audio packet...
303 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
304 .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
305 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
306 .WillOnce(Return(0));
307
308 // Attempt a read from the audio stream and run the message loop until done.
309 scoped_refptr<DemuxerStream> audio =
310 demuxer_->GetStream(DemuxerStream::AUDIO);
311 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
312 reader->Read(audio); 183 reader->Read(audio);
313 message_loop_.RunAllPending(); 184 message_loop_.RunAllPending();
314
315 EXPECT_TRUE(reader->called()); 185 EXPECT_TRUE(reader->called());
316 ASSERT_TRUE(reader->buffer()); 186 ValidateBuffer(FROM_HERE, reader->buffer(), 27, 3000);
317 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
318 EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
319 reader->buffer()->GetDataSize()));
320 } 187 }
321 188
322 TEST_F(FFmpegDemuxerTest, Read_Video) { 189 TEST_F(FFmpegDemuxerTest, Read_Video) {
323 // We test that on a successful video packet read, that the packet is 190 // We test that on a successful video packet read.
324 // duplicated (FFmpeg memory management safety), and a copy of it ends up in 191 InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
325 // the DemuxerStream.
326 {
327 SCOPED_TRACE("");
328 InitializeDemuxer();
329 }
330
331 // Ignore all AVFreePacket() calls. We check this via valgrind.
332 EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
333
334 // Simulate a successful frame read.
335 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
336 .WillOnce(CreatePacketNoCount(AV_STREAM_VIDEO, kVideoData, kDataSize));
337 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
338 .WillOnce(Return(0));
339 192
340 // Attempt a read from the video stream and run the message loop until done. 193 // Attempt a read from the video stream and run the message loop until done.
341 scoped_refptr<DemuxerStream> video = 194 scoped_refptr<DemuxerStream> video =
342 demuxer_->GetStream(DemuxerStream::VIDEO); 195 demuxer_->GetStream(DemuxerStream::VIDEO);
343 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 196 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
197
344 reader->Read(video); 198 reader->Read(video);
345 message_loop_.RunAllPending(); 199 message_loop_.RunAllPending();
200 EXPECT_TRUE(reader->called());
201 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
346 202
203 reader->Reset();
204 reader->Read(video);
205 message_loop_.RunAllPending();
347 EXPECT_TRUE(reader->called()); 206 EXPECT_TRUE(reader->called());
348 ASSERT_TRUE(reader->buffer()); 207 ValidateBuffer(FROM_HERE, reader->buffer(), 1057, 33000);
349 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
350 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
351 reader->buffer()->GetDataSize()));
352 } 208 }
353 209
354 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) { 210 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) {
355 // Test the start time is the first timestamp of the video and audio stream. 211 // Test the start time is the first timestamp of the video and audio stream.
356 const int64 kStartTime = 60000; 212 InitializeDemuxer(CreateDataSource("nonzero-start-time.webm"));
357 // Set the audio and video stream's first timestamp.
358 streams_[AV_STREAM_AUDIO].first_dts = kStartTime;
359 streams_[AV_STREAM_VIDEO].first_dts = kStartTime;
360 {
361 SCOPED_TRACE("");
362 InitializeDemuxer();
363 }
364
365 // Ignore all AVFreePacket() calls. We check this via valgrind.
366 EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
367 213
368 const base::TimeDelta kExpectedTimestamp = 214 const base::TimeDelta kExpectedTimestamp =
369 base::TimeDelta::FromMicroseconds(kStartTime); 215 base::TimeDelta::FromMicroseconds(396000);
370
371 // Simulate a successful frame read.
372 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
373 .WillOnce(CreatePacketTimeNoCount(AV_STREAM_VIDEO,
374 kVideoData,
375 kDataSize,
376 kStartTime));
377 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
378 .WillOnce(Return(0));
379
380 // Attempt a read from the video stream and run the message loop until done.
381 scoped_refptr<DemuxerStream> video =
382 demuxer_->GetStream(DemuxerStream::VIDEO);
383 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
384 reader->Read(video);
385 message_loop_.RunAllPending();
386
387 EXPECT_TRUE(reader->called());
388 ASSERT_TRUE(reader->buffer());
389 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
390 EXPECT_EQ(kExpectedTimestamp, reader->buffer()->GetTimestamp());
391 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
392 reader->buffer()->GetDataSize()));
393
394 EXPECT_EQ(kExpectedTimestamp, demuxer_->GetStartTime());
395 }
396
397 TEST_F(FFmpegDemuxerTest, CheckMinStartTime) {
398 // Test the start time is minimum timestamp of all streams.
399 const int64 kAudioStartTime = 5000000;
400 const int64 kVideoStartTime = 5033000;
401 // Set the audio and video stream's first timestamp.
402 streams_[AV_STREAM_AUDIO].first_dts = kAudioStartTime;
403 streams_[AV_STREAM_VIDEO].first_dts = kVideoStartTime;
404 {
405 SCOPED_TRACE("");
406 InitializeDemuxer();
407 }
408
409 // Ignore all AVFreePacket() calls. We check this via valgrind.
410 EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
411
412 // Expect all calls in sequence.
413 InSequence s;
414
415 const base::TimeDelta kExpectedAudioTimestamp =
416 base::TimeDelta::FromMicroseconds(kAudioStartTime);
417 const base::TimeDelta kExpectedVideoTimestamp =
418 base::TimeDelta::FromMicroseconds(kVideoStartTime);
419
420 // First read a video packet, then an audio packet.
421 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
422 .WillOnce(CreatePacketTimeNoCount(AV_STREAM_AUDIO,
423 kAudioData,
424 kDataSize,
425 kAudioStartTime));
426 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
427 .WillOnce(Return(0));
428 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
429 .WillOnce(CreatePacketTimeNoCount(AV_STREAM_VIDEO,
430 kVideoData,
431 kDataSize,
432 kVideoStartTime));
433 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
434 .WillOnce(Return(0));
435 216
436 // Attempt a read from the video stream and run the message loop until done. 217 // Attempt a read from the video stream and run the message loop until done.
437 scoped_refptr<DemuxerStream> video = 218 scoped_refptr<DemuxerStream> video =
438 demuxer_->GetStream(DemuxerStream::VIDEO); 219 demuxer_->GetStream(DemuxerStream::VIDEO);
439 scoped_refptr<DemuxerStream> audio = 220 scoped_refptr<DemuxerStream> audio =
440 demuxer_->GetStream(DemuxerStream::AUDIO); 221 demuxer_->GetStream(DemuxerStream::AUDIO);
441 ASSERT_TRUE(video); 222 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
442 ASSERT_TRUE(audio);
443 223
444 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 224 // Check first buffer in video stream.
445 reader->Read(video); 225 reader->Read(video);
446 message_loop_.RunAllPending(); 226 message_loop_.RunAllPending();
227 EXPECT_TRUE(reader->called());
228 ValidateBuffer(FROM_HERE, reader->buffer(), 5636, 400000);
229 const base::TimeDelta video_timestamp = reader->buffer()->GetTimestamp();
447 230
448 EXPECT_TRUE(reader->called()); 231 // Check first buffer in audio stream.
449 ASSERT_TRUE(reader->buffer());
450 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
451 EXPECT_EQ(kExpectedVideoTimestamp, reader->buffer()->GetTimestamp());
452 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
453 reader->buffer()->GetDataSize()));
454
455 EXPECT_EQ(kExpectedAudioTimestamp, demuxer_->GetStartTime());
456
457 reader->Reset(); 232 reader->Reset();
458 reader->Read(audio); 233 reader->Read(audio);
459 message_loop_.RunAllPending(); 234 message_loop_.RunAllPending();
460 EXPECT_TRUE(reader->called()); 235 EXPECT_TRUE(reader->called());
461 ASSERT_TRUE(reader->buffer()); 236 ValidateBuffer(FROM_HERE, reader->buffer(), 165, 396000);
462 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize()); 237 const base::TimeDelta audio_timestamp = reader->buffer()->GetTimestamp();
463 EXPECT_EQ(kExpectedAudioTimestamp, reader->buffer()->GetTimestamp());
464 EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
465 reader->buffer()->GetDataSize()));
466 238
467 EXPECT_EQ(kExpectedAudioTimestamp, demuxer_->GetStartTime()); 239 // Verify that the start time is equal to the lowest timestamp.
240 EXPECT_EQ(std::min(audio_timestamp, video_timestamp),
241 demuxer_->GetStartTime());
468 } 242 }
469 243
470 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { 244 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
471 // On end of stream, a new, empty, AVPackets are created without any data for 245 // Verify that end of stream buffers are created.
472 // each stream and enqueued into the Buffer stream. Verify that these are 246 InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
473 // indeed inserted.
474 {
475 SCOPED_TRACE("");
476 InitializeDemuxer();
477 }
478
479 // Ignore all AVFreePacket() calls. We check this via valgrind.
480 EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
481
482 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
483 .WillOnce(Return(AVERROR(EIO)));
484 247
485 // We should now expect an end of stream buffer. 248 // We should now expect an end of stream buffer.
486 scoped_refptr<DemuxerStream> audio = 249 scoped_refptr<DemuxerStream> audio =
487 demuxer_->GetStream(DemuxerStream::AUDIO); 250 demuxer_->GetStream(DemuxerStream::AUDIO);
488 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 251 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
489 reader->Read(audio); 252
490 message_loop_.RunAllPending(); 253 bool got_eos_buffer = false;
491 EXPECT_TRUE(reader->called()); 254 const int kMaxBuffers = 170;
492 ASSERT_TRUE(reader->buffer()); 255 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
493 EXPECT_TRUE(reader->buffer()->IsEndOfStream()); 256 reader->Read(audio);
494 EXPECT_TRUE(reader->buffer()->GetData() == NULL); 257 message_loop_.RunAllPending();
495 EXPECT_EQ(0u, reader->buffer()->GetDataSize()); 258 EXPECT_TRUE(reader->called());
259 ASSERT_TRUE(reader->buffer());
260
261 if (reader->buffer()->IsEndOfStream()) {
262 got_eos_buffer = true;
263 EXPECT_TRUE(reader->buffer()->GetData() == NULL);
264 EXPECT_EQ(0u, reader->buffer()->GetDataSize());
265 break;
266 }
267
268 EXPECT_TRUE(reader->buffer()->GetData() != NULL);
269 EXPECT_GT(reader->buffer()->GetDataSize(), 0u);
270 reader->Reset();
271 }
272
273 EXPECT_TRUE(got_eos_buffer);
496 } 274 }
497 275
498 TEST_F(FFmpegDemuxerTest, Seek) { 276 TEST_F(FFmpegDemuxerTest, Seek) {
499 // We're testing that the demuxer frees all queued packets when it receives 277 // We're testing that the demuxer frees all queued packets when it receives
500 // a Seek(). 278 // a Seek().
501 // 279 InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
502 // Since we can't test which packets are being freed, we use check points to
503 // infer that the correct packets have been freed.
504 {
505 SCOPED_TRACE("");
506 InitializeDemuxer();
507 }
508 280
509 // Get our streams. 281 // Get our streams.
510 scoped_refptr<DemuxerStream> video = 282 scoped_refptr<DemuxerStream> video =
511 demuxer_->GetStream(DemuxerStream::VIDEO); 283 demuxer_->GetStream(DemuxerStream::VIDEO);
512 scoped_refptr<DemuxerStream> audio = 284 scoped_refptr<DemuxerStream> audio =
513 demuxer_->GetStream(DemuxerStream::AUDIO); 285 demuxer_->GetStream(DemuxerStream::AUDIO);
514 ASSERT_TRUE(video); 286 ASSERT_TRUE(video);
515 ASSERT_TRUE(audio); 287 ASSERT_TRUE(audio);
516 288
517 // Expected values.
518 const int64 kExpectedTimestamp = 1234;
519 const int64 kExpectedFlags = AVSEEK_FLAG_BACKWARD;
520
521 // Ignore all AVFreePacket() calls. We check this via valgrind.
522 EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
523
524 // Expect all calls in sequence.
525 InSequence s;
526
527 // First we'll read a video packet that causes two audio packets to be queued
528 // inside FFmpegDemuxer...
529 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
530 .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
531 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
532 .WillOnce(Return(0));
533 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
534 .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
535 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
536 .WillOnce(Return(0));
537 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
538 .WillOnce(CreatePacketNoCount(AV_STREAM_VIDEO, kVideoData, kDataSize));
539 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
540 .WillOnce(Return(0));
541
542 EXPECT_CALL(mock_ffmpeg_, CheckPoint(1));
543
544 // ...then we'll expect a seek call...
545 EXPECT_CALL(mock_ffmpeg_,
546 AVSeekFrame(&format_context_, -1, kExpectedTimestamp, kExpectedFlags))
547 .WillOnce(Return(0));
548
549 // ...then our callback will be executed...
550 FilterStatusCB seek_cb = NewExpectedStatusCB(PIPELINE_OK);
551 EXPECT_CALL(mock_ffmpeg_, CheckPoint(2));
552
553 // ...followed by two audio packet reads we'll trigger...
554 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
555 .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
556 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
557 .WillOnce(Return(0));
558 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
559 .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
560 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
561 .WillOnce(Return(0));
562
563 // ...followed by two video packet reads...
564 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
565 .WillOnce(CreatePacketNoCount(AV_STREAM_VIDEO, kVideoData, kDataSize));
566 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
567 .WillOnce(Return(0));
568 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
569 .WillOnce(CreatePacketNoCount(AV_STREAM_VIDEO, kVideoData, kDataSize));
570 EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
571 .WillOnce(Return(0));
572
573 // ...and finally a sanity checkpoint to make sure everything was released.
574 EXPECT_CALL(mock_ffmpeg_, CheckPoint(3));
575
576 // Read a video packet and release it. 289 // Read a video packet and release it.
577 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 290 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
578 reader->Read(video); 291 reader->Read(video);
579 message_loop_.RunAllPending(); 292 message_loop_.RunAllPending();
580 EXPECT_TRUE(reader->called()); 293 EXPECT_TRUE(reader->called());
581 ASSERT_TRUE(reader->buffer()); 294 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
582 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
583 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
584 reader->buffer()->GetDataSize()));
585 295
586 // Release the video packet and verify the other packets are still queued. 296 // Release the video packet and verify the other packets are still queued.
587 reader->Reset(); 297 reader->Reset();
588 message_loop_.RunAllPending(); 298 message_loop_.RunAllPending();
589 mock_ffmpeg_.CheckPoint(1);
590 299
591 // Issue a simple forward seek, which should discard queued packets. 300 // Issue a simple forward seek, which should discard queued packets.
592 demuxer_->Seek(base::TimeDelta::FromMicroseconds(kExpectedTimestamp), 301 demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
593 seek_cb); 302 NewExpectedStatusCB(PIPELINE_OK));
594 message_loop_.RunAllPending(); 303 message_loop_.RunAllPending();
595 mock_ffmpeg_.CheckPoint(2);
596 304
597 // Audio read #1. 305 // Audio read #1.
598 reader->Read(audio); 306 reader->Read(audio);
599 message_loop_.RunAllPending(); 307 message_loop_.RunAllPending();
600 EXPECT_TRUE(reader->called()); 308 EXPECT_TRUE(reader->called());
601 ASSERT_TRUE(reader->buffer()); 309 ValidateBuffer(FROM_HERE, reader->buffer(), 145, 803000);
602 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
603 EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
604 reader->buffer()->GetDataSize()));
605 310
606 // Audio read #2. 311 // Audio read #2.
607 reader->Reset(); 312 reader->Reset();
608 reader->Read(audio); 313 reader->Read(audio);
609 message_loop_.RunAllPending(); 314 message_loop_.RunAllPending();
610 EXPECT_TRUE(reader->called()); 315 EXPECT_TRUE(reader->called());
611 ASSERT_TRUE(reader->buffer()); 316 ValidateBuffer(FROM_HERE, reader->buffer(), 148, 826000);
612 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
613 EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
614 reader->buffer()->GetDataSize()));
615 317
616 // Video read #1. 318 // Video read #1.
617 reader->Reset(); 319 reader->Reset();
618 reader->Read(video); 320 reader->Read(video);
619 message_loop_.RunAllPending(); 321 message_loop_.RunAllPending();
620 EXPECT_TRUE(reader->called()); 322 EXPECT_TRUE(reader->called());
621 ASSERT_TRUE(reader->buffer()); 323 ValidateBuffer(FROM_HERE, reader->buffer(), 5425, 801000);
622 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
623 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
624 reader->buffer()->GetDataSize()));
625 324
626 // Video read #2. 325 // Video read #2.
627 reader->Reset(); 326 reader->Reset();
628 reader->Read(video); 327 reader->Read(video);
629 message_loop_.RunAllPending(); 328 message_loop_.RunAllPending();
630 EXPECT_TRUE(reader->called()); 329 EXPECT_TRUE(reader->called());
631 ASSERT_TRUE(reader->buffer()); 330 ValidateBuffer(FROM_HERE, reader->buffer(), 1906, 834000);
632 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
633 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
634 reader->buffer()->GetDataSize()));
635 331
636 // Manually release the last reference to the buffer and verify it was freed. 332 // Manually release the last reference to the buffer and verify it was freed.
637 reader->Reset(); 333 reader->Reset();
638 message_loop_.RunAllPending(); 334 message_loop_.RunAllPending();
639 mock_ffmpeg_.CheckPoint(3);
640 } 335 }
641 336
642 // A mocked callback specialization for calling Read(). Since RunWithParams() 337 // A mocked callback specialization for calling Read(). Since RunWithParams()
643 // is mocked we don't need to pass in object or method pointers. 338 // is mocked we don't need to pass in object or method pointers.
644 class MockReadCallback : public base::RefCountedThreadSafe<MockReadCallback> { 339 class MockReadCallback : public base::RefCountedThreadSafe<MockReadCallback> {
645 public: 340 public:
646 MockReadCallback() {} 341 MockReadCallback() {}
647 342
648 virtual ~MockReadCallback() { 343 virtual ~MockReadCallback() {
649 OnDelete(); 344 OnDelete();
650 } 345 }
651 346
652 MOCK_METHOD0(OnDelete, void()); 347 MOCK_METHOD0(OnDelete, void());
653 MOCK_METHOD1(Run, void(Buffer* buffer)); 348 MOCK_METHOD1(Run, void(Buffer* buffer));
654 349
655 private: 350 private:
656 DISALLOW_COPY_AND_ASSIGN(MockReadCallback); 351 DISALLOW_COPY_AND_ASSIGN(MockReadCallback);
657 }; 352 };
658 353
659 TEST_F(FFmpegDemuxerTest, Stop) { 354 TEST_F(FFmpegDemuxerTest, Stop) {
660 // Tests that calling Read() on a stopped demuxer immediately deletes the 355 // Tests that calling Read() on a stopped demuxer immediately deletes the
661 // callback. 356 // callback.
662 { 357 InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
663 SCOPED_TRACE("");
664 InitializeDemuxer();
665 }
666 358
667 // Get our stream. 359 // Get our stream.
668 scoped_refptr<DemuxerStream> audio = 360 scoped_refptr<DemuxerStream> audio =
669 demuxer_->GetStream(DemuxerStream::AUDIO); 361 demuxer_->GetStream(DemuxerStream::AUDIO);
670 ASSERT_TRUE(audio); 362 ASSERT_TRUE(audio);
671 363
672 // Stop the demuxer, overriding the default expectation to assert that
673 // data_source_ really is Stop()'d.
674 EXPECT_CALL(*data_source_, Stop(_))
675 .WillOnce(Invoke(&RunStopFilterCallback))
676 .RetiresOnSaturation();
677 demuxer_->Stop(NewExpectedCallback()); 364 demuxer_->Stop(NewExpectedCallback());
678 365
679 // Expect all calls in sequence. 366 // Expect all calls in sequence.
680 InSequence s; 367 InSequence s;
681 368
682 // Create our mocked callback. The Callback created by base::Bind() will take 369 // Create our mocked callback. The Callback created by base::Bind() will take
683 // ownership of this pointer. 370 // ownership of this pointer.
684 StrictMock<MockReadCallback>* callback = new StrictMock<MockReadCallback>(); 371 StrictMock<MockReadCallback>* callback = new StrictMock<MockReadCallback>();
685 372
686 // The callback should be immediately deleted. We'll use a checkpoint to 373 // The callback should be immediately deleted. We'll use a checkpoint to
687 // verify that it has indeed been deleted. 374 // verify that it has indeed been deleted.
688 EXPECT_CALL(*callback, OnDelete()); 375 EXPECT_CALL(*callback, OnDelete());
689 EXPECT_CALL(mock_ffmpeg_, CheckPoint(1)); 376 EXPECT_CALL(*this, CheckPoint(1));
690 377
691 // Attempt the read... 378 // Attempt the read...
692 audio->Read(base::Bind(&MockReadCallback::Run, callback)); 379 audio->Read(base::Bind(&MockReadCallback::Run, callback));
693 380
694 message_loop_.RunAllPending(); 381 message_loop_.RunAllPending();
695 382
696 // ...and verify that |callback| was deleted. 383 // ...and verify that |callback| was deleted.
697 mock_ffmpeg_.CheckPoint(1); 384 CheckPoint(1);
698 } 385 }
699 386
700 TEST_F(FFmpegDemuxerTest, DisableAudioStream) { 387 TEST_F(FFmpegDemuxerTest, DisableAudioStream) {
701 // We are doing the following things here: 388 // We are doing the following things here:
702 // 1. Initialize the demuxer with audio and video stream. 389 // 1. Initialize the demuxer with audio and video stream.
703 // 2. Send a "disable audio stream" message to the demuxer. 390 // 2. Send a "disable audio stream" message to the demuxer.
704 // 3. Demuxer will free audio packets even if audio stream was initialized. 391 // 3. Demuxer will free audio packets even if audio stream was initialized.
705 { 392 InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
706 SCOPED_TRACE("");
707 InitializeDemuxer();
708 }
709 393
710 // Submit a "disable audio stream" message to the demuxer. 394 // Submit a "disable audio stream" message to the demuxer.
711 demuxer_->OnAudioRendererDisabled(); 395 demuxer_->OnAudioRendererDisabled();
712 message_loop_.RunAllPending(); 396 message_loop_.RunAllPending();
713 397
714 // Ignore all AVFreePacket() calls. We check this via valgrind.
715 EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
716
717 // Expect all calls in sequence.
718 InSequence s;
719
720 // The demuxer will read an audio packet which will get immediately freed.
721 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
722 .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kNullData, 0));
723
724 // Then an end-of-stream packet is read.
725 EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
726 .WillOnce(Return(AVERROR(EIO)));
727
728 // Get our streams. 398 // Get our streams.
729 scoped_refptr<DemuxerStream> video = 399 scoped_refptr<DemuxerStream> video =
730 demuxer_->GetStream(DemuxerStream::VIDEO); 400 demuxer_->GetStream(DemuxerStream::VIDEO);
401 scoped_refptr<DemuxerStream> audio =
402 demuxer_->GetStream(DemuxerStream::AUDIO);
731 ASSERT_TRUE(video); 403 ASSERT_TRUE(video);
404 ASSERT_TRUE(audio);
732 405
733 // Attempt a read from the video stream and run the message loop until done. 406 // Attempt a read from the video stream and run the message loop until done.
734 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 407 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
735 reader->Read(video); 408 reader->Read(video);
736 message_loop_.RunAllPending(); 409 message_loop_.RunAllPending();
410 EXPECT_TRUE(reader->called());
411 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
412
413 reader->Reset();
414 reader->Read(audio);
415 message_loop_.RunAllPending();
416 EXPECT_TRUE(reader->called());
417 EXPECT_TRUE(reader->buffer()->IsEndOfStream());
737 } 418 }
738 419
739 class MockFFmpegDemuxer : public FFmpegDemuxer { 420 class MockFFmpegDemuxer : public FFmpegDemuxer {
740 public: 421 public:
741 explicit MockFFmpegDemuxer(MessageLoop* message_loop) 422 explicit MockFFmpegDemuxer(MessageLoop* message_loop)
742 : FFmpegDemuxer(message_loop) { 423 : FFmpegDemuxer(message_loop) {
743 } 424 }
744 virtual ~MockFFmpegDemuxer() {} 425 virtual ~MockFFmpegDemuxer() {}
745 426
746 MOCK_METHOD0(WaitForRead, size_t()); 427 MOCK_METHOD0(WaitForRead, size_t());
747 MOCK_METHOD1(SignalReadCompleted, void(size_t size)); 428 MOCK_METHOD1(SignalReadCompleted, void(size_t size));
748 429
749 private: 430 private:
750 DISALLOW_COPY_AND_ASSIGN(MockFFmpegDemuxer); 431 DISALLOW_COPY_AND_ASSIGN(MockFFmpegDemuxer);
751 }; 432 };
752 433
753 // A gmock helper method to execute the callback and deletes it. 434 // A gmock helper method to execute the callback and deletes it.
754 void RunCallback(size_t size, DataSource::ReadCallback* callback) { 435 void RunCallback(size_t size, DataSource::ReadCallback* callback) {
755 DCHECK(callback); 436 DCHECK(callback);
756 callback->RunWithParams(Tuple1<size_t>(size)); 437 callback->RunWithParams(Tuple1<size_t>(size));
757 delete callback; 438 delete callback;
758 } 439 }
759 440
760 TEST_F(FFmpegDemuxerTest, ProtocolRead) { 441 TEST_F(FFmpegDemuxerTest, ProtocolRead) {
442 scoped_refptr<StrictMock<MockDataSource> > data_source =
443 new StrictMock<MockDataSource>();
444
445 EXPECT_CALL(*data_source, Stop(NotNull()))
446 .WillRepeatedly(Invoke(&RunStopFilterCallback));
447
761 // Creates a demuxer. 448 // Creates a demuxer.
762 scoped_refptr<MockFFmpegDemuxer> demuxer( 449 scoped_refptr<MockFFmpegDemuxer> demuxer(
763 new MockFFmpegDemuxer(&message_loop_)); 450 new MockFFmpegDemuxer(&message_loop_));
764 ASSERT_TRUE(demuxer); 451 ASSERT_TRUE(demuxer);
765 demuxer->set_host(&host_); 452 demuxer->set_host(&host_);
766 demuxer->data_source_ = data_source_; 453 demuxer->data_source_ = data_source;
767 454
768 uint8 kBuffer[1]; 455 uint8 kBuffer[1];
769 InSequence s; 456 InSequence s;
770 // Actions taken in the first read. 457 // Actions taken in the first read.
771 EXPECT_CALL(*data_source_, GetSize(_)) 458 EXPECT_CALL(*data_source, GetSize(_))
772 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true))); 459 .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true)));
773 EXPECT_CALL(*data_source_, Read(0, 512, kBuffer, NotNull())) 460 EXPECT_CALL(*data_source, Read(0, 512, kBuffer, NotNull()))
774 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback))); 461 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback)));
775 EXPECT_CALL(*demuxer, SignalReadCompleted(512)); 462 EXPECT_CALL(*demuxer, SignalReadCompleted(512));
776 EXPECT_CALL(*demuxer, WaitForRead()) 463 EXPECT_CALL(*demuxer, WaitForRead())
777 .WillOnce(Return(512)); 464 .WillOnce(Return(512));
778 EXPECT_CALL(host_, SetCurrentReadPosition(512)); 465 EXPECT_CALL(host_, SetCurrentReadPosition(512));
779 466
780 // Second read. 467 // Second read.
781 EXPECT_CALL(*data_source_, GetSize(_)) 468 EXPECT_CALL(*data_source, GetSize(_))
782 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true))); 469 .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true)));
783 EXPECT_CALL(*data_source_, Read(512, 512, kBuffer, NotNull())) 470 EXPECT_CALL(*data_source, Read(512, 512, kBuffer, NotNull()))
784 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback))); 471 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback)));
785 EXPECT_CALL(*demuxer, SignalReadCompleted(512)); 472 EXPECT_CALL(*demuxer, SignalReadCompleted(512));
786 EXPECT_CALL(*demuxer, WaitForRead()) 473 EXPECT_CALL(*demuxer, WaitForRead())
787 .WillOnce(Return(512)); 474 .WillOnce(Return(512));
788 EXPECT_CALL(host_, SetCurrentReadPosition(1024)); 475 EXPECT_CALL(host_, SetCurrentReadPosition(1024));
789 476
790 // Third read will fail because it exceeds the file size. 477 // Third read will fail because it exceeds the file size.
791 EXPECT_CALL(*data_source_, GetSize(_)) 478 EXPECT_CALL(*data_source, GetSize(_))
792 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true))); 479 .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true)));
793 480
794 // First read. 481 // First read.
795 EXPECT_EQ(512, demuxer->Read(512, kBuffer)); 482 EXPECT_EQ(512, demuxer->Read(512, kBuffer));
796 int64 position; 483 int64 position;
797 EXPECT_TRUE(demuxer->GetPosition(&position)); 484 EXPECT_TRUE(demuxer->GetPosition(&position));
798 EXPECT_EQ(512, position); 485 EXPECT_EQ(512, position);
799 486
800 // Second read. 487 // Second read.
801 EXPECT_EQ(512, demuxer->Read(512, kBuffer)); 488 EXPECT_EQ(512, demuxer->Read(512, kBuffer));
802 EXPECT_TRUE(demuxer->GetPosition(&position)); 489 EXPECT_TRUE(demuxer->GetPosition(&position));
803 EXPECT_EQ(1024, position); 490 EXPECT_EQ(1024, position);
804 491
805 // Third read will get an end-of-file error, which is represented as zero. 492 // Third read will get an end-of-file error, which is represented as zero.
806 EXPECT_EQ(0, demuxer->Read(512, kBuffer)); 493 EXPECT_EQ(0, demuxer->Read(512, kBuffer));
807 494
808 // This read complete signal is generated when demuxer is stopped. 495 // This read complete signal is generated when demuxer is stopped.
809 EXPECT_CALL(*demuxer, SignalReadCompleted(DataSource::kReadError)); 496 EXPECT_CALL(*demuxer, SignalReadCompleted(DataSource::kReadError));
810 demuxer->Stop(NewExpectedCallback()); 497 demuxer->Stop(NewExpectedCallback());
811 message_loop_.RunAllPending(); 498 message_loop_.RunAllPending();
812 } 499 }
813 500
814 TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) { 501 TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) {
815 { 502 scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm");
816 SCOPED_TRACE(""); 503 InitializeDemuxer(data_source);
817 InitializeDemuxer();
818 }
819 504
820 InSequence s; 505 InSequence s;
821 506
822 EXPECT_CALL(*data_source_, GetSize(_)) 507 int64 size;
823 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
824 EXPECT_CALL(*data_source_, GetSize(_))
825 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
826 EXPECT_CALL(*data_source_, GetSize(_))
827 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
828
829 int64 position; 508 int64 position;
509 EXPECT_TRUE(demuxer_->GetSize(&size));
830 EXPECT_TRUE(demuxer_->GetPosition(&position)); 510 EXPECT_TRUE(demuxer_->GetPosition(&position));
831 EXPECT_EQ(0, position); 511 EXPECT_EQ(current_read_position_, position);
832 512
833 EXPECT_TRUE(demuxer_->SetPosition(512)); 513 EXPECT_TRUE(demuxer_->SetPosition(512));
834 EXPECT_FALSE(demuxer_->SetPosition(2048)); 514 EXPECT_FALSE(demuxer_->SetPosition(size));
515 EXPECT_FALSE(demuxer_->SetPosition(size + 1));
835 EXPECT_FALSE(demuxer_->SetPosition(-1)); 516 EXPECT_FALSE(demuxer_->SetPosition(-1));
836 EXPECT_TRUE(demuxer_->GetPosition(&position)); 517 EXPECT_TRUE(demuxer_->GetPosition(&position));
837 EXPECT_EQ(512, position); 518 EXPECT_EQ(512, position);
838 } 519 }
839 520
840 TEST_F(FFmpegDemuxerTest, ProtocolGetSize) { 521 TEST_F(FFmpegDemuxerTest, ProtocolGetSize) {
841 { 522 scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm");
842 SCOPED_TRACE(""); 523 InitializeDemuxer(data_source);
843 InitializeDemuxer();
844 }
845 524
846 EXPECT_CALL(*data_source_, GetSize(_)) 525 int64 data_source_size = 0;
847 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true))); 526 int64 demuxer_size = 0;
848 527 EXPECT_TRUE(data_source->GetSize(&data_source_size));
849 int64 size; 528 EXPECT_TRUE(demuxer_->GetSize(&demuxer_size));
850 EXPECT_TRUE(demuxer_->GetSize(&size)); 529 EXPECT_NE(0, data_source_size);
851 EXPECT_EQ(1024, size); 530 EXPECT_EQ(data_source_size, demuxer_size);
852 } 531 }
853 532
854 TEST_F(FFmpegDemuxerTest, ProtocolIsStreaming) { 533 TEST_F(FFmpegDemuxerTest, ProtocolIsStreaming) {
855 { 534 scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm");
856 SCOPED_TRACE(""); 535 InitializeDemuxer(data_source);
857 InitializeDemuxer(); 536
858 } 537 EXPECT_FALSE(data_source->IsStreaming());
859 EXPECT_CALL(*data_source_, IsStreaming())
860 .WillOnce(Return(false));
861 EXPECT_FALSE(demuxer_->IsStreaming()); 538 EXPECT_FALSE(demuxer_->IsStreaming());
862 } 539 }
863 540
864 } // namespace media 541 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698