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

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

Issue 126306: Refactor FFmpegDemuxerTest to use gmock and eliminate flakiness. (Closed)
Patch Set: Added SCOPED_TRACE Created 11 years, 6 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
« no previous file with comments | « media/filters/ffmpeg_demuxer.cc ('k') | no next file » | 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) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/singleton.h" 7 #include "base/singleton.h"
8 #include "base/tuple.h" 8 #include "base/tuple.h"
9 #include "media/base/filter_host.h" 9 #include "media/base/filter_host.h"
10 #include "media/base/filters.h" 10 #include "media/base/filters.h"
11 #include "media/base/mock_ffmpeg.h"
11 #include "media/base/mock_filter_host.h" 12 #include "media/base/mock_filter_host.h"
12 #include "media/base/mock_media_filters.h" 13 #include "media/base/mock_media_filters.h"
13 #include "media/base/mock_reader.h" 14 #include "media/base/mock_reader.h"
14 #include "media/filters/ffmpeg_common.h" 15 #include "media/filters/ffmpeg_common.h"
15 #include "media/filters/ffmpeg_demuxer.h" 16 #include "media/filters/ffmpeg_demuxer.h"
16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
17 18
18 namespace { 19 using ::testing::_;
19 20 using ::testing::DoAll;
20 // Simulates a queue of media packets that get "demuxed" when av_read_frame() 21 using ::testing::InSequence;
21 // is called. It also tracks the number of packets read but not released, 22 using ::testing::Return;
22 // which lets us test for memory leaks and handling seeks. 23 using ::testing::SetArgumentPointee;
23 class PacketQueue : public Singleton<PacketQueue> {
24 public:
25 bool IsEmpty() {
26 return packets_.empty();
27 }
28
29 void Enqueue(int stream, size_t size, uint8* data) {
30 packets_.push_back(PacketTuple(stream, size, data));
31 }
32
33 void Dequeue(AVPacket* packet) {
34 CHECK(!packets_.empty());
35 memset(packet, 0, sizeof(*packet));
36 packet->stream_index = packets_.front().a;
37 packet->size = packets_.front().b;
38 packet->data = packets_.front().c;
39 packet->destruct = &PacketQueue::DestructPacket;
40 packets_.pop_front();
41
42 // We now have an outstanding packet which must be freed at some point.
43 ++outstanding_packets_;
44 }
45
46 bool WaitForOutstandingPackets(int count) {
47 const base::TimeDelta kTimedWait = base::TimeDelta::FromMilliseconds(500);
48 while (outstanding_packets_ != count) {
49 if (!wait_for_outstanding_packets_.TimedWait(kTimedWait)) {
50 return false;
51 }
52 }
53 return true;
54 }
55
56 private:
57 static void DestructPacket(AVPacket* packet) {
58 PacketQueue::get()->DestructPacket();
59 }
60
61 void DestructPacket() {
62 --outstanding_packets_;
63 wait_for_outstanding_packets_.Signal();
64 }
65
66 // Only allow Singleton to create and delete PacketQueue.
67 friend struct DefaultSingletonTraits<PacketQueue>;
68
69 PacketQueue()
70 : outstanding_packets_(0),
71 wait_for_outstanding_packets_(false, false) {
72 }
73
74 ~PacketQueue() {
75 CHECK(outstanding_packets_ == 0);
76 }
77
78 // Packet queue for tests to enqueue mock packets, which are dequeued when
79 // FFmpegDemuxer calls av_read_frame().
80 typedef Tuple3<int, size_t, uint8*> PacketTuple;
81 std::deque<PacketTuple> packets_;
82
83 // Counts the number of packets "allocated" by av_read_frame() and "released"
84 // by av_free_packet(). This should always be zero after everything is
85 // cleaned up.
86 int outstanding_packets_;
87
88 // Tests can wait on this event until a specific number of outstanding packets
89 // have been reached. Used to ensure other threads release their references
90 // to objects so we don't get false positive test results when comparing the
91 // number of outstanding packets.
92 base::WaitableEvent wait_for_outstanding_packets_;
93
94 DISALLOW_COPY_AND_ASSIGN(PacketQueue);
95 };
96
97 } // namespace
98
99 // FFmpeg mocks to remove dependency on having the DLLs present.
100 extern "C" {
101 static const size_t kMaxStreams = 3;
102 static AVFormatContext g_format;
103 static AVStream g_streams[kMaxStreams];
104 static AVCodecContext g_audio_codec;
105 static AVCodecContext g_video_codec;
106 static AVCodecContext g_data_codec;
107
108 // FFmpeg return codes for various functions.
109 static int g_av_open_input_file = 0;
110 static int g_av_find_stream_info = 0;
111 static int g_av_read_frame = 0;
112 static int g_av_seek_frame = 0;
113
114 // Expected values when seeking.
115 static base::WaitableEvent* g_seek_event = NULL;
116 static int64_t g_expected_seek_timestamp = 0;
117 static int g_expected_seek_flags = 0;
118
119 // Counts outstanding packets allocated by av_new_frame().
120 static int g_outstanding_packets_av_new_frame = 0;
121
122 int av_open_input_file(AVFormatContext** format, const char* filename,
123 AVInputFormat* input_format, int buffer_size,
124 AVFormatParameters* parameters) {
125 EXPECT_FALSE(input_format) << "AVInputFormat should be NULL.";
126 EXPECT_FALSE(buffer_size) << "buffer_size should be 0.";
127 EXPECT_FALSE(parameters) << "AVFormatParameters should be NULL.";
128 if (g_av_open_input_file < 0) {
129 *format = NULL;
130 } else {
131 *format = &g_format;
132 }
133 return g_av_open_input_file;
134 }
135
136 int av_find_stream_info(AVFormatContext* format) {
137 EXPECT_EQ(&g_format, format);
138 return g_av_find_stream_info;
139 }
140
141 int64 av_rescale_q(int64 a, AVRational bq, AVRational cq) {
142 int64 num = bq.num * cq.den;
143 int64 den = cq.num * bq.den;
144 return a * num / den;
145 }
146
147 void av_free_packet(AVPacket* packet) {
148 if (packet->destruct) {
149 packet->destruct(packet);
150 packet->data = NULL;
151 packet->size = 0;
152 }
153 }
154
155 void DestructPacket(AVPacket* packet) {
156 delete [] packet->data;
157 --g_outstanding_packets_av_new_frame;
158 }
159
160 int av_new_packet(AVPacket* packet, int size) {
161 memset(packet, 0, sizeof(*packet));
162 packet->data = new uint8[size];
163 packet->size = size;
164 packet->destruct = &DestructPacket;
165 ++g_outstanding_packets_av_new_frame;
166 return 0;
167 }
168
169 void av_free(void* ptr) {
170 if (ptr) {
171 EXPECT_EQ(&g_format, ptr);
172 }
173 }
174
175 int av_read_frame(AVFormatContext* format, AVPacket* packet) {
176 EXPECT_EQ(&g_format, format);
177 if (g_av_read_frame == 0) {
178 PacketQueue::get()->Dequeue(packet);
179 }
180 return g_av_read_frame;
181 }
182
183 int av_seek_frame(AVFormatContext *format, int stream_index, int64_t timestamp,
184 int flags) {
185 EXPECT_EQ(&g_format, format);
186 EXPECT_EQ(-1, stream_index); // Should always use -1 for default stream.
187 EXPECT_EQ(g_expected_seek_timestamp, timestamp);
188 EXPECT_EQ(g_expected_seek_flags, flags);
189 EXPECT_FALSE(g_seek_event->IsSignaled());
190 g_seek_event->Signal();
191 return g_av_seek_frame;
192 }
193
194 } // extern "C"
195 24
196 namespace media { 25 namespace media {
197 26
198 // Fixture class to facilitate writing tests. Takes care of setting up the 27 // Fixture class to facilitate writing tests. Takes care of setting up the
199 // FFmpeg, pipeline and filter host mocks. 28 // FFmpeg, pipeline and filter host mocks.
200 class FFmpegDemuxerTest : public testing::Test { 29 class FFmpegDemuxerTest : public testing::Test {
201 protected: 30 protected:
202 FFmpegDemuxerTest() {} 31 // These constants refer to the stream ordering inside AVFormatContext. We
203 virtual ~FFmpegDemuxerTest() {} 32 // simulate media with a data stream, audio stream and video stream. Having
33 // the data stream first forces the audio and video streams to get remapped
34 // from indices {1,2} to {0,1} respectively, which covers an important test
35 // case.
36 enum AVStreamIndex {
37 AV_STREAM_DATA,
38 AV_STREAM_VIDEO,
39 AV_STREAM_AUDIO,
40 AV_STREAM_MAX,
41 };
204 42
205 virtual void SetUp() { 43 // These constants refer to the stream ordering inside an initialized
206 InitializeFFmpegMocks(); 44 // FFmpegDemuxer based on the ordering of the AVStreamIndex constants.
45 enum DemuxerStreamIndex {
46 DS_STREAM_VIDEO,
47 DS_STREAM_AUDIO,
48 DS_STREAM_MAX,
49 };
207 50
51 static const int kDurations[];
52 static const int kChannels;
53 static const int kSampleRate;
54 static const int kWidth;
55 static const int kHeight;
56
57 static const size_t kDataSize;
58 static const uint8 kAudioData[];
59 static const uint8 kVideoData[];
60 static const uint8* kNullData;
61
62 FFmpegDemuxerTest()
63 : wait_for_demuxer_(false, false) {
208 // Create an FFmpegDemuxer. 64 // Create an FFmpegDemuxer.
209 factory_ = FFmpegDemuxer::CreateFilterFactory(); 65 factory_ = FFmpegDemuxer::CreateFilterFactory();
210 MediaFormat media_format; 66 MediaFormat media_format;
211 media_format.SetAsString(MediaFormat::kMimeType, 67 media_format.SetAsString(MediaFormat::kMimeType,
212 mime_type::kApplicationOctetStream); 68 mime_type::kApplicationOctetStream);
213 demuxer_ = factory_->Create<Demuxer>(media_format); 69 demuxer_ = factory_->Create<FFmpegDemuxer>(media_format);
214 DCHECK(demuxer_); 70 DCHECK(demuxer_);
215 71
216 // Prepare a filter host and data source for the demuxer. 72 // Prepare a filter host and data source for the demuxer.
217 pipeline_.reset(new MockPipeline()); 73 pipeline_.reset(new MockPipeline());
218 filter_host_.reset(new MockFilterHost<Demuxer>(pipeline_.get(), demuxer_)); 74 filter_host_.reset(new MockFilterHost<Demuxer>(pipeline_.get(), demuxer_));
219 old_mocks::MockFilterConfig config; 75 old_mocks::MockFilterConfig config;
220 data_source_ = new old_mocks::MockDataSource(&config); 76 data_source_ = new old_mocks::MockDataSource(&config);
77
78 // Initialize FFmpeg fixtures.
79 memset(&format_context_, 0, sizeof(format_context_));
80 memset(&streams_, 0, sizeof(streams_));
81 memset(&codecs_, 0, sizeof(codecs_));
82
83 // Initialize AVCodexContext structures.
84 codecs_[AV_STREAM_DATA].codec_type = CODEC_TYPE_DATA;
85 codecs_[AV_STREAM_DATA].codec_id = CODEC_ID_NONE;
86
87 codecs_[AV_STREAM_VIDEO].codec_type = CODEC_TYPE_VIDEO;
88 codecs_[AV_STREAM_VIDEO].codec_id = CODEC_ID_THEORA;
89 codecs_[AV_STREAM_VIDEO].width = kWidth;
90 codecs_[AV_STREAM_VIDEO].height = kHeight;
91
92 codecs_[AV_STREAM_AUDIO].codec_type = CODEC_TYPE_AUDIO;
93 codecs_[AV_STREAM_AUDIO].codec_id = CODEC_ID_VORBIS;
94 codecs_[AV_STREAM_AUDIO].channels = kChannels;
95 codecs_[AV_STREAM_AUDIO].sample_rate = kSampleRate;
96
97 // Initialize AVStream and AVFormatContext structures. We set the time base
98 // of the streams such that duration is reported in microseconds.
99 format_context_.nb_streams = AV_STREAM_MAX;
100 for (size_t i = 0; i < AV_STREAM_MAX; ++i) {
101 format_context_.streams[i] = &streams_[i];
102 streams_[i].codec = &codecs_[i];
103 streams_[i].duration = kDurations[i];
104 streams_[i].time_base.den = 1 * base::Time::kMicrosecondsPerSecond;
105 streams_[i].time_base.num = 1;
106 }
107
108 // Initialize MockFFmpeg.
109 MockFFmpeg::set(&mock_ffmpeg_);
221 } 110 }
222 111
223 virtual void TearDown() { 112 virtual ~FFmpegDemuxerTest() {
224 // Call Stop() to shut down internal threads. 113 // Call Stop() to shut down internal threads.
225 demuxer_->Stop(); 114 demuxer_->Stop();
115
116 // Reset MockFFmpeg.
117 MockFFmpeg::set(NULL);
118 }
119
120 // Sets up MockFFmpeg to allow FFmpegDemuxer to successfully initialize.
121 void InitializeDemuxerMocks() {
122 EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL))
123 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0)));
124 EXPECT_CALL(*MockFFmpeg::get(), AVFindStreamInfo(&format_context_))
125 .WillOnce(Return(0));
126 EXPECT_CALL(*MockFFmpeg::get(), AVFree(&format_context_));
127 }
128
129 // Initializes both MockFFmpeg and FFmpegDemuxer.
130 void InitializeDemuxer() {
131 InitializeDemuxerMocks();
132 EXPECT_TRUE(demuxer_->Initialize(data_source_.get()));
133 EXPECT_TRUE(filter_host_->WaitForInitialized());
134 EXPECT_TRUE(filter_host_->IsInitialized());
135 EXPECT_EQ(PIPELINE_OK, pipeline_->GetError());
136 }
137
138 // To eliminate flakiness, this method will wait for the demuxer's message
139 // loop to finish any currently executing and queued tasks.
140 void WaitForDemuxerThread() {
141 demuxer_->thread_.message_loop()->PostTask(FROM_HERE,
142 NewRunnableFunction(&FFmpegDemuxerTest::Notify, &wait_for_demuxer_));
143 wait_for_demuxer_.Wait();
226 } 144 }
227 145
228 // Fixture members. 146 // Fixture members.
229 scoped_refptr<FilterFactory> factory_; 147 scoped_refptr<FilterFactory> factory_;
230 scoped_refptr<Demuxer> demuxer_; 148 scoped_refptr<FFmpegDemuxer> demuxer_;
231 scoped_ptr<MockPipeline> pipeline_; 149 scoped_ptr<MockPipeline> pipeline_;
232 scoped_ptr<MockFilterHost<Demuxer> > filter_host_; 150 scoped_ptr<MockFilterHost<Demuxer> > filter_host_;
233 scoped_refptr<old_mocks::MockDataSource> data_source_; 151 scoped_refptr<old_mocks::MockDataSource> data_source_;
234 152
153 // FFmpeg fixtures.
154 AVFormatContext format_context_;
155 AVCodecContext codecs_[AV_STREAM_MAX];
156 AVStream streams_[AV_STREAM_MAX];
157 MockFFmpeg mock_ffmpeg_;
158
235 private: 159 private:
236 static void InitializeFFmpegMocks() { 160 // Used with NewRunnableFunction() -- we don't use NewRunnableMethod() since
237 // Initialize function return codes. 161 // it would force this class to be refcounted causing double deletions.
238 g_av_open_input_file = 0; 162 static void Notify(base::WaitableEvent* event) {
239 g_av_find_stream_info = 0; 163 event->Signal();
240 g_av_read_frame = 0; 164 }
241 165
242 // Initialize AVFormatContext structure. 166 base::WaitableEvent wait_for_demuxer_;
243 memset(&g_format, 0, sizeof(g_format));
244
245 // Initialize AVStream structures.
246 for (size_t i = 0; i < kMaxStreams; ++i) {
247 memset(&g_streams[i], 0, sizeof(g_streams[i]));
248 g_streams[i].time_base.den = 1 * base::Time::kMicrosecondsPerSecond;
249 g_streams[i].time_base.num = 1;
250 }
251
252 // Initialize AVCodexContext structures.
253 memset(&g_audio_codec, 0, sizeof(g_audio_codec));
254 g_audio_codec.codec_type = CODEC_TYPE_AUDIO;
255 g_audio_codec.codec_id = CODEC_ID_VORBIS;
256 g_audio_codec.channels = 2;
257 g_audio_codec.sample_rate = 44100;
258
259 memset(&g_video_codec, 0, sizeof(g_video_codec));
260 g_video_codec.codec_type = CODEC_TYPE_VIDEO;
261 g_video_codec.codec_id = CODEC_ID_THEORA;
262 g_video_codec.height = 720;
263 g_video_codec.width = 1280;
264
265 memset(&g_data_codec, 0, sizeof(g_data_codec));
266 g_data_codec.codec_type = CODEC_TYPE_DATA;
267 g_data_codec.codec_id = CODEC_ID_NONE;
268 }
269 167
270 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); 168 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
271 }; 169 };
272 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
273 TEST(FFmpegDemuxerFactoryTest, Create) { 184 TEST(FFmpegDemuxerFactoryTest, Create) {
274 // Should only accept application/octet-stream type. 185 // Should only accept application/octet-stream type.
275 scoped_refptr<FilterFactory> factory = FFmpegDemuxer::CreateFilterFactory(); 186 scoped_refptr<FilterFactory> factory = FFmpegDemuxer::CreateFilterFactory();
276 MediaFormat media_format; 187 MediaFormat media_format;
277 media_format.SetAsString(MediaFormat::kMimeType, "foo/x-bar"); 188 media_format.SetAsString(MediaFormat::kMimeType, "foo/x-bar");
278 scoped_refptr<Demuxer> demuxer(factory->Create<Demuxer>(media_format)); 189 scoped_refptr<Demuxer> demuxer(factory->Create<Demuxer>(media_format));
279 ASSERT_FALSE(demuxer); 190 ASSERT_FALSE(demuxer);
280 191
281 // Try again with application/octet-stream mime type. 192 // Try again with application/octet-stream mime type.
282 media_format.Clear(); 193 media_format.Clear();
283 media_format.SetAsString(MediaFormat::kMimeType, 194 media_format.SetAsString(MediaFormat::kMimeType,
284 mime_type::kApplicationOctetStream); 195 mime_type::kApplicationOctetStream);
285 demuxer = factory->Create<Demuxer>(media_format); 196 demuxer = factory->Create<Demuxer>(media_format);
286 ASSERT_TRUE(demuxer); 197 ASSERT_TRUE(demuxer);
287 } 198 }
288 199
289 TEST_F(FFmpegDemuxerTest, InitializeCouldNotOpen) { 200 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
290 // Simulate av_open_input_fail failing. 201 // Simulate av_open_input_file() failing.
291 g_av_open_input_file = AVERROR_IO; 202 EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL))
292 g_av_find_stream_info = 0; 203 .WillOnce(Return(-1));
204
293 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); 205 EXPECT_TRUE(demuxer_->Initialize(data_source_.get()));
294 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_COULD_NOT_OPEN)); 206 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_COULD_NOT_OPEN));
295 EXPECT_FALSE(filter_host_->IsInitialized()); 207 EXPECT_FALSE(filter_host_->IsInitialized());
296 } 208 }
297 209
298 TEST_F(FFmpegDemuxerTest, InitializeCouldNotParse) { 210 TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
299 // Simulate av_find_stream_info failing. 211 // Simulate av_find_stream_info() failing.
300 g_av_open_input_file = 0; 212 EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL))
301 g_av_find_stream_info = AVERROR_IO; 213 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0)));
214 EXPECT_CALL(*MockFFmpeg::get(), AVFindStreamInfo(&format_context_))
215 .WillOnce(Return(AVERROR_IO));
216 EXPECT_CALL(*MockFFmpeg::get(), AVFree(&format_context_));
302 217
303 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); 218 EXPECT_TRUE(demuxer_->Initialize(data_source_.get()));
304 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_COULD_NOT_PARSE)); 219 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_COULD_NOT_PARSE));
305 EXPECT_FALSE(filter_host_->IsInitialized()); 220 EXPECT_FALSE(filter_host_->IsInitialized());
306 } 221 }
307 222
308 TEST_F(FFmpegDemuxerTest, InitializeNoStreams) { 223 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
309 // Simulate media with no parseable streams. 224 // Simulate media with no parseable streams.
310 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); 225 {
311 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); 226 SCOPED_TRACE("");
312 EXPECT_FALSE(filter_host_->IsInitialized()); 227 InitializeDemuxerMocks();
313 } 228 }
314 229 format_context_.nb_streams = 0;
315 TEST_F(FFmpegDemuxerTest, InitializeDataStreamOnly) {
316 // Simulate media with a data stream but no audio or video streams.
317 g_format.nb_streams = 1;
318 g_format.streams[0] = &g_streams[0];
319 g_streams[0].codec = &g_data_codec;
320 g_streams[0].duration = 10;
321 230
322 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); 231 EXPECT_TRUE(demuxer_->Initialize(data_source_.get()));
323 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); 232 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
324 EXPECT_FALSE(filter_host_->IsInitialized()); 233 EXPECT_FALSE(filter_host_->IsInitialized());
325 } 234 }
326 235
327 TEST_F(FFmpegDemuxerTest, InitializeStreams) { 236 TEST_F(FFmpegDemuxerTest, Initialize_DataStreamOnly) {
328 // Simulate media with a data stream, a video stream and audio stream. 237 // Simulate media with a data stream but no audio or video streams.
329 g_format.nb_streams = 3; 238 {
330 g_format.streams[0] = &g_streams[0]; 239 SCOPED_TRACE("");
331 g_format.streams[1] = &g_streams[1]; 240 InitializeDemuxerMocks();
332 g_format.streams[2] = &g_streams[2]; 241 }
333 g_streams[0].duration = 1000; 242 EXPECT_EQ(format_context_.streams[0], &streams_[AV_STREAM_DATA]);
334 g_streams[0].codec = &g_data_codec; 243 format_context_.nb_streams = 1;
335 g_streams[1].duration = 100;
336 g_streams[1].codec = &g_video_codec;
337 g_streams[2].duration = 10;
338 g_streams[2].codec = &g_audio_codec;
339 244
340 // Initialize the demuxer.
341 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); 245 EXPECT_TRUE(demuxer_->Initialize(data_source_.get()));
342 EXPECT_TRUE(filter_host_->WaitForInitialized()); 246 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
343 EXPECT_TRUE(filter_host_->IsInitialized()); 247 EXPECT_FALSE(filter_host_->IsInitialized());
344 EXPECT_EQ(PIPELINE_OK, pipeline_->GetError()); 248 }
345 249
346 // Since we ignore data streams, the duration should be equal to the video 250 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
347 // stream's duration. 251 {
348 EXPECT_EQ(g_streams[1].duration, pipeline_->GetDuration().InMicroseconds()); 252 SCOPED_TRACE("");
253 InitializeDemuxer();
254 }
349 255
350 // Verify that 2 out of 3 streams were created. 256 // Verify that our demuxer streams were created from our AVStream structures.
351 EXPECT_EQ(2u, demuxer_->GetNumberOfStreams()); 257 EXPECT_EQ(DS_STREAM_MAX, static_cast<int>(demuxer_->GetNumberOfStreams()));
352 258
353 // First stream should be video and support FFmpegDemuxerStream interface. 259 // Since we ignore data streams, the duration should be equal to the longest
354 scoped_refptr<DemuxerStream> stream = demuxer_->GetStream(0); 260 // supported stream's duration (audio, in this case).
261 EXPECT_EQ(kDurations[AV_STREAM_AUDIO],
262 pipeline_->GetDuration().InMicroseconds());
263
264 // First stream should be video and support the FFmpegDemuxerStream interface.
265 scoped_refptr<DemuxerStream> stream = demuxer_->GetStream(DS_STREAM_VIDEO);
355 AVStreamProvider* av_stream_provider = NULL; 266 AVStreamProvider* av_stream_provider = NULL;
356 ASSERT_TRUE(stream); 267 ASSERT_TRUE(stream);
357 std::string mime_type; 268 std::string mime_type;
358 EXPECT_TRUE( 269 EXPECT_TRUE(
359 stream->media_format().GetAsString(MediaFormat::kMimeType, &mime_type)); 270 stream->media_format().GetAsString(MediaFormat::kMimeType, &mime_type));
360 EXPECT_STREQ(mime_type::kFFmpegVideo, mime_type.c_str()); 271 EXPECT_STREQ(mime_type::kFFmpegVideo, mime_type.c_str());
361 EXPECT_TRUE(stream->QueryInterface(&av_stream_provider)); 272 EXPECT_TRUE(stream->QueryInterface(&av_stream_provider));
362 EXPECT_TRUE(av_stream_provider); 273 EXPECT_TRUE(av_stream_provider);
363 EXPECT_EQ(&g_streams[1], av_stream_provider->GetAVStream()); 274 EXPECT_EQ(&streams_[AV_STREAM_VIDEO], av_stream_provider->GetAVStream());
364 275
365 // Second stream should be audio and support FFmpegDemuxerStream interface. 276 // Other stream should be audio and support the FFmpegDemuxerStream interface.
366 stream = demuxer_->GetStream(1); 277 stream = demuxer_->GetStream(DS_STREAM_AUDIO);
367 av_stream_provider = NULL; 278 av_stream_provider = NULL;
368 ASSERT_TRUE(stream); 279 ASSERT_TRUE(stream);
369 EXPECT_TRUE(stream->media_format().GetAsString(MediaFormat::kMimeType, 280 EXPECT_TRUE(stream->media_format().GetAsString(MediaFormat::kMimeType,
370 &mime_type)); 281 &mime_type));
371 EXPECT_STREQ(mime_type::kFFmpegAudio, mime_type.c_str()); 282 EXPECT_STREQ(mime_type::kFFmpegAudio, mime_type.c_str());
372 EXPECT_TRUE(stream->QueryInterface(&av_stream_provider)); 283 EXPECT_TRUE(stream->QueryInterface(&av_stream_provider));
373 EXPECT_TRUE(av_stream_provider); 284 EXPECT_TRUE(av_stream_provider);
374 EXPECT_EQ(&g_streams[2], av_stream_provider->GetAVStream()); 285 EXPECT_EQ(&streams_[AV_STREAM_AUDIO], av_stream_provider->GetAVStream());
375 } 286 }
376 287
377 TEST_F(FFmpegDemuxerTest, ReadAndSeek) { 288 TEST_F(FFmpegDemuxerTest, Read) {
378 // Prepare some test data. 289 // We're testing the following:
379 const int kPacketData = 0; 290 //
380 const int kPacketAudio = 1; 291 // 1) The demuxer immediately frees packets it doesn't care about and keeps
381 const int kPacketVideo = 2; 292 // reading until it finds a packet it cares about.
382 const int kAudio = 0; 293 // 2) The demuxer doesn't free packets that we read from it.
383 const int kVideo = 1; 294 // 3) On end of stream, the demuxer queues end of stream packets on every
384 const size_t kDataSize = 4; 295 // stream.
385 uint8 audio_data[kDataSize] = {0, 1, 2, 3}; 296 //
386 uint8 video_data[kDataSize] = {4, 5, 6, 7}; 297 // Since we can't test which packets are being freed, we use check points to
387 298 // infer that the correct packets have been freed.
388 // Simulate media with a data stream, audio stream and video stream. Having 299 {
389 // the data stream first forces the audio and video streams to get remapped 300 SCOPED_TRACE("");
390 // from indices {1,2} to {0,1} respectively, which covers an important test 301 InitializeDemuxer();
391 // case. 302 }
392 g_format.nb_streams = 3;
393 g_format.streams[kPacketData] = &g_streams[0];
394 g_format.streams[kPacketAudio] = &g_streams[1];
395 g_format.streams[kPacketVideo] = &g_streams[2];
396 g_streams[0].duration = 10;
397 g_streams[0].codec = &g_data_codec;
398 g_streams[1].duration = 10;
399 g_streams[1].codec = &g_audio_codec;
400 g_streams[2].duration = 10;
401 g_streams[2].codec = &g_video_codec;
402
403 // Initialize the demuxer.
404 EXPECT_TRUE(demuxer_->Initialize(data_source_.get()));
405 EXPECT_TRUE(filter_host_->WaitForInitialized());
406 EXPECT_TRUE(filter_host_->IsInitialized());
407 EXPECT_EQ(PIPELINE_OK, pipeline_->GetError());
408
409 // Verify both streams were created.
410 EXPECT_EQ(2u, demuxer_->GetNumberOfStreams());
411 303
412 // Get our streams. 304 // Get our streams.
413 scoped_refptr<DemuxerStream> audio_stream = demuxer_->GetStream(kAudio); 305 scoped_refptr<DemuxerStream> video = demuxer_->GetStream(DS_STREAM_VIDEO);
414 scoped_refptr<DemuxerStream> video_stream = demuxer_->GetStream(kVideo); 306 scoped_refptr<DemuxerStream> audio = demuxer_->GetStream(DS_STREAM_AUDIO);
415 ASSERT_TRUE(audio_stream); 307 ASSERT_TRUE(video);
416 ASSERT_TRUE(video_stream); 308 ASSERT_TRUE(audio);
417 309
418 // Prepare data packets, which should all get immediately released. 310 // Expect all calls in sequence.
419 PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); 311 InSequence s;
420 PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); 312
421 PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); 313 // The demuxer will read a data packet which will get immediately freed,
422 314 // followed by reading an audio packet...
423 // Prepare our test audio packet. 315 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
424 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); 316 .WillOnce(CreatePacket(AV_STREAM_DATA, kNullData, 0));
317 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
318 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
319 .WillOnce(CreatePacket(AV_STREAM_AUDIO, kAudioData, kDataSize));
320
321 // ...then we'll free it with some sanity checkpoints...
322 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(1));
323 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
324 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(2));
325
326 // ...then we'll read a video packet...
327 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
328 .WillOnce(CreatePacket(AV_STREAM_VIDEO, kVideoData, kDataSize));
329
330 // ...then we'll free it with some sanity checkpoints...
331 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(3));
332 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
333 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(4));
334
335 // ...then we'll simulate end of stream. Note that a packet isn't "created"
336 // in this situation so there is no outstanding packet. However an end of
337 // stream packet is created for each stream, which means av_free_packet()
338 // will still be called twice.
339 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
340 .WillOnce(Return(AVERROR_IO));
341 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_));
342 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(5));
343 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_));
344 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(6));
425 345
426 // Attempt a read from the audio stream and run the message loop until done. 346 // Attempt a read from the audio stream and run the message loop until done.
427 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); 347 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
428 reader->Read(audio_stream); 348 reader->Read(audio);
429 pipeline_->RunAllTasks(); 349 pipeline_->RunAllTasks();
430 EXPECT_TRUE(reader->WaitForRead()); 350 EXPECT_TRUE(reader->WaitForRead());
431 EXPECT_TRUE(reader->called()); 351 EXPECT_TRUE(reader->called());
432 ASSERT_TRUE(reader->buffer()); 352 ASSERT_TRUE(reader->buffer());
433 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); 353 EXPECT_FALSE(reader->buffer()->IsDiscontinuous());
434 EXPECT_EQ(audio_data, reader->buffer()->GetData()); 354 EXPECT_EQ(kAudioData, reader->buffer()->GetData());
435 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); 355 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize());
436 356
437 // Prepare our test video packet. 357 // We shouldn't have freed the audio packet yet.
438 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); 358 MockFFmpeg::get()->CheckPoint(1);
359
360 // Manually release the last reference to the buffer.
361 reader->Reset();
362 WaitForDemuxerThread();
363 MockFFmpeg::get()->CheckPoint(2);
439 364
440 // Attempt a read from the video stream and run the message loop until done. 365 // Attempt a read from the video stream and run the message loop until done.
441 reader->Reset(); 366 reader->Read(video);
442 reader->Read(video_stream); 367 pipeline_->RunAllTasks();
443 pipeline_->RunAllTasks(); 368 EXPECT_TRUE(reader->WaitForRead());
444 EXPECT_TRUE(reader->WaitForRead()); 369 EXPECT_TRUE(reader->called());
445 EXPECT_TRUE(reader->called()); 370 ASSERT_TRUE(reader->buffer());
446 ASSERT_TRUE(reader->buffer()); 371 EXPECT_FALSE(reader->buffer()->IsDiscontinuous());
447 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); 372 EXPECT_EQ(kVideoData, reader->buffer()->GetData());
448 EXPECT_EQ(video_data, reader->buffer()->GetData()); 373 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize());
449 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); 374
375 // We shouldn't have freed the video packet yet.
376 MockFFmpeg::get()->CheckPoint(3);
377
378 // Manually release the last reference to the buffer and verify it was freed.
379 reader->Reset();
380 WaitForDemuxerThread();
381 MockFFmpeg::get()->CheckPoint(4);
382
383 // We should now expect an end of stream buffer in both the audio and video
384 // streams.
385
386 // Attempt a read from the audio stream and run the message loop until done.
387 reader->Read(audio);
388 pipeline_->RunAllTasks();
389 EXPECT_TRUE(reader->WaitForRead());
390 EXPECT_TRUE(reader->called());
391 ASSERT_TRUE(reader->buffer());
392 EXPECT_TRUE(reader->buffer()->IsEndOfStream());
393 EXPECT_EQ(NULL, reader->buffer()->GetData());
394 EXPECT_EQ(0u, reader->buffer()->GetDataSize());
450 395
451 // Manually release buffer, which should release any remaining AVPackets. 396 // Manually release buffer, which should release any remaining AVPackets.
452 reader = NULL; 397 reader->Reset();
453 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); 398 WaitForDemuxerThread();
454 399 MockFFmpeg::get()->CheckPoint(5);
455 //---------------------------------------------------------------------------- 400
456 // Seek tests. 401 // Attempt a read from the audio stream and run the message loop until done.
457 EXPECT_FALSE(g_seek_event); 402 reader->Read(video);
458 g_seek_event = new base::WaitableEvent(false, false); 403 pipeline_->RunAllTasks();
459 404 EXPECT_TRUE(reader->WaitForRead());
460 // Let's trigger a simple forward seek with no outstanding packets. 405 EXPECT_TRUE(reader->called());
461 g_expected_seek_timestamp = 1234; 406 ASSERT_TRUE(reader->buffer());
462 g_expected_seek_flags = 0; 407 EXPECT_TRUE(reader->buffer()->IsEndOfStream());
463 demuxer_->Seek(base::TimeDelta::FromMicroseconds(g_expected_seek_timestamp)); 408 EXPECT_EQ(NULL, reader->buffer()->GetData());
464 EXPECT_TRUE(g_seek_event->TimedWait(base::TimeDelta::FromSeconds(1))); 409 EXPECT_EQ(0u, reader->buffer()->GetDataSize());
410
411 // Manually release buffer, which should release any remaining AVPackets.
412 reader->Reset();
413 WaitForDemuxerThread();
414 MockFFmpeg::get()->CheckPoint(6);
415 }
416
417 TEST_F(FFmpegDemuxerTest, Seek) {
418 // We're testing the following:
419 //
420 // 1) The demuxer frees all queued packets when it receives a Seek().
421 // 2) The demuxer queues a single discontinuous packet on every stream.
422 //
423 // Since we can't test which packets are being freed, we use check points to
424 // infer that the correct packets have been freed.
425 {
426 SCOPED_TRACE("");
427 InitializeDemuxer();
428 }
429
430 // Get our streams.
431 scoped_refptr<DemuxerStream> video = demuxer_->GetStream(DS_STREAM_VIDEO);
432 scoped_refptr<DemuxerStream> audio = demuxer_->GetStream(DS_STREAM_AUDIO);
433 ASSERT_TRUE(video);
434 ASSERT_TRUE(audio);
435
436 // Expected values.
437 const int64 kExpectedTimestamp = 1234;
438 const int64 kExpectedFlags = 0;
439
440 // Expect all calls in sequence.
441 InSequence s;
442
443 // First we'll read a video packet that causes two audio packets to be queued
444 // inside FFmpegDemuxer...
445 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
446 .WillOnce(CreatePacket(AV_STREAM_AUDIO, kAudioData, kDataSize));
447 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
448 .WillOnce(CreatePacket(AV_STREAM_AUDIO, kAudioData, kDataSize));
449 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
450 .WillOnce(CreatePacket(AV_STREAM_VIDEO, kVideoData, kDataSize));
451
452 // ...then we'll release our video packet...
453 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
454 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(1));
455
456 // ...then we'll seek, which should release the previously queued packets...
457 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
458 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
459
460 // ...then we'll expect the actual seek call...
461 EXPECT_CALL(*MockFFmpeg::get(),
462 AVSeekFrame(&format_context_, -1, kExpectedTimestamp, kExpectedFlags))
463 .WillOnce(Return(0));
464 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(2));
465
466 // ...followed by two audio packet reads we'll trigger...
467 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
468 .WillOnce(CreatePacket(AV_STREAM_AUDIO, kAudioData, kDataSize));
469 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
470 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
471 .WillOnce(CreatePacket(AV_STREAM_AUDIO, kAudioData, kDataSize));
472 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
473
474 // ...followed by two video packet reads...
475 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
476 .WillOnce(CreatePacket(AV_STREAM_VIDEO, kVideoData, kDataSize));
477 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
478 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
479 .WillOnce(CreatePacket(AV_STREAM_VIDEO, kVideoData, kDataSize));
480 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
481
482 // ...and finally a sanity checkpoint to make sure everything was released.
483 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(3));
484
485 // Read a video packet and release it.
486 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
487 reader->Read(video);
488 pipeline_->RunAllTasks();
489 EXPECT_TRUE(reader->WaitForRead());
490 EXPECT_TRUE(reader->called());
491 ASSERT_TRUE(reader->buffer());
492 EXPECT_FALSE(reader->buffer()->IsDiscontinuous());
493 EXPECT_EQ(kVideoData, reader->buffer()->GetData());
494 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize());
495
496 // Release the video packet and verify the other packets are still queued.
497 reader->Reset();
498 WaitForDemuxerThread();
499 MockFFmpeg::get()->CheckPoint(1);
500
501 // Now issue a simple forward seek, which should discard queued packets.
502 demuxer_->Seek(base::TimeDelta::FromMicroseconds(kExpectedTimestamp));
503 WaitForDemuxerThread();
504 MockFFmpeg::get()->CheckPoint(2);
465 505
466 // The next read from each stream should now be discontinuous, but subsequent 506 // The next read from each stream should now be discontinuous, but subsequent
467 // reads should not. 507 // reads should not.
468 508
469 // Prepare our test audio packet.
470 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data);
471 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data);
472
473 // Audio read #1, should be discontinuous. 509 // Audio read #1, should be discontinuous.
474 reader = new DemuxerStreamReader(); 510 reader->Read(audio);
475 reader->Read(audio_stream);
476 pipeline_->RunAllTasks(); 511 pipeline_->RunAllTasks();
477 EXPECT_TRUE(reader->WaitForRead()); 512 EXPECT_TRUE(reader->WaitForRead());
478 EXPECT_TRUE(reader->called()); 513 EXPECT_TRUE(reader->called());
479 ASSERT_TRUE(reader->buffer()); 514 ASSERT_TRUE(reader->buffer());
480 EXPECT_TRUE(reader->buffer()->IsDiscontinuous()); 515 EXPECT_TRUE(reader->buffer()->IsDiscontinuous());
481 EXPECT_EQ(audio_data, reader->buffer()->GetData()); 516 EXPECT_EQ(kAudioData, reader->buffer()->GetData());
482 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); 517 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize());
483 518
484 // Audio read #2, should not be discontinuous. 519 // Audio read #2, should not be discontinuous.
485 reader->Reset(); 520 reader->Reset();
486 reader->Read(audio_stream); 521 reader->Read(audio);
487 pipeline_->RunAllTasks(); 522 pipeline_->RunAllTasks();
488 EXPECT_TRUE(reader->WaitForRead()); 523 EXPECT_TRUE(reader->WaitForRead());
489 EXPECT_TRUE(reader->called()); 524 EXPECT_TRUE(reader->called());
490 ASSERT_TRUE(reader->buffer()); 525 ASSERT_TRUE(reader->buffer());
491 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); 526 EXPECT_FALSE(reader->buffer()->IsDiscontinuous());
492 EXPECT_EQ(audio_data, reader->buffer()->GetData()); 527 EXPECT_EQ(kAudioData, reader->buffer()->GetData());
493 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); 528 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize());
494
495 // Prepare our test video packet.
496 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data);
497 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data);
498 529
499 // Video read #1, should be discontinuous. 530 // Video read #1, should be discontinuous.
500 reader->Reset(); 531 reader->Reset();
501 reader->Read(video_stream); 532 reader->Read(video);
502 pipeline_->RunAllTasks(); 533 pipeline_->RunAllTasks();
503 EXPECT_TRUE(reader->WaitForRead()); 534 EXPECT_TRUE(reader->WaitForRead());
504 EXPECT_TRUE(reader->called()); 535 EXPECT_TRUE(reader->called());
505 ASSERT_TRUE(reader->buffer()); 536 ASSERT_TRUE(reader->buffer());
506 EXPECT_TRUE(reader->buffer()->IsDiscontinuous()); 537 EXPECT_TRUE(reader->buffer()->IsDiscontinuous());
507 EXPECT_EQ(video_data, reader->buffer()->GetData()); 538 EXPECT_EQ(kVideoData, reader->buffer()->GetData());
508 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); 539 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize());
509 540
510 // Video read #2, should not be discontinuous. 541 // Video read #2, should not be discontinuous.
511 reader->Reset(); 542 reader->Reset();
512 reader->Read(video_stream); 543 reader->Read(video);
513 pipeline_->RunAllTasks(); 544 pipeline_->RunAllTasks();
514 EXPECT_TRUE(reader->WaitForRead()); 545 EXPECT_TRUE(reader->WaitForRead());
515 EXPECT_TRUE(reader->called()); 546 EXPECT_TRUE(reader->called());
516 ASSERT_TRUE(reader->buffer()); 547 ASSERT_TRUE(reader->buffer());
517 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); 548 EXPECT_FALSE(reader->buffer()->IsDiscontinuous());
518 EXPECT_EQ(video_data, reader->buffer()->GetData()); 549 EXPECT_EQ(kVideoData, reader->buffer()->GetData());
519 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); 550 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize());
520 551
521 // Manually release buffer, which should release any remaining AVPackets. 552 // Manually release the last reference to the buffer and verify it was freed.
522 reader = NULL; 553 reader->Reset();
523 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); 554 WaitForDemuxerThread();
524 555 MockFFmpeg::get()->CheckPoint(3);
525 // Let's trigger another simple forward seek, but with outstanding packets.
526 // The outstanding packets should get freed after the Seek() is issued.
527 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data);
528 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data);
529 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data);
530 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data);
531
532 // Attempt a read from video stream, which will force the demuxer to queue
533 // the audio packets preceding the video packet.
534 reader = new DemuxerStreamReader();
535 reader->Read(video_stream);
536 pipeline_->RunAllTasks();
537 EXPECT_TRUE(reader->WaitForRead());
538 EXPECT_TRUE(reader->called());
539 ASSERT_TRUE(reader->buffer());
540 EXPECT_FALSE(reader->buffer()->IsDiscontinuous());
541 EXPECT_EQ(video_data, reader->buffer()->GetData());
542 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize());
543
544 // Manually release video buffer, remaining audio packets are outstanding.
545 reader = NULL;
546 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(3));
547
548 // Trigger the seek.
549 g_expected_seek_timestamp = 1234;
550 g_expected_seek_flags = 0;
551 demuxer_->Seek(base::TimeDelta::FromMicroseconds(g_expected_seek_timestamp));
552 EXPECT_TRUE(g_seek_event->TimedWait(base::TimeDelta::FromSeconds(1)));
553
554 // All outstanding packets should have been freed.
555 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0));
556
557 // Clean up.
558 delete g_seek_event;
559 g_seek_event = NULL;
560
561 //----------------------------------------------------------------------------
562 // End of stream tests.
563
564 // Simulate end of stream.
565 g_av_read_frame = AVERROR_IO;
566
567 // Attempt a read from the audio stream and run the message loop until done.
568 reader = new DemuxerStreamReader();
569 reader->Read(audio_stream);
570 pipeline_->RunAllTasks();
571 EXPECT_TRUE(reader->WaitForRead());
572 EXPECT_TRUE(reader->called());
573 ASSERT_TRUE(reader->buffer());
574 EXPECT_TRUE(reader->buffer()->IsEndOfStream());
575
576 // Manually release buffer, which should release any remaining AVPackets.
577 reader = NULL;
578 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0));
579 } 556 }
580 557
581 // This tests our deep-copying workaround for FFmpeg's MP3 demuxer. When we fix 558 TEST_F(FFmpegDemuxerTest, MP3Hack) {
582 // the root cause this test will fail and should be removed. 559 // This tests our deep-copying workaround for FFmpeg's MP3 demuxer. When we
583 // 560 // fix the root cause this test will fail and should be removed.
584 // TODO(scherkus): disabled due to flakiness http://crbug.com/13933 561 //
585 TEST_F(FFmpegDemuxerTest, DISABLED_MP3Hack) { 562 // TODO(scherkus): according to the documentation, deep-copying the packet is
586 // Prepare some test data. 563 // actually the correct action -- remove this test when we fix our demuxer.
587 const int kPacketAudio = 0; // Stream index relative to the container. 564
588 const int kAudio = 0; // Stream index relative to Demuxer::GetStream(). 565 // Simulate an MP3 stream.
589 const size_t kDataSize = 4; 566 codecs_[AV_STREAM_AUDIO].codec_id = CODEC_ID_MP3;
590 uint8 audio_data[kDataSize] = {0, 1, 2, 3}; 567 {
591 568 SCOPED_TRACE("");
592 // Simulate media with a single MP3 audio stream. 569 InitializeDemuxer();
593 g_format.nb_streams = 1; 570 }
594 g_format.streams[kPacketAudio] = &g_streams[0]; 571
595 g_streams[0].duration = 10; 572 // Get our stream.
596 g_streams[0].codec = &g_audio_codec; 573 scoped_refptr<DemuxerStream> audio = demuxer_->GetStream(DS_STREAM_AUDIO);
597 g_audio_codec.codec_id = CODEC_ID_MP3; 574 ASSERT_TRUE(audio);
598 575
599 // Initialize the demuxer. 576 // Expect all calls in sequence.
600 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); 577 InSequence s;
601 EXPECT_TRUE(filter_host_->WaitForInitialized()); 578
602 EXPECT_TRUE(filter_host_->IsInitialized()); 579 // We'll read an MP3 packet and allocate a new packet, then instantly free
603 EXPECT_EQ(PIPELINE_OK, pipeline_->GetError()); 580 // the original packet due to deep copying...
604 581 EXPECT_CALL(*MockFFmpeg::get(), AVReadFrame(&format_context_, _))
605 // Verify the stream was created. 582 .WillOnce(CreatePacket(AV_STREAM_AUDIO, kAudioData, kDataSize));
606 EXPECT_EQ(1u, demuxer_->GetNumberOfStreams()); 583 EXPECT_CALL(*MockFFmpeg::get(), AVNewPacket(_, _)).WillOnce(NewPacket());
607 scoped_refptr<DemuxerStream> audio_stream = demuxer_->GetStream(kAudio); 584 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
608 ASSERT_TRUE(audio_stream); 585
609 586 // ...then we'll have a sanity checkpoint...
610 // Prepare our test audio packet. 587 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(1));
611 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); 588
589 // ...then we'll free the deep copied packet.
590 EXPECT_CALL(*MockFFmpeg::get(), AVFreePacket(_)).WillOnce(FreePacket());
591 EXPECT_CALL(*MockFFmpeg::get(), CheckPoint(2));
612 592
613 // Audio read should perform a deep copy on the packet and instantly release 593 // Audio read should perform a deep copy on the packet and instantly release
614 // the original packet. The data pointers should not be the same, but the 594 // the original packet. The data pointers should not be the same, but the
615 // contents should match. 595 // contents should match.
616 scoped_refptr<DemuxerStreamReader> reader = new DemuxerStreamReader(); 596 scoped_refptr<DemuxerStreamReader> reader = new DemuxerStreamReader();
617 reader->Read(audio_stream); 597 reader->Read(audio);
618 pipeline_->RunAllTasks(); 598 pipeline_->RunAllTasks();
619 EXPECT_TRUE(reader->WaitForRead()); 599 EXPECT_TRUE(reader->WaitForRead());
620 EXPECT_TRUE(reader->called()); 600 EXPECT_TRUE(reader->called());
621 ASSERT_TRUE(reader->buffer()); 601 ASSERT_TRUE(reader->buffer());
622 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); 602 EXPECT_FALSE(reader->buffer()->IsDiscontinuous());
623 EXPECT_NE(audio_data, reader->buffer()->GetData()); 603 EXPECT_NE(kAudioData, reader->buffer()->GetData());
624 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); 604 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize());
625 EXPECT_EQ(0, memcmp(audio_data, reader->buffer()->GetData(), kDataSize)); 605 EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(), kDataSize));
626 606
627 // Original AVPacket from the queue should have been released due to copying. 607 // We shouldn't have freed the MP3 packet yet.
628 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); 608 MockFFmpeg::get()->CheckPoint(1);
629 EXPECT_EQ(1, g_outstanding_packets_av_new_frame); 609
630 610 // Manually release the last reference to the buffer and verify it was freed.
631 // Now release our reference, which should destruct the packet allocated by 611 reader->Reset();
632 // av_new_packet(). 612 WaitForDemuxerThread();
633 reader = NULL; 613 MockFFmpeg::get()->CheckPoint(2);
634 EXPECT_EQ(0, g_outstanding_packets_av_new_frame);
635 } 614 }
636 615
637 } // namespace media 616 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_demuxer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698