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

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

Issue 7658017: Revert 96974 - 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
« no previous file with comments | « media/filters/chunk_demuxer_unittest.cc ('k') | media/filters/ffmpeg_glue.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
9 #include "base/threading/thread.h" 7 #include "base/threading/thread.h"
10 #include "media/base/filters.h" 8 #include "media/base/filters.h"
11 #include "media/base/mock_callback.h" 9 #include "media/base/mock_callback.h"
10 #include "media/base/mock_ffmpeg.h"
12 #include "media/base/mock_filter_host.h" 11 #include "media/base/mock_filter_host.h"
13 #include "media/base/mock_filters.h" 12 #include "media/base/mock_filters.h"
14 #include "media/base/mock_reader.h" 13 #include "media/base/mock_reader.h"
15 #include "media/ffmpeg/ffmpeg_common.h" 14 #include "media/ffmpeg/ffmpeg_common.h"
16 #include "media/filters/ffmpeg_demuxer.h" 15 #include "media/filters/ffmpeg_demuxer.h"
17 #include "media/filters/file_data_source.h"
18 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
19 17
20 using ::testing::AnyNumber; 18 using ::testing::AnyNumber;
21 using ::testing::DoAll; 19 using ::testing::DoAll;
22 using ::testing::InSequence; 20 using ::testing::InSequence;
23 using ::testing::Invoke; 21 using ::testing::Invoke;
24 using ::testing::NotNull; 22 using ::testing::NotNull;
25 using ::testing::Return; 23 using ::testing::Return;
26 using ::testing::SaveArg; 24 using ::testing::SetArgumentPointee;
27 using ::testing::SetArgPointee;
28 using ::testing::StrictMock; 25 using ::testing::StrictMock;
29 using ::testing::WithArgs; 26 using ::testing::WithArgs;
30 using ::testing::_; 27 using ::testing::_;
31 28
32 namespace media { 29 namespace media {
33 30
34 // Fixture class to facilitate writing tests. Takes care of setting up the 31 // Fixture class to facilitate writing tests. Takes care of setting up the
35 // FFmpeg, pipeline and filter host mocks. 32 // FFmpeg, pipeline and filter host mocks.
36 class FFmpegDemuxerTest : public testing::Test { 33 class FFmpegDemuxerTest : public testing::Test {
37 protected: 34 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;
38 65
39 FFmpegDemuxerTest() { 66 FFmpegDemuxerTest() {
40 // Create an FFmpegDemuxer. 67 // Create an FFmpegDemuxer.
41 demuxer_ = new FFmpegDemuxer(&message_loop_); 68 demuxer_ = new FFmpegDemuxer(&message_loop_);
42 demuxer_->disable_first_seek_hack_for_testing(); 69 demuxer_->disable_first_seek_hack_for_testing();
43 70
44 // Inject a filter host and message loop and prepare a data source. 71 // Inject a filter host and message loop and prepare a data source.
45 demuxer_->set_host(&host_); 72 demuxer_->set_host(&host_);
73 data_source_ = new StrictMock<MockDataSource>();
46 74
47 EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber()); 75 EXPECT_CALL(*data_source_, Stop(NotNull()))
48 EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber()); 76 .WillRepeatedly(Invoke(&RunStopFilterCallback));
49 EXPECT_CALL(host_, SetCurrentReadPosition(_)) 77
50 .WillRepeatedly(SaveArg<0>(&current_read_position_)); 78 // Initialize FFmpeg fixtures.
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 }
51 } 112 }
52 113
53 virtual ~FFmpegDemuxerTest() { 114 virtual ~FFmpegDemuxerTest() {
54 // Call Stop() to shut down internal threads. 115 // Call Stop() to shut down internal threads.
55 demuxer_->Stop(NewExpectedCallback()); 116 demuxer_->Stop(NewExpectedCallback());
56 117
57 // Finish up any remaining tasks. 118 // Finish up any remaining tasks.
58 message_loop_.RunAllPending(); 119 message_loop_.RunAllPending();
59 // Release the reference to the demuxer. 120 // Release the reference to the demuxer.
60 demuxer_ = NULL; 121 demuxer_ = NULL;
61 } 122
62 123 if (format_context_.streams) {
63 scoped_refptr<DataSource> CreateDataSource(const std::string& name) { 124 delete[] format_context_.streams;
64 FilePath file_path; 125 format_context_.streams = NULL;
65 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); 126 format_context_.nb_streams = 0;
66 127 }
67 file_path = file_path.Append(FILE_PATH_LITERAL("media")) 128 }
68 .Append(FILE_PATH_LITERAL("test")) 129
69 .Append(FILE_PATH_LITERAL("data")) 130 // Sets up MockFFmpeg to allow FFmpegDemuxer to successfully initialize.
70 .AppendASCII(name); 131 void InitializeDemuxerMocks() {
71 132 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL))
72 scoped_refptr<FileDataSource> data_source = new FileDataSource(); 133 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0)));
73 134 EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_))
74 EXPECT_EQ(PIPELINE_OK, data_source->Initialize(file_path.MaybeAsASCII())); 135 .WillOnce(Return(0));
75 136 EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_));
76 return data_source.get(); 137 }
77 } 138
78 139 // Initializes both MockFFmpeg and FFmpegDemuxer.
79 MOCK_METHOD1(CheckPoint, void(int v)); 140 void InitializeDemuxer() {
80 141 InitializeDemuxerMocks();
81 // Initializes FFmpegDemuxer. 142
82 void InitializeDemuxer(const scoped_refptr<DataSource>& data_source) { 143 // Since we ignore data streams, the duration should be equal to the longest
83 EXPECT_CALL(host_, SetDuration(_)); 144 // supported stream's duration (audio, in this case).
84 demuxer_->Initialize(data_source, NewExpectedStatusCB(PIPELINE_OK)); 145 base::TimeDelta expected_duration =
146 base::TimeDelta::FromMicroseconds(kDurations[AV_STREAM_AUDIO]);
147 EXPECT_CALL(host_, SetDuration(expected_duration));
148
149 demuxer_->Initialize(data_source_.get(),
150 NewExpectedStatusCB(PIPELINE_OK));
85 message_loop_.RunAllPending(); 151 message_loop_.RunAllPending();
86 } 152 }
87 153
88 // Verifies that |buffer| has a specific |size| and |timestamp|.
89 // |location| simply indicates where the call to this function was made.
90 // This makes it easier to track down where test failures occur.
91 void ValidateBuffer(const tracked_objects::Location& location,
92 const scoped_refptr<Buffer>& buffer,
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());
102 }
103
104 // Fixture members. 154 // Fixture members.
105 scoped_refptr<FFmpegDemuxer> demuxer_; 155 scoped_refptr<FFmpegDemuxer> demuxer_;
156 scoped_refptr<StrictMock<MockDataSource> > data_source_;
106 StrictMock<MockFilterHost> host_; 157 StrictMock<MockFilterHost> host_;
107 MessageLoop message_loop_; 158 MessageLoop message_loop_;
108 159
109 int64 current_read_position_; 160 // FFmpeg fixtures.
161 AVFormatContext format_context_;
162 AVInputFormat input_format_;
163 AVCodecContext codecs_[AV_STREAM_MAX];
164 AVStream streams_[AV_STREAM_MAX];
165 MockFFmpeg mock_ffmpeg_;
110 166
111 private: 167 private:
112 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); 168 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
113 }; 169 };
114 170
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
115 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { 184 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
116 // Simulate av_open_input_file() failing. 185 // Simulate av_open_input_file() failing.
117 EXPECT_CALL(host_, SetCurrentReadPosition(_)); 186 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL))
118 demuxer_->Initialize(CreateDataSource("ten_byte_file"), 187 .WillOnce(Return(-1));
188
189 demuxer_->Initialize(data_source_.get(),
119 NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); 190 NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
120 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 }
133 207
134 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { 208 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
135 // Open a file with no parseable streams. 209 // Simulate media with no parseable streams.
136 EXPECT_CALL(host_, SetCurrentReadPosition(_)); 210 {
211 SCOPED_TRACE("");
212 InitializeDemuxerMocks();
213 }
214 format_context_.nb_streams = 0;
215
137 demuxer_->Initialize( 216 demuxer_->Initialize(
138 CreateDataSource("no_streams.webm"), 217 data_source_.get(),
139 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); 218 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
140 message_loop_.RunAllPending(); 219 message_loop_.RunAllPending();
141 } 220 }
142 221
143 // TODO(acolwell): Find a subtitle only file so we can uncomment this test. 222 TEST_F(FFmpegDemuxerTest, Initialize_DataStreamOnly) {
144 // 223 // Simulate media with a data stream but no audio or video streams.
145 //TEST_F(FFmpegDemuxerTest, Initialize_DataStreamOnly) { 224 {
146 // demuxer_->Initialize( 225 SCOPED_TRACE("");
147 // CreateDataSource("subtitles_only.mp4"),, 226 InitializeDemuxerMocks();
148 // NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); 227 }
149 // message_loop_.RunAllPending(); 228 EXPECT_EQ(format_context_.streams[0], &streams_[AV_STREAM_DATA]);
150 //} 229 format_context_.nb_streams = 1;
230
231 demuxer_->Initialize(
232 data_source_.get(),
233 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
234 message_loop_.RunAllPending();
235 }
151 236
152 TEST_F(FFmpegDemuxerTest, Initialize_Successful) { 237 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
153 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); 238 {
239 SCOPED_TRACE("");
240 InitializeDemuxer();
241 }
154 242
155 // First stream should be video and support the FFmpegDemuxerStream interface. 243 // First stream should be video and support the FFmpegDemuxerStream interface.
156 scoped_refptr<DemuxerStream> stream = 244 scoped_refptr<DemuxerStream> stream =
157 demuxer_->GetStream(DemuxerStream::VIDEO); 245 demuxer_->GetStream(DemuxerStream::VIDEO);
158 ASSERT_TRUE(stream); 246 ASSERT_TRUE(stream);
159 EXPECT_EQ(DemuxerStream::VIDEO, stream->type()); 247 EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
160 ASSERT_TRUE(stream->GetAVStream()); 248 EXPECT_EQ(&streams_[AV_STREAM_VIDEO], stream->GetAVStream());
161 249
162 // Other stream should be audio and support the FFmpegDemuxerStream interface. 250 // Other stream should be audio and support the FFmpegDemuxerStream interface.
163 stream = demuxer_->GetStream(DemuxerStream::AUDIO); 251 stream = demuxer_->GetStream(DemuxerStream::AUDIO);
164 ASSERT_TRUE(stream); 252 ASSERT_TRUE(stream);
165 EXPECT_EQ(DemuxerStream::AUDIO, stream->type()); 253 EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
166 ASSERT_TRUE(stream->GetAVStream()); 254 EXPECT_EQ(&streams_[AV_STREAM_AUDIO], stream->GetAVStream());
167 } 255 }
168 256
169 TEST_F(FFmpegDemuxerTest, Read_Audio) { 257 TEST_F(FFmpegDemuxerTest, Read_DiscardUninteresting) {
170 // We test that on a successful audio packet read. 258 // We test that on a successful audio packet read, that the packet is
171 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); 259 // duplicated (FFmpeg memory management safety), and a copy of it ends up in
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)));
172 276
173 // Attempt a read from the audio stream and run the message loop until done. 277 // Attempt a read from the audio stream and run the message loop until done.
174 scoped_refptr<DemuxerStream> audio = 278 scoped_refptr<DemuxerStream> audio =
175 demuxer_->GetStream(DemuxerStream::AUDIO); 279 demuxer_->GetStream(DemuxerStream::AUDIO);
176 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 280 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
177 reader->Read(audio); 281 reader->Read(audio);
178 message_loop_.RunAllPending(); 282 message_loop_.RunAllPending();
179 EXPECT_TRUE(reader->called()); 283
180 ValidateBuffer(FROM_HERE, reader->buffer(), 29, 0); 284 EXPECT_TRUE(reader->called());
181 285 ASSERT_TRUE(reader->buffer());
182 reader->Reset(); 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());
183 reader->Read(audio); 312 reader->Read(audio);
184 message_loop_.RunAllPending(); 313 message_loop_.RunAllPending();
185 EXPECT_TRUE(reader->called()); 314
186 ValidateBuffer(FROM_HERE, reader->buffer(), 27, 3000); 315 EXPECT_TRUE(reader->called());
316 ASSERT_TRUE(reader->buffer());
317 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
318 EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
319 reader->buffer()->GetDataSize()));
187 } 320 }
188 321
189 TEST_F(FFmpegDemuxerTest, Read_Video) { 322 TEST_F(FFmpegDemuxerTest, Read_Video) {
190 // We test that on a successful video packet read. 323 // We test that on a successful video packet read, that the packet is
191 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); 324 // duplicated (FFmpeg memory management safety), and a copy of it ends up in
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));
192 339
193 // Attempt a read from the video stream and run the message loop until done. 340 // Attempt a read from the video stream and run the message loop until done.
194 scoped_refptr<DemuxerStream> video = 341 scoped_refptr<DemuxerStream> video =
195 demuxer_->GetStream(DemuxerStream::VIDEO); 342 demuxer_->GetStream(DemuxerStream::VIDEO);
196 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 343 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
197
198 reader->Read(video); 344 reader->Read(video);
199 message_loop_.RunAllPending(); 345 message_loop_.RunAllPending();
200 EXPECT_TRUE(reader->called()); 346
201 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0); 347 EXPECT_TRUE(reader->called());
202 348 ASSERT_TRUE(reader->buffer());
203 reader->Reset(); 349 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
204 reader->Read(video); 350 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
205 message_loop_.RunAllPending(); 351 reader->buffer()->GetDataSize()));
206 EXPECT_TRUE(reader->called());
207 ValidateBuffer(FROM_HERE, reader->buffer(), 1057, 33000);
208 } 352 }
209 353
210 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) { 354 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) {
211 // Test the start time is the first timestamp of the video and audio stream. 355 // Test the start time is the first timestamp of the video and audio stream.
212 InitializeDemuxer(CreateDataSource("nonzero-start-time.webm")); 356 const int64 kStartTime = 60000;
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());
213 367
214 const base::TimeDelta kExpectedTimestamp = 368 const base::TimeDelta kExpectedTimestamp =
215 base::TimeDelta::FromMicroseconds(396000); 369 base::TimeDelta::FromMicroseconds(kStartTime);
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));
216 435
217 // Attempt a read from the video stream and run the message loop until done. 436 // Attempt a read from the video stream and run the message loop until done.
218 scoped_refptr<DemuxerStream> video = 437 scoped_refptr<DemuxerStream> video =
219 demuxer_->GetStream(DemuxerStream::VIDEO); 438 demuxer_->GetStream(DemuxerStream::VIDEO);
220 scoped_refptr<DemuxerStream> audio = 439 scoped_refptr<DemuxerStream> audio =
221 demuxer_->GetStream(DemuxerStream::AUDIO); 440 demuxer_->GetStream(DemuxerStream::AUDIO);
222 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 441 ASSERT_TRUE(video);
223 442 ASSERT_TRUE(audio);
224 // Check first buffer in video stream. 443
444 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
225 reader->Read(video); 445 reader->Read(video);
226 message_loop_.RunAllPending(); 446 message_loop_.RunAllPending();
227 EXPECT_TRUE(reader->called()); 447
228 ValidateBuffer(FROM_HERE, reader->buffer(), 5636, 400000); 448 EXPECT_TRUE(reader->called());
229 const base::TimeDelta video_timestamp = reader->buffer()->GetTimestamp(); 449 ASSERT_TRUE(reader->buffer());
230 450 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
231 // Check first buffer in audio stream. 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
232 reader->Reset(); 457 reader->Reset();
233 reader->Read(audio); 458 reader->Read(audio);
234 message_loop_.RunAllPending(); 459 message_loop_.RunAllPending();
235 EXPECT_TRUE(reader->called()); 460 EXPECT_TRUE(reader->called());
236 ValidateBuffer(FROM_HERE, reader->buffer(), 165, 396000); 461 ASSERT_TRUE(reader->buffer());
237 const base::TimeDelta audio_timestamp = reader->buffer()->GetTimestamp(); 462 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
238 463 EXPECT_EQ(kExpectedAudioTimestamp, reader->buffer()->GetTimestamp());
239 // Verify that the start time is equal to the lowest timestamp. 464 EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
240 EXPECT_EQ(std::min(audio_timestamp, video_timestamp), 465 reader->buffer()->GetDataSize()));
241 demuxer_->GetStartTime()); 466
467 EXPECT_EQ(kExpectedAudioTimestamp, demuxer_->GetStartTime());
242 } 468 }
243 469
244 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { 470 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
245 // Verify that end of stream buffers are created. 471 // On end of stream, a new, empty, AVPackets are created without any data for
246 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); 472 // each stream and enqueued into the Buffer stream. Verify that these are
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)));
247 484
248 // We should now expect an end of stream buffer. 485 // We should now expect an end of stream buffer.
249 scoped_refptr<DemuxerStream> audio = 486 scoped_refptr<DemuxerStream> audio =
250 demuxer_->GetStream(DemuxerStream::AUDIO); 487 demuxer_->GetStream(DemuxerStream::AUDIO);
251 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 488 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
252 489 reader->Read(audio);
253 bool got_eos_buffer = false; 490 message_loop_.RunAllPending();
254 const int kMaxBuffers = 170; 491 EXPECT_TRUE(reader->called());
255 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) { 492 ASSERT_TRUE(reader->buffer());
256 reader->Read(audio); 493 EXPECT_TRUE(reader->buffer()->IsEndOfStream());
257 message_loop_.RunAllPending(); 494 EXPECT_TRUE(reader->buffer()->GetData() == NULL);
258 EXPECT_TRUE(reader->called()); 495 EXPECT_EQ(0u, reader->buffer()->GetDataSize());
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);
274 } 496 }
275 497
276 TEST_F(FFmpegDemuxerTest, Seek) { 498 TEST_F(FFmpegDemuxerTest, Seek) {
277 // We're testing that the demuxer frees all queued packets when it receives 499 // We're testing that the demuxer frees all queued packets when it receives
278 // a Seek(). 500 // a Seek().
279 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); 501 //
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 }
280 508
281 // Get our streams. 509 // Get our streams.
282 scoped_refptr<DemuxerStream> video = 510 scoped_refptr<DemuxerStream> video =
283 demuxer_->GetStream(DemuxerStream::VIDEO); 511 demuxer_->GetStream(DemuxerStream::VIDEO);
284 scoped_refptr<DemuxerStream> audio = 512 scoped_refptr<DemuxerStream> audio =
285 demuxer_->GetStream(DemuxerStream::AUDIO); 513 demuxer_->GetStream(DemuxerStream::AUDIO);
286 ASSERT_TRUE(video); 514 ASSERT_TRUE(video);
287 ASSERT_TRUE(audio); 515 ASSERT_TRUE(audio);
288 516
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
289 // Read a video packet and release it. 576 // Read a video packet and release it.
290 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 577 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
291 reader->Read(video); 578 reader->Read(video);
292 message_loop_.RunAllPending(); 579 message_loop_.RunAllPending();
293 EXPECT_TRUE(reader->called()); 580 EXPECT_TRUE(reader->called());
294 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0); 581 ASSERT_TRUE(reader->buffer());
582 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
583 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
584 reader->buffer()->GetDataSize()));
295 585
296 // Release the video packet and verify the other packets are still queued. 586 // Release the video packet and verify the other packets are still queued.
297 reader->Reset(); 587 reader->Reset();
298 message_loop_.RunAllPending(); 588 message_loop_.RunAllPending();
589 mock_ffmpeg_.CheckPoint(1);
299 590
300 // Issue a simple forward seek, which should discard queued packets. 591 // Issue a simple forward seek, which should discard queued packets.
301 demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000), 592 demuxer_->Seek(base::TimeDelta::FromMicroseconds(kExpectedTimestamp),
302 NewExpectedStatusCB(PIPELINE_OK)); 593 seek_cb);
303 message_loop_.RunAllPending(); 594 message_loop_.RunAllPending();
595 mock_ffmpeg_.CheckPoint(2);
304 596
305 // Audio read #1. 597 // Audio read #1.
306 reader->Read(audio); 598 reader->Read(audio);
307 message_loop_.RunAllPending(); 599 message_loop_.RunAllPending();
308 EXPECT_TRUE(reader->called()); 600 EXPECT_TRUE(reader->called());
309 ValidateBuffer(FROM_HERE, reader->buffer(), 145, 803000); 601 ASSERT_TRUE(reader->buffer());
602 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
603 EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
604 reader->buffer()->GetDataSize()));
310 605
311 // Audio read #2. 606 // Audio read #2.
312 reader->Reset(); 607 reader->Reset();
313 reader->Read(audio); 608 reader->Read(audio);
314 message_loop_.RunAllPending(); 609 message_loop_.RunAllPending();
315 EXPECT_TRUE(reader->called()); 610 EXPECT_TRUE(reader->called());
316 ValidateBuffer(FROM_HERE, reader->buffer(), 148, 826000); 611 ASSERT_TRUE(reader->buffer());
612 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
613 EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
614 reader->buffer()->GetDataSize()));
317 615
318 // Video read #1. 616 // Video read #1.
319 reader->Reset(); 617 reader->Reset();
320 reader->Read(video); 618 reader->Read(video);
321 message_loop_.RunAllPending(); 619 message_loop_.RunAllPending();
322 EXPECT_TRUE(reader->called()); 620 EXPECT_TRUE(reader->called());
323 ValidateBuffer(FROM_HERE, reader->buffer(), 5425, 801000); 621 ASSERT_TRUE(reader->buffer());
622 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
623 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
624 reader->buffer()->GetDataSize()));
324 625
325 // Video read #2. 626 // Video read #2.
326 reader->Reset(); 627 reader->Reset();
327 reader->Read(video); 628 reader->Read(video);
328 message_loop_.RunAllPending(); 629 message_loop_.RunAllPending();
329 EXPECT_TRUE(reader->called()); 630 EXPECT_TRUE(reader->called());
330 ValidateBuffer(FROM_HERE, reader->buffer(), 1906, 834000); 631 ASSERT_TRUE(reader->buffer());
632 ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
633 EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
634 reader->buffer()->GetDataSize()));
331 635
332 // Manually release the last reference to the buffer and verify it was freed. 636 // Manually release the last reference to the buffer and verify it was freed.
333 reader->Reset(); 637 reader->Reset();
334 message_loop_.RunAllPending(); 638 message_loop_.RunAllPending();
639 mock_ffmpeg_.CheckPoint(3);
335 } 640 }
336 641
337 // A mocked callback specialization for calling Read(). Since RunWithParams() 642 // A mocked callback specialization for calling Read(). Since RunWithParams()
338 // is mocked we don't need to pass in object or method pointers. 643 // is mocked we don't need to pass in object or method pointers.
339 class MockReadCallback : public base::RefCountedThreadSafe<MockReadCallback> { 644 class MockReadCallback : public base::RefCountedThreadSafe<MockReadCallback> {
340 public: 645 public:
341 MockReadCallback() {} 646 MockReadCallback() {}
342 647
343 virtual ~MockReadCallback() { 648 virtual ~MockReadCallback() {
344 OnDelete(); 649 OnDelete();
345 } 650 }
346 651
347 MOCK_METHOD0(OnDelete, void()); 652 MOCK_METHOD0(OnDelete, void());
348 MOCK_METHOD1(Run, void(Buffer* buffer)); 653 MOCK_METHOD1(Run, void(Buffer* buffer));
349 654
350 private: 655 private:
351 DISALLOW_COPY_AND_ASSIGN(MockReadCallback); 656 DISALLOW_COPY_AND_ASSIGN(MockReadCallback);
352 }; 657 };
353 658
354 TEST_F(FFmpegDemuxerTest, Stop) { 659 TEST_F(FFmpegDemuxerTest, Stop) {
355 // Tests that calling Read() on a stopped demuxer immediately deletes the 660 // Tests that calling Read() on a stopped demuxer immediately deletes the
356 // callback. 661 // callback.
357 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); 662 {
663 SCOPED_TRACE("");
664 InitializeDemuxer();
665 }
358 666
359 // Get our stream. 667 // Get our stream.
360 scoped_refptr<DemuxerStream> audio = 668 scoped_refptr<DemuxerStream> audio =
361 demuxer_->GetStream(DemuxerStream::AUDIO); 669 demuxer_->GetStream(DemuxerStream::AUDIO);
362 ASSERT_TRUE(audio); 670 ASSERT_TRUE(audio);
363 671
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();
364 demuxer_->Stop(NewExpectedCallback()); 677 demuxer_->Stop(NewExpectedCallback());
365 678
366 // Expect all calls in sequence. 679 // Expect all calls in sequence.
367 InSequence s; 680 InSequence s;
368 681
369 // Create our mocked callback. The Callback created by base::Bind() will take 682 // Create our mocked callback. The Callback created by base::Bind() will take
370 // ownership of this pointer. 683 // ownership of this pointer.
371 StrictMock<MockReadCallback>* callback = new StrictMock<MockReadCallback>(); 684 StrictMock<MockReadCallback>* callback = new StrictMock<MockReadCallback>();
372 685
373 // The callback should be immediately deleted. We'll use a checkpoint to 686 // The callback should be immediately deleted. We'll use a checkpoint to
374 // verify that it has indeed been deleted. 687 // verify that it has indeed been deleted.
375 EXPECT_CALL(*callback, OnDelete()); 688 EXPECT_CALL(*callback, OnDelete());
376 EXPECT_CALL(*this, CheckPoint(1)); 689 EXPECT_CALL(mock_ffmpeg_, CheckPoint(1));
377 690
378 // Attempt the read... 691 // Attempt the read...
379 audio->Read(base::Bind(&MockReadCallback::Run, callback)); 692 audio->Read(base::Bind(&MockReadCallback::Run, callback));
380 693
381 message_loop_.RunAllPending(); 694 message_loop_.RunAllPending();
382 695
383 // ...and verify that |callback| was deleted. 696 // ...and verify that |callback| was deleted.
384 CheckPoint(1); 697 mock_ffmpeg_.CheckPoint(1);
385 } 698 }
386 699
387 TEST_F(FFmpegDemuxerTest, DisableAudioStream) { 700 TEST_F(FFmpegDemuxerTest, DisableAudioStream) {
388 // We are doing the following things here: 701 // We are doing the following things here:
389 // 1. Initialize the demuxer with audio and video stream. 702 // 1. Initialize the demuxer with audio and video stream.
390 // 2. Send a "disable audio stream" message to the demuxer. 703 // 2. Send a "disable audio stream" message to the demuxer.
391 // 3. Demuxer will free audio packets even if audio stream was initialized. 704 // 3. Demuxer will free audio packets even if audio stream was initialized.
392 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); 705 {
706 SCOPED_TRACE("");
707 InitializeDemuxer();
708 }
393 709
394 // Submit a "disable audio stream" message to the demuxer. 710 // Submit a "disable audio stream" message to the demuxer.
395 demuxer_->OnAudioRendererDisabled(); 711 demuxer_->OnAudioRendererDisabled();
396 message_loop_.RunAllPending(); 712 message_loop_.RunAllPending();
397 713
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
398 // Get our streams. 728 // Get our streams.
399 scoped_refptr<DemuxerStream> video = 729 scoped_refptr<DemuxerStream> video =
400 demuxer_->GetStream(DemuxerStream::VIDEO); 730 demuxer_->GetStream(DemuxerStream::VIDEO);
401 scoped_refptr<DemuxerStream> audio =
402 demuxer_->GetStream(DemuxerStream::AUDIO);
403 ASSERT_TRUE(video); 731 ASSERT_TRUE(video);
404 ASSERT_TRUE(audio);
405 732
406 // Attempt a read from the video stream and run the message loop until done. 733 // Attempt a read from the video stream and run the message loop until done.
407 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 734 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
408 reader->Read(video); 735 reader->Read(video);
409 message_loop_.RunAllPending(); 736 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());
418 } 737 }
419 738
420 class MockFFmpegDemuxer : public FFmpegDemuxer { 739 class MockFFmpegDemuxer : public FFmpegDemuxer {
421 public: 740 public:
422 explicit MockFFmpegDemuxer(MessageLoop* message_loop) 741 explicit MockFFmpegDemuxer(MessageLoop* message_loop)
423 : FFmpegDemuxer(message_loop) { 742 : FFmpegDemuxer(message_loop) {
424 } 743 }
425 virtual ~MockFFmpegDemuxer() {} 744 virtual ~MockFFmpegDemuxer() {}
426 745
427 MOCK_METHOD0(WaitForRead, size_t()); 746 MOCK_METHOD0(WaitForRead, size_t());
428 MOCK_METHOD1(SignalReadCompleted, void(size_t size)); 747 MOCK_METHOD1(SignalReadCompleted, void(size_t size));
429 748
430 private: 749 private:
431 DISALLOW_COPY_AND_ASSIGN(MockFFmpegDemuxer); 750 DISALLOW_COPY_AND_ASSIGN(MockFFmpegDemuxer);
432 }; 751 };
433 752
434 // A gmock helper method to execute the callback and deletes it. 753 // A gmock helper method to execute the callback and deletes it.
435 void RunCallback(size_t size, DataSource::ReadCallback* callback) { 754 void RunCallback(size_t size, DataSource::ReadCallback* callback) {
436 DCHECK(callback); 755 DCHECK(callback);
437 callback->RunWithParams(Tuple1<size_t>(size)); 756 callback->RunWithParams(Tuple1<size_t>(size));
438 delete callback; 757 delete callback;
439 } 758 }
440 759
441 TEST_F(FFmpegDemuxerTest, ProtocolRead) { 760 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
448 // Creates a demuxer. 761 // Creates a demuxer.
449 scoped_refptr<MockFFmpegDemuxer> demuxer( 762 scoped_refptr<MockFFmpegDemuxer> demuxer(
450 new MockFFmpegDemuxer(&message_loop_)); 763 new MockFFmpegDemuxer(&message_loop_));
451 ASSERT_TRUE(demuxer); 764 ASSERT_TRUE(demuxer);
452 demuxer->set_host(&host_); 765 demuxer->set_host(&host_);
453 demuxer->data_source_ = data_source; 766 demuxer->data_source_ = data_source_;
454 767
455 uint8 kBuffer[1]; 768 uint8 kBuffer[1];
456 InSequence s; 769 InSequence s;
457 // Actions taken in the first read. 770 // Actions taken in the first read.
458 EXPECT_CALL(*data_source, GetSize(_)) 771 EXPECT_CALL(*data_source_, GetSize(_))
459 .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true))); 772 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
460 EXPECT_CALL(*data_source, Read(0, 512, kBuffer, NotNull())) 773 EXPECT_CALL(*data_source_, Read(0, 512, kBuffer, NotNull()))
461 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback))); 774 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback)));
462 EXPECT_CALL(*demuxer, SignalReadCompleted(512)); 775 EXPECT_CALL(*demuxer, SignalReadCompleted(512));
463 EXPECT_CALL(*demuxer, WaitForRead()) 776 EXPECT_CALL(*demuxer, WaitForRead())
464 .WillOnce(Return(512)); 777 .WillOnce(Return(512));
465 EXPECT_CALL(host_, SetCurrentReadPosition(512)); 778 EXPECT_CALL(host_, SetCurrentReadPosition(512));
466 779
467 // Second read. 780 // Second read.
468 EXPECT_CALL(*data_source, GetSize(_)) 781 EXPECT_CALL(*data_source_, GetSize(_))
469 .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true))); 782 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
470 EXPECT_CALL(*data_source, Read(512, 512, kBuffer, NotNull())) 783 EXPECT_CALL(*data_source_, Read(512, 512, kBuffer, NotNull()))
471 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback))); 784 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback)));
472 EXPECT_CALL(*demuxer, SignalReadCompleted(512)); 785 EXPECT_CALL(*demuxer, SignalReadCompleted(512));
473 EXPECT_CALL(*demuxer, WaitForRead()) 786 EXPECT_CALL(*demuxer, WaitForRead())
474 .WillOnce(Return(512)); 787 .WillOnce(Return(512));
475 EXPECT_CALL(host_, SetCurrentReadPosition(1024)); 788 EXPECT_CALL(host_, SetCurrentReadPosition(1024));
476 789
477 // Third read will fail because it exceeds the file size. 790 // Third read will fail because it exceeds the file size.
478 EXPECT_CALL(*data_source, GetSize(_)) 791 EXPECT_CALL(*data_source_, GetSize(_))
479 .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true))); 792 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
480 793
481 // First read. 794 // First read.
482 EXPECT_EQ(512, demuxer->Read(512, kBuffer)); 795 EXPECT_EQ(512, demuxer->Read(512, kBuffer));
483 int64 position; 796 int64 position;
484 EXPECT_TRUE(demuxer->GetPosition(&position)); 797 EXPECT_TRUE(demuxer->GetPosition(&position));
485 EXPECT_EQ(512, position); 798 EXPECT_EQ(512, position);
486 799
487 // Second read. 800 // Second read.
488 EXPECT_EQ(512, demuxer->Read(512, kBuffer)); 801 EXPECT_EQ(512, demuxer->Read(512, kBuffer));
489 EXPECT_TRUE(demuxer->GetPosition(&position)); 802 EXPECT_TRUE(demuxer->GetPosition(&position));
490 EXPECT_EQ(1024, position); 803 EXPECT_EQ(1024, position);
491 804
492 // Third read will get an end-of-file error, which is represented as zero. 805 // Third read will get an end-of-file error, which is represented as zero.
493 EXPECT_EQ(0, demuxer->Read(512, kBuffer)); 806 EXPECT_EQ(0, demuxer->Read(512, kBuffer));
494 807
495 // This read complete signal is generated when demuxer is stopped. 808 // This read complete signal is generated when demuxer is stopped.
496 EXPECT_CALL(*demuxer, SignalReadCompleted(DataSource::kReadError)); 809 EXPECT_CALL(*demuxer, SignalReadCompleted(DataSource::kReadError));
497 demuxer->Stop(NewExpectedCallback()); 810 demuxer->Stop(NewExpectedCallback());
498 message_loop_.RunAllPending(); 811 message_loop_.RunAllPending();
499 } 812 }
500 813
501 TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) { 814 TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) {
502 scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm"); 815 {
503 InitializeDemuxer(data_source); 816 SCOPED_TRACE("");
817 InitializeDemuxer();
818 }
504 819
505 InSequence s; 820 InSequence s;
506 821
507 int64 size; 822 EXPECT_CALL(*data_source_, GetSize(_))
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
508 int64 position; 829 int64 position;
509 EXPECT_TRUE(demuxer_->GetSize(&size));
510 EXPECT_TRUE(demuxer_->GetPosition(&position)); 830 EXPECT_TRUE(demuxer_->GetPosition(&position));
511 EXPECT_EQ(current_read_position_, position); 831 EXPECT_EQ(0, position);
512 832
513 EXPECT_TRUE(demuxer_->SetPosition(512)); 833 EXPECT_TRUE(demuxer_->SetPosition(512));
514 EXPECT_FALSE(demuxer_->SetPosition(size)); 834 EXPECT_FALSE(demuxer_->SetPosition(2048));
515 EXPECT_FALSE(demuxer_->SetPosition(size + 1));
516 EXPECT_FALSE(demuxer_->SetPosition(-1)); 835 EXPECT_FALSE(demuxer_->SetPosition(-1));
517 EXPECT_TRUE(demuxer_->GetPosition(&position)); 836 EXPECT_TRUE(demuxer_->GetPosition(&position));
518 EXPECT_EQ(512, position); 837 EXPECT_EQ(512, position);
519 } 838 }
520 839
521 TEST_F(FFmpegDemuxerTest, ProtocolGetSize) { 840 TEST_F(FFmpegDemuxerTest, ProtocolGetSize) {
522 scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm"); 841 {
523 InitializeDemuxer(data_source); 842 SCOPED_TRACE("");
843 InitializeDemuxer();
844 }
524 845
525 int64 data_source_size = 0; 846 EXPECT_CALL(*data_source_, GetSize(_))
526 int64 demuxer_size = 0; 847 .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
527 EXPECT_TRUE(data_source->GetSize(&data_source_size)); 848
528 EXPECT_TRUE(demuxer_->GetSize(&demuxer_size)); 849 int64 size;
529 EXPECT_NE(0, data_source_size); 850 EXPECT_TRUE(demuxer_->GetSize(&size));
530 EXPECT_EQ(data_source_size, demuxer_size); 851 EXPECT_EQ(1024, size);
531 } 852 }
532 853
533 TEST_F(FFmpegDemuxerTest, ProtocolIsStreaming) { 854 TEST_F(FFmpegDemuxerTest, ProtocolIsStreaming) {
534 scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm"); 855 {
535 InitializeDemuxer(data_source); 856 SCOPED_TRACE("");
536 857 InitializeDemuxer();
537 EXPECT_FALSE(data_source->IsStreaming()); 858 }
859 EXPECT_CALL(*data_source_, IsStreaming())
860 .WillOnce(Return(false));
538 EXPECT_FALSE(demuxer_->IsStreaming()); 861 EXPECT_FALSE(demuxer_->IsStreaming());
539 } 862 }
540 863
541 } // namespace media 864 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer_unittest.cc ('k') | media/filters/ffmpeg_glue.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698