| 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();
|
| 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
|
|
|