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

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

Issue 10969028: Add video decoding methods in Decryptor and add DecryptingVideoDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: resolve comments Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <string>
6 #include <vector>
7
8 #include "base/bind.h"
9 #include "base/callback_helpers.h"
10 #include "base/message_loop.h"
11 #include "media/base/decoder_buffer.h"
12 #include "media/base/decrypt_config.h"
13 #include "media/base/mock_callback.h"
14 #include "media/base/mock_filters.h"
15 #include "media/base/video_frame.h"
16 #include "media/filters/ffmpeg_decoder_unittest.h"
17 #include "media/filters/decrypting_video_decoder.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19
20 using ::testing::_;
21 using ::testing::Invoke;
22 using ::testing::IsNull;
23 using ::testing::ReturnRef;
24 using ::testing::SaveArg;
25 using ::testing::StrictMock;
26
27 namespace media {
28
29 static const VideoFrame::Format kVideoFormat = VideoFrame::YV12;
30 static const gfx::Size kCodedSize(320, 240);
31 static const gfx::Rect kVisibleRect(320, 240);
32 static const gfx::Size kNaturalSize(320, 240);
33 static const uint8 kFakeKeyId[] = { 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44 };
34 static const uint8 kFakeIv[DecryptConfig::kDecryptionKeySize] = { 0 };
35
36 // Create a fake non-empty encrypted buffer.
37 static scoped_refptr<DecoderBuffer> CreateFakeEncryptedBuffer() {
38 const int buffer_size = 16; // Need a non-empty buffer;
39 const int encrypted_frame_offset = 1; // This should be non-zero.
ddorwin 2012/10/01 18:43:20 Why should this be non-zero? (That was my original
xhwang 2012/10/01 20:09:26 I think this was required before but it seems not
40 scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(buffer_size));
41 buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig(
42 std::string(reinterpret_cast<const char*>(kFakeKeyId),
43 arraysize(kFakeKeyId)),
44 std::string(reinterpret_cast<const char*>(kFakeIv), arraysize(kFakeIv)),
45 encrypted_frame_offset,
46 std::vector<SubsampleEntry>())));
47 return buffer;
48 }
49
50 ACTION_P(ReturnBuffer, buffer) {
51 arg0.Run(buffer ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer);
52 }
53
54 ACTION(ReturnConfigChanged) {
55 arg0.Run(DemuxerStream::kConfigChanged, scoped_refptr<DecoderBuffer>(NULL));
56 }
57
58 ACTION_P(RunCallback1, param) {
59 arg1.Run(param);
60 }
61
62 ACTION_P2(RunCallback2, param1, param2) {
63 arg1.Run(param1, param2);
64 }
65
66 class DecryptingVideoDecoderTest : public testing::Test {
67 public:
68 DecryptingVideoDecoderTest()
69 : decryptor_(new StrictMock<MockDecryptor>()),
70 decoder_(new StrictMock<DecryptingVideoDecoder>(
71 base::Bind(&Identity<scoped_refptr<base::MessageLoopProxy> >,
72 message_loop_.message_loop_proxy()),
73 decryptor_.get())),
74 demuxer_(new StrictMock<MockDemuxerStream>()),
75 encrypted_buffer_(CreateFakeEncryptedBuffer()),
76 decoded_video_frame_(VideoFrame::CreateBlackFrame(kCodedSize)) {
77 }
78
79 virtual ~DecryptingVideoDecoderTest() {
80 Stop();
81 }
82
xhwang 2012/09/30 19:58:51 Will reorder these functions, but in a later patch
ddorwin 2012/10/01 18:43:20 Thank you!
xhwang 2012/10/04 16:38:33 Done.
83 void Initialize() {
84 EXPECT_CALL(*decryptor_, InitializeVideoDecoder(_, _))
85 .WillOnce(RunCallback1(true));
86
87 config_.Initialize(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, kVideoFormat,
88 kCodedSize, kVisibleRect, kNaturalSize,
89 NULL, 0, true, true);
90
91 InitializeAndExpectStatus(config_, PIPELINE_OK);
92 }
93
94 void InitializeAndExpectStatus(const VideoDecoderConfig& config,
95 PipelineStatus status) {
96 EXPECT_CALL(*demuxer_, video_decoder_config())
97 .WillRepeatedly(ReturnRef(config));
98
99 decoder_->Initialize(demuxer_, NewExpectedStatusCB(status),
100 base::Bind(&MockStatisticsCB::OnStatistics,
101 base::Unretained(&statistics_cb_)));
102 message_loop_.RunAllPending();
103 }
104
105 void AbortPendingVideoDecodeCB() {
106 if (!pending_video_decode_cb_.is_null()) {
107 base::ResetAndReturn(&pending_video_decode_cb_).Run(
108 Decryptor::kSuccess, scoped_refptr<VideoFrame>(NULL));
109 }
110 }
111
112 void AbortAllPendingCBs() {
113 if (!pending_init_cb_.is_null()) {
114 ASSERT_TRUE(pending_video_decode_cb_.is_null());
115 base::ResetAndReturn(&pending_init_cb_).Run(false);
116 return;
117 }
118
119 AbortPendingVideoDecodeCB();
120 }
121
122 void Reset() {
123 EXPECT_CALL(*decryptor_, CancelDecryptAndDecodeVideo())
124 .WillOnce(Invoke(
125 this, &DecryptingVideoDecoderTest::AbortPendingVideoDecodeCB));
126
127 decoder_->Reset(NewExpectedClosure());
128 message_loop_.RunAllPending();
129 }
130
131 void Stop() {
132 EXPECT_CALL(*decryptor_, StopVideoDecoder())
133 .WillOnce(Invoke(
134 this, &DecryptingVideoDecoderTest::AbortAllPendingCBs));
135
136 decoder_->Stop(NewExpectedClosure());
137 message_loop_.RunAllPending();
138 }
139
140 // Sets up expectations and actions to put DecryptingVideoDecoder in an
141 // active normal decoding state.
142 void EnterNormalDecodingState() {
143 VideoDecoder::Status status = VideoDecoder::kDecodeError;
144 scoped_refptr<VideoFrame> video_frame;
145 DecryptAndDecodeSingleFrame(encrypted_buffer_, &status, &video_frame);
146
147 EXPECT_EQ(VideoDecoder::kOk, status);
148 ASSERT_TRUE(video_frame);
149 EXPECT_FALSE(video_frame->IsEndOfStream());
150 }
151
152 // Sets up expectations and actions to put DecryptingVideoDecoder in an end
153 // of stream state.
154 void EnterEndOfStreamState() {
155 scoped_refptr<VideoFrame> video_frame;
156 VideoDecoder::Status status = VideoDecoder::kDecodeError;
157 ReadAndExpectToCompleteWith(&status, &video_frame);
158
159 EXPECT_EQ(VideoDecoder::kOk, status);
160 ASSERT_TRUE(video_frame);
161 EXPECT_TRUE(video_frame->IsEndOfStream());
162 }
163
164 // Decodes the single compressed frame in |buffer| and writes the
165 // uncompressed output to |video_frame|. This method works with single
166 // and multithreaded decoders. End of stream buffers are used to trigger
167 // the frame to be returned in the multithreaded decoder case.
168 void DecryptAndDecodeSingleFrame(const scoped_refptr<DecoderBuffer>& buffer,
169 VideoDecoder::Status* status,
170 scoped_refptr<VideoFrame>* video_frame) {
171 EXPECT_CALL(*demuxer_, Read(_))
172 .WillOnce(ReturnBuffer(buffer))
173 .WillRepeatedly(ReturnBuffer(DecoderBuffer::CreateEOSBuffer()));
174 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
175 .WillOnce(RunCallback2(Decryptor::kSuccess, decoded_video_frame_))
176 .WillRepeatedly(RunCallback2(Decryptor::kSuccess,
177 VideoFrame::CreateEmptyFrame()));
178 EXPECT_CALL(statistics_cb_, OnStatistics(_));
179
180 ReadAndExpectToCompleteWith(status, video_frame);
181 }
182
183 void ReadAndExpectToCompleteWith(VideoDecoder::Status* status,
ddorwin 2012/10/01 18:43:20 ReadAndExpectToCompleteWithStatus
xhwang 2012/10/01 20:09:26 Changed to ReadAndExpectFrameReadyWithStatusAndFra
184 scoped_refptr<VideoFrame>* video_frame) {
185 EXPECT_CALL(*this, FrameReady(_, _))
186 .WillOnce(DoAll(SaveArg<0>(status), SaveArg<1>(video_frame)));
187
188 decoder_->Read(base::Bind(&DecryptingVideoDecoderTest::FrameReady,
189 base::Unretained(this)));
190 message_loop_.RunAllPending();
191 }
192
193 // Make the read callback pending by saving and not firing it.
194 void EnterPendingReadState() {
195 EXPECT_TRUE(pending_demuxer_read_cb_.is_null());
196 EXPECT_CALL(*demuxer_, Read(_))
197 .WillOnce(SaveArg<0>(&pending_demuxer_read_cb_));
198 decoder_->Read(base::Bind(&DecryptingVideoDecoderTest::FrameReady,
199 base::Unretained(this)));
200 message_loop_.RunAllPending();
201 // Make sure the Read() on the decoder triggers a Read() on the demuxer.
202 EXPECT_FALSE(pending_demuxer_read_cb_.is_null());
203 }
204
205 // Make the video decode callback pending by saving and not firing it.
206 void EnterPendingDecryptAndDecodeState() {
207 EXPECT_TRUE(pending_video_decode_cb_.is_null());
208 EXPECT_CALL(*demuxer_, Read(_))
209 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
210 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(encrypted_buffer_, _))
211 .WillOnce(SaveArg<1>(&pending_video_decode_cb_));
212
213 decoder_->Read(base::Bind(&DecryptingVideoDecoderTest::FrameReady,
214 base::Unretained(this)));
215 message_loop_.RunAllPending();
216 // Make sure the Read() on the decoder triggers a DecryptAndDecode() on the
217 // decryptor.
218 EXPECT_FALSE(pending_video_decode_cb_.is_null());
219 }
220
221 MOCK_METHOD2(FrameReady, void(VideoDecoder::Status,
222 const scoped_refptr<VideoFrame>&));
223
224 MessageLoop message_loop_;
225 scoped_ptr<StrictMock<MockDecryptor> > decryptor_;
226 scoped_refptr<StrictMock<DecryptingVideoDecoder> > decoder_;
227 scoped_refptr<StrictMock<MockDemuxerStream> > demuxer_;
228 MockStatisticsCB statistics_cb_;
229 VideoDecoderConfig config_;
230
231 DemuxerStream::ReadCB pending_demuxer_read_cb_;
232 Decryptor::DecoderInitCB pending_init_cb_;
233 Decryptor::VideoDecodeCB pending_video_decode_cb_;
234
235 scoped_refptr<DecoderBuffer> encrypted_buffer_;
236 scoped_refptr<VideoFrame> decoded_video_frame_;
237
238 private:
239 DISALLOW_COPY_AND_ASSIGN(DecryptingVideoDecoderTest);
240 };
241
242 TEST_F(DecryptingVideoDecoderTest, Initialize_Normal) {
243 Initialize();
244 }
245
246 // Ensure that DecryptingVideoDecoder only accepts encrypted video.
247 TEST_F(DecryptingVideoDecoderTest, Initialize_UnencryptedVideoConfig) {
248 VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
249 kVideoFormat,
250 kCodedSize, kVisibleRect, kNaturalSize,
251 NULL, 0, false);
252
253 InitializeAndExpectStatus(config, DECODER_ERROR_NOT_SUPPORTED);
254 }
255
256 // Ensure decoder handles invalid video configs without crashing.
257 TEST_F(DecryptingVideoDecoderTest, Initialize_InvalidVideoConfig) {
258 VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
259 VideoFrame::INVALID,
260 kCodedSize, kVisibleRect, kNaturalSize,
261 NULL, 0, true);
262
263 InitializeAndExpectStatus(config, PIPELINE_ERROR_DECODE);
264 }
265
266 // Ensure decoder handles unsupported video configs without crashing.
267 TEST_F(DecryptingVideoDecoderTest, Initialize_UnsupportedVideoConfig) {
268 EXPECT_CALL(*decryptor_, InitializeVideoDecoder(_, _))
269 .WillOnce(RunCallback1(false));
270
271 VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
272 kVideoFormat,
273 kCodedSize, kVisibleRect, kNaturalSize,
274 NULL, 0, true);
275
276 InitializeAndExpectStatus(config, DECODER_ERROR_NOT_SUPPORTED);
277 }
278
279 // Test normal decrypt and decode case.
280 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_Normal) {
281 Initialize();
282 EnterNormalDecodingState();
283 }
284
285 // Test the case where the decryptor returns error when doing decrypt and
286 // decode.
287 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_DecodeError) {
288 Initialize();
289
290 EXPECT_CALL(*demuxer_, Read(_))
291 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
292 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
293 .WillRepeatedly(RunCallback2(Decryptor::kError,
294 scoped_refptr<VideoFrame>(NULL)));
295
296 VideoDecoder::Status status = VideoDecoder::kDecryptError;
ddorwin 2012/10/01 18:43:20 kSuccess would be fine in this case. Then you don'
xhwang 2012/10/01 20:09:26 Done.
297 scoped_refptr<VideoFrame> video_frame;
298 ReadAndExpectToCompleteWith(&status, &video_frame);
299
300 EXPECT_EQ(VideoDecoder::kDecodeError, status);
301 EXPECT_FALSE(video_frame);
302 }
303
304 // Test the case where the decryptor does not have the decryption key to do
305 // decrypt and decode.
306 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_NoKey) {
307 Initialize();
308
309 EXPECT_CALL(*demuxer_, Read(_))
310 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
311 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
312 .WillRepeatedly(RunCallback2(Decryptor::kNoKey,
313 scoped_refptr<VideoFrame>(NULL)));
314
315 VideoDecoder::Status status = VideoDecoder::kDecryptError;
316 scoped_refptr<VideoFrame> video_frame;
317 ReadAndExpectToCompleteWith(&status, &video_frame);
318
319 EXPECT_EQ(VideoDecoder::kDecodeError, status);
320 EXPECT_FALSE(video_frame);
321 }
322
323 // Test the case where the decryptor returns kNeedMoreData to ask for more
324 // buffers before it can produce a frame.
325 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_NeedMoreData) {
326 Initialize();
327
328 EXPECT_CALL(*demuxer_, Read(_))
329 .Times(2)
330 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
331 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
332 .WillOnce(RunCallback2(Decryptor::kNeedMoreData,
333 scoped_refptr<VideoFrame>(NULL)))
334 .WillRepeatedly(RunCallback2(Decryptor::kSuccess, decoded_video_frame_));
335 EXPECT_CALL(statistics_cb_, OnStatistics(_))
336 .Times(2);
337
338 VideoDecoder::Status status = VideoDecoder::kDecodeError;
339 scoped_refptr<VideoFrame> video_frame;
340 ReadAndExpectToCompleteWith(&status, &video_frame);
341
342 EXPECT_EQ(VideoDecoder::kOk, status);
343 EXPECT_EQ(decoded_video_frame_, video_frame);
344 }
345
346 // Test the case where the decryptor receives end-of-stream buffer.
347 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_EndOfStream) {
348 Initialize();
349 EnterNormalDecodingState();
350 EnterEndOfStreamState();
351 }
352
353 // Test resetting when decoder has initialized but has not decoded any frame.
354 TEST_F(DecryptingVideoDecoderTest, Reset_Initialized) {
355 Initialize();
356 Reset();
357 }
358
359 // Test resetting when decoder has decoded single frame.
360 TEST_F(DecryptingVideoDecoderTest, Reset_Decoding) {
361 Initialize();
362 EnterNormalDecodingState();
363 Reset();
364 }
365
366 // Test resetting when decoder has hit end of stream.
367 TEST_F(DecryptingVideoDecoderTest, Reset_EndOfStream) {
368 Initialize();
369 EnterNormalDecodingState();
370 EnterEndOfStreamState();
371 Reset();
372 }
373
374 // Test resetting after the decoder has been reset.
375 TEST_F(DecryptingVideoDecoderTest, Reset_AfterReset) {
376 Initialize();
377 EnterNormalDecodingState();
378 Reset();
379 Reset();
380 }
381
382 // Test resetting when there is a pending read on the demuxer.
383 TEST_F(DecryptingVideoDecoderTest, Reset_DuringPendingDemuxerRead) {
384 Initialize();
385 EnterPendingReadState();
386
387 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
388
389 Reset();
390 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kOk,
391 encrypted_buffer_);
392 message_loop_.RunAllPending();
393 }
394
395 // Test resetting when there is a pending video decode callback on the
396 // decryptor.
397 TEST_F(DecryptingVideoDecoderTest, Reset_DuringPendingDecryptAndDecode) {
398 Initialize();
399 EnterPendingDecryptAndDecodeState();
400
401 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
402
403 Reset();
404 }
405
406 // Test stopping when decoder has initialized but has not decoded any frame.
407 TEST_F(DecryptingVideoDecoderTest, Stop_Initialized) {
408 Initialize();
409 Stop();
410 }
411
412 // Test stopping when decoder has decoded single frame.
413 TEST_F(DecryptingVideoDecoderTest, Stop_Decoding) {
414 Initialize();
415 EnterNormalDecodingState();
416 Stop();
417 }
418
419 // Test stopping when decoder has hit end of stream.
420 TEST_F(DecryptingVideoDecoderTest, Stop_EndOfStream) {
421 Initialize();
422 EnterNormalDecodingState();
423 EnterEndOfStreamState();
424 Stop();
425 }
426
427 // Test stopping when there is a pending read on the demuxer.
428 TEST_F(DecryptingVideoDecoderTest, Stop_DuringPendingInitialize) {
429 EXPECT_CALL(*decryptor_, InitializeVideoDecoder(_, _))
430 .WillOnce(SaveArg<1>(&pending_init_cb_));
431
432 config_.Initialize(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, kVideoFormat,
433 kCodedSize, kVisibleRect, kNaturalSize, NULL, 0, true,
434 true);
435 InitializeAndExpectStatus(config_, DECODER_ERROR_NOT_SUPPORTED);
436
437 Stop();
438 message_loop_.RunAllPending();
439 }
440
441 // Test stopping when there is a pending read on the demuxer.
442 TEST_F(DecryptingVideoDecoderTest, Stop_DuringPendingDemuxerRead) {
443 Initialize();
444 EnterPendingReadState();
445
446 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
447
448 Stop();
449 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kOk,
450 encrypted_buffer_);
451 message_loop_.RunAllPending();
452 }
453
454 // Test stopping when there is a pending video decode callback on the
455 // decryptor.
456 TEST_F(DecryptingVideoDecoderTest, Stop_DuringPendingDecryptAndDecode) {
457 Initialize();
458 EnterPendingDecryptAndDecodeState();
459
460 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
461
462 Stop();
463 }
464
465 // Test stopping when there is a pending reset on the decoder.
466 // Reset is pending because it cannot complete when the video decode callback
467 // is pending.
468 TEST_F(DecryptingVideoDecoderTest, Stop_DuringPendingReset) {
469 Initialize();
470 EnterPendingDecryptAndDecodeState();
471
472 EXPECT_CALL(*decryptor_, CancelDecryptAndDecodeVideo());
473 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
474
475 decoder_->Reset(NewExpectedClosure());
476 Stop();
477 }
478
479 // Test stopping after the decoder has been stopped.
480 TEST_F(DecryptingVideoDecoderTest, Stop_AfterReset) {
481 Initialize();
482 EnterNormalDecodingState();
483 Reset();
484 Stop();
485 }
486
487 // Test stopping after the decoder has been stopped.
488 TEST_F(DecryptingVideoDecoderTest, Stop_AfterStop) {
489 Initialize();
490 EnterNormalDecodingState();
491 Stop();
492 Stop();
493 }
494
495 // Test aborted read on the demuxer stream.
496 TEST_F(DecryptingVideoDecoderTest, AbortPendingDemuxerRead) {
497 Initialize();
498
499 // ReturnBuffer() with NULL triggers aborted demuxer read.
500 EXPECT_CALL(*demuxer_, Read(_))
501 .WillOnce(ReturnBuffer(scoped_refptr<DecoderBuffer>()));
502
503 VideoDecoder::Status status = VideoDecoder::kDecodeError;
504 scoped_refptr<VideoFrame> video_frame;
505 ReadAndExpectToCompleteWith(&status, &video_frame);
506
507 EXPECT_EQ(VideoDecoder::kOk, status);
508 EXPECT_FALSE(video_frame);
509 }
510
511 // Test aborted read on the demuxer stream when the decoder is being reset.
512 TEST_F(DecryptingVideoDecoderTest, AbortPendingDemuxerReadDuringReset) {
513 Initialize();
514 EnterPendingReadState();
515
516 // Make sure we get a NULL video frame returned.
517 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
518
519 Reset();
520 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kAborted,
521 NULL);
522 message_loop_.RunAllPending();
523 }
524
525 // Test config change on the demuxer stream.
526 TEST_F(DecryptingVideoDecoderTest, ConfigChanged) {
527 Initialize();
528
529 EXPECT_CALL(*demuxer_, Read(_))
530 .WillOnce(ReturnConfigChanged());
531
532 VideoDecoder::Status status = VideoDecoder::kDecryptError;
533 scoped_refptr<VideoFrame> video_frame;
534
535 ReadAndExpectToCompleteWith(&status, &video_frame);
536
537 // TODO(xhwang): Update this test when kConfigChanged is supported in
538 // DecryptingVideoDecoder.
539 EXPECT_EQ(VideoDecoder::kDecodeError, status);
540 EXPECT_FALSE(video_frame);
541 }
542
543 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698