Chromium Code Reviews| Index: media/filters/ffmpeg_video_decoder_unittest.cc |
| diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc |
| index 24627f2874bd2677b36b86eff17e73b857f98d91..c81c820cea354f0a7df9680df9f087aa64adb982 100644 |
| --- a/media/filters/ffmpeg_video_decoder_unittest.cc |
| +++ b/media/filters/ffmpeg_video_decoder_unittest.cc |
| @@ -2,6 +2,7 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#include <list> |
| #include <string> |
| #include <vector> |
| @@ -26,6 +27,7 @@ |
| using ::testing::_; |
| using ::testing::AtLeast; |
| +using ::testing::AtMost; |
| using ::testing::InSequence; |
| using ::testing::IsNull; |
| using ::testing::Return; |
| @@ -43,11 +45,15 @@ ACTION_P(ReturnBuffer, buffer) { |
| arg0.Run(buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer); |
| } |
| +ACTION_P(PushBackTo, output) { |
| + output->push_back(arg0); |
| +} |
| + |
| class FFmpegVideoDecoderTest : public testing::Test { |
| public: |
| FFmpegVideoDecoderTest() |
| : decoder_(new FFmpegVideoDecoder(message_loop_.message_loop_proxy())), |
| - decode_cb_(base::Bind(&FFmpegVideoDecoderTest::FrameReady, |
| + decode_cb_(base::Bind(&FFmpegVideoDecoderTest::DecodeDone, |
| base::Unretained(this))) { |
| FFmpegGlue::InitializeFFmpeg(); |
| @@ -68,7 +74,9 @@ class FFmpegVideoDecoderTest : public testing::Test { |
| void InitializeWithConfigAndStatus(const VideoDecoderConfig& config, |
| PipelineStatus status) { |
| - decoder_->Initialize(config, false, NewExpectedStatusCB(status)); |
| + decoder_->Initialize(config, false, NewExpectedStatusCB(status), |
| + base::Bind(&FFmpegVideoDecoderTest::FrameReady, |
| + base::Unretained(this))); |
| message_loop_.RunUntilIdle(); |
| } |
| @@ -121,9 +129,10 @@ class FFmpegVideoDecoderTest : public testing::Test { |
| // Returns the last decode status returned by the decoder. |
| VideoDecoder::Status DecodeMultipleFrames(const InputBuffers& input_buffers, |
| OutputFrames* output_frames) { |
| + output_frames->clear(); |
|
xhwang
2014/06/05 21:53:51
DCHECK(output_frames->empty())?
Sergey Ulanov
2014/06/06 22:49:41
Done.
|
| InputBuffers::const_iterator input_iter = input_buffers.begin(); |
| - for (;;) { |
| + while (output_frames->empty() || !output_frames->back()->end_of_stream()) { |
| // Prepare input buffer. |
| scoped_refptr<DecoderBuffer> buffer; |
| if (input_iter != input_buffers.end()) { |
| @@ -134,29 +143,24 @@ class FFmpegVideoDecoderTest : public testing::Test { |
| } |
| VideoDecoder::Status status; |
| - scoped_refptr<VideoFrame> frame; |
| - Decode(buffer, &status, &frame); |
| + Decode(buffer, &status, output_frames); |
| switch (status) { |
| case VideoDecoder::kOk: |
| - DCHECK(frame); |
| - if (!frame->end_of_stream()) { |
| - output_frames->push_back(frame); |
| - continue; |
| - } else { // EOS |
| - return status; |
| - } |
| - case VideoDecoder::kNotEnoughData: |
| - DCHECK(!frame); |
| - continue; |
| + break; |
| case VideoDecoder::kAborted: |
| NOTREACHED(); |
| case VideoDecoder::kDecodeError: |
| case VideoDecoder::kDecryptError: |
| - DCHECK(!frame); |
| + DCHECK(output_frames->empty()); |
| return status; |
| } |
| } |
| + |
| + // Remove the EOS frame. |
| + output_frames->erase(--output_frames->end()); |
| + |
| + return VideoDecoder::kOk; |
| } |
| // Decodes the single compressed frame in |buffer| and writes the |
| @@ -215,17 +219,18 @@ class FFmpegVideoDecoderTest : public testing::Test { |
| void Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| VideoDecoder::Status* status, |
| - scoped_refptr<VideoFrame>* video_frame) { |
| - EXPECT_CALL(*this, FrameReady(_, _)) |
| - .WillOnce(DoAll(SaveArg<0>(status), SaveArg<1>(video_frame))); |
| + OutputFrames* video_frames) { |
| + EXPECT_CALL(*this, FrameReady(_)) |
| + .WillRepeatedly(PushBackTo(video_frames)); |
| + EXPECT_CALL(*this, DecodeDone(_)).WillOnce(SaveArg<0>(status)); |
| decoder_->Decode(buffer, decode_cb_); |
| message_loop_.RunUntilIdle(); |
| } |
| - MOCK_METHOD2(FrameReady, void(VideoDecoder::Status, |
| - const scoped_refptr<VideoFrame>&)); |
| + MOCK_METHOD1(FrameReady, void(const scoped_refptr<VideoFrame>&)); |
| + MOCK_METHOD1(DecodeDone, void(VideoDecoder::Status)); |
| base::MessageLoop message_loop_; |
| scoped_ptr<FFmpegVideoDecoder> decoder_; |
| @@ -391,23 +396,23 @@ TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeError) { |
| Initialize(); |
| VideoDecoder::Status status; |
| - scoped_refptr<VideoFrame> frame; |
| + OutputFrames frames; |
| // The error is only raised on the second decode attempt, so we expect at |
| // least one successful decode but we don't expect valid frame to be decoded. |
| // During the second decode attempt an error is raised. |
| - Decode(corrupt_i_frame_buffer_, &status, &frame); |
| - DCHECK(!frame); |
| - DCHECK_EQ(VideoDecoder::kNotEnoughData, status); |
| - Decode(i_frame_buffer_, &status, &frame); |
| - DCHECK(!frame); |
| - DCHECK_EQ(VideoDecoder::kDecodeError, status); |
| + Decode(corrupt_i_frame_buffer_, &status, &frames); |
| + EXPECT_TRUE(frames.empty()); |
| + EXPECT_EQ(VideoDecoder::kOk, status); |
| + Decode(i_frame_buffer_, &status, &frames); |
| + EXPECT_TRUE(frames.empty()); |
| + EXPECT_EQ(VideoDecoder::kDecodeError, status); |
| // After a decode error occurred, all following decodes will return |
| // kDecodeError. |
| - Decode(i_frame_buffer_, &status, &frame); |
| - DCHECK(!frame); |
| - DCHECK_EQ(VideoDecoder::kDecodeError, status); |
| + Decode(i_frame_buffer_, &status, &frames); |
| + EXPECT_TRUE(frames.empty()); |
| + EXPECT_EQ(VideoDecoder::kDecodeError, status); |
| } |
| // Multi-threaded decoders have different behavior than single-threaded |