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

Unified Diff: media/filters/ffmpeg_video_decoder_unittest.cc

Issue 16274005: Separate DemuxerStream and VideoDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix win64 Created 7 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/ffmpeg_video_decoder.cc ('k') | media/filters/gpu_video_decoder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 f6ac974fc280555dd5b6d781a8e5e308efebea99..c3f5fd51a334fb744ace3804693f20ad9f8cd27c 100644
--- a/media/filters/ffmpeg_video_decoder_unittest.cc
+++ b/media/filters/ffmpeg_video_decoder_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <string>
+#include <vector>
#include "base/bind.h"
#include "base/callback_helpers.h"
@@ -46,7 +47,6 @@ class FFmpegVideoDecoderTest : public testing::Test {
public:
FFmpegVideoDecoderTest()
: decoder_(new FFmpegVideoDecoder(message_loop_.message_loop_proxy())),
- demuxer_(new StrictMock<MockDemuxerStream>(DemuxerStream::VIDEO)),
read_cb_(base::Bind(&FFmpegVideoDecoderTest::FrameReady,
base::Unretained(this))) {
FFmpegGlue::InitializeFFmpeg();
@@ -68,11 +68,9 @@ class FFmpegVideoDecoderTest : public testing::Test {
void InitializeWithConfigAndStatus(const VideoDecoderConfig& config,
PipelineStatus status) {
- demuxer_->set_video_decoder_config(config);
- decoder_->Initialize(demuxer_.get(), NewExpectedStatusCB(status),
+ decoder_->Initialize(config, NewExpectedStatusCB(status),
base::Bind(&MockStatisticsCB::OnStatistics,
base::Unretained(&statistics_cb_)));
-
message_loop_.RunUntilIdle();
}
@@ -109,14 +107,58 @@ class FFmpegVideoDecoderTest : public testing::Test {
// Sets up expectations and actions to put FFmpegVideoDecoder in an end
// of stream state.
void EnterEndOfStreamState() {
- scoped_refptr<VideoFrame> video_frame;
VideoDecoder::Status status;
- Read(&status, &video_frame);
+ scoped_refptr<VideoFrame> video_frame;
+ DecodeSingleFrame(end_of_stream_buffer_, &status, &video_frame);
EXPECT_EQ(VideoDecoder::kOk, status);
ASSERT_TRUE(video_frame.get());
EXPECT_TRUE(video_frame->IsEndOfStream());
}
+ typedef std::vector<scoped_refptr<DecoderBuffer> > InputBuffers;
+ typedef std::vector<scoped_refptr<VideoFrame> > OutputFrames;
+
+ // Decodes all buffers in |input_buffers| and push all successfully decoded
+ // output frames (excluding EOS frames) into |output_frames|.
+ // Returns the last decode status returned by the decoder.
+ VideoDecoder::Status DecodeMultipleFrames(const InputBuffers& input_buffers,
+ OutputFrames* output_frames) {
+ InputBuffers::const_iterator input_iter = input_buffers.begin();
+
+ for (;;) {
+ // Prepare input buffer.
+ scoped_refptr<DecoderBuffer> buffer;
+ if (input_iter != input_buffers.end()) {
+ buffer = *input_iter;
+ ++input_iter;
+ } else {
+ buffer = end_of_stream_buffer_;
+ }
+
+ VideoDecoder::Status status;
+ scoped_refptr<VideoFrame> frame;
+ Decode(buffer, &status, &frame);
+
+ switch (status) {
+ case VideoDecoder::kOk:
+ DCHECK(frame);
+ if (!frame->IsEndOfStream()) {
+ output_frames->push_back(frame);
+ continue;
+ } else { // EOS
+ return status;
+ }
+ case VideoDecoder::kNotEnoughData:
+ DCHECK(!frame);
+ continue;
+ case VideoDecoder::kDecodeError:
+ case VideoDecoder::kDecryptError:
+ DCHECK(!frame);
+ return status;
+ }
+ }
+ }
+
// Decodes the single compressed frame in |buffer| and writes the
// uncompressed output to |video_frame|. This method works with single
// and multithreaded decoders. End of stream buffers are used to trigger
@@ -124,13 +166,23 @@ class FFmpegVideoDecoderTest : public testing::Test {
void DecodeSingleFrame(const scoped_refptr<DecoderBuffer>& buffer,
VideoDecoder::Status* status,
scoped_refptr<VideoFrame>* video_frame) {
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(ReturnBuffer(buffer))
- .WillRepeatedly(ReturnBuffer(end_of_stream_buffer_));
+ InputBuffers input_buffers;
+ input_buffers.push_back(buffer);
+
+ if (!buffer->IsEndOfStream())
+ EXPECT_CALL(statistics_cb_, OnStatistics(_));
- EXPECT_CALL(statistics_cb_, OnStatistics(_));
+ OutputFrames output_frames;
+ *status = DecodeMultipleFrames(input_buffers, &output_frames);
- Read(status, video_frame);
+ if (*status != VideoDecoder::kOk)
+ return;
+
+ ASSERT_LE(output_frames.size(), 1U);
+ if (output_frames.size() == 1U)
+ *video_frame = output_frames[0];
+ else
+ *video_frame = VideoFrame::CreateEmptyFrame();
}
// Decodes |i_frame_buffer_| and then decodes the data contained in
@@ -140,44 +192,40 @@ class FFmpegVideoDecoderTest : public testing::Test {
int expected_width,
int expected_height) {
Initialize();
-
- VideoDecoder::Status status_a;
- VideoDecoder::Status status_b;
- scoped_refptr<VideoFrame> video_frame_a;
- scoped_refptr<VideoFrame> video_frame_b;
-
scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name);
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(ReturnBuffer(i_frame_buffer_))
- .WillOnce(ReturnBuffer(buffer))
- .WillRepeatedly(ReturnBuffer(end_of_stream_buffer_));
+ InputBuffers input_buffers;
+ input_buffers.push_back(i_frame_buffer_);
+ input_buffers.push_back(buffer);
EXPECT_CALL(statistics_cb_, OnStatistics(_))
.Times(2);
- Read(&status_a, &video_frame_a);
- Read(&status_b, &video_frame_b);
+ OutputFrames output_frames;
+ VideoDecoder::Status status =
+ DecodeMultipleFrames(input_buffers, &output_frames);
+
+ EXPECT_EQ(VideoDecoder::kOk, status);
+ ASSERT_EQ(2U, output_frames.size());
gfx::Size original_size = kVisibleRect.size();
- EXPECT_EQ(VideoDecoder::kOk, status_a);
- EXPECT_EQ(VideoDecoder::kOk, status_b);
- ASSERT_TRUE(video_frame_a.get());
- ASSERT_TRUE(video_frame_b.get());
EXPECT_EQ(original_size.width(),
- video_frame_a->visible_rect().size().width());
+ output_frames[0]->visible_rect().size().width());
EXPECT_EQ(original_size.height(),
- video_frame_a->visible_rect().size().height());
- EXPECT_EQ(expected_width, video_frame_b->visible_rect().size().width());
- EXPECT_EQ(expected_height, video_frame_b->visible_rect().size().height());
+ output_frames[0]->visible_rect().size().height());
+ EXPECT_EQ(expected_width,
+ output_frames[1]->visible_rect().size().width());
+ EXPECT_EQ(expected_height,
+ output_frames[1]->visible_rect().size().height());
}
- void Read(VideoDecoder::Status* status,
- scoped_refptr<VideoFrame>* video_frame) {
+ 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)));
- decoder_->Read(read_cb_);
+ decoder_->Decode(buffer, read_cb_);
message_loop_.RunUntilIdle();
}
@@ -187,7 +235,6 @@ class FFmpegVideoDecoderTest : public testing::Test {
base::MessageLoop message_loop_;
scoped_ptr<FFmpegVideoDecoder> decoder_;
- scoped_ptr<StrictMock<MockDemuxerStream> > demuxer_;
MockStatisticsCB statistics_cb_;
VideoDecoder::ReadCB read_cb_;
@@ -213,7 +260,7 @@ TEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedDecoder) {
}
TEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedPixelFormat) {
- // Ensure decoder handles unsupport pixel formats without crashing.
+ // Ensure decoder handles unsupported pixel formats without crashing.
VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
VideoFrame::INVALID,
kCodedSize, kVisibleRect, kNaturalSize,
@@ -331,63 +378,46 @@ TEST_F(FFmpegVideoDecoderTest, DecodeFrame_0ByteFrame) {
scoped_refptr<DecoderBuffer> zero_byte_buffer = new DecoderBuffer(0);
- VideoDecoder::Status status_a;
- VideoDecoder::Status status_b;
- VideoDecoder::Status status_c;
- scoped_refptr<VideoFrame> video_frame_a;
- scoped_refptr<VideoFrame> video_frame_b;
- scoped_refptr<VideoFrame> video_frame_c;
-
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(ReturnBuffer(i_frame_buffer_))
- .WillOnce(ReturnBuffer(zero_byte_buffer))
- .WillOnce(ReturnBuffer(i_frame_buffer_))
- .WillRepeatedly(ReturnBuffer(end_of_stream_buffer_));
+ InputBuffers input_buffers;
+ input_buffers.push_back(i_frame_buffer_);
+ input_buffers.push_back(zero_byte_buffer);
+ input_buffers.push_back(i_frame_buffer_);
EXPECT_CALL(statistics_cb_, OnStatistics(_))
.Times(2);
- Read(&status_a, &video_frame_a);
- Read(&status_b, &video_frame_b);
- Read(&status_c, &video_frame_c);
+ OutputFrames output_frames;
+ VideoDecoder::Status status =
+ DecodeMultipleFrames(input_buffers, &output_frames);
- EXPECT_EQ(VideoDecoder::kOk, status_a);
- EXPECT_EQ(VideoDecoder::kOk, status_b);
- EXPECT_EQ(VideoDecoder::kOk, status_c);
-
- ASSERT_TRUE(video_frame_a.get());
- ASSERT_TRUE(video_frame_b.get());
- ASSERT_TRUE(video_frame_c.get());
+ EXPECT_EQ(VideoDecoder::kOk, status);
+ ASSERT_EQ(2U, output_frames.size());
- EXPECT_FALSE(video_frame_a->IsEndOfStream());
- EXPECT_FALSE(video_frame_b->IsEndOfStream());
- EXPECT_TRUE(video_frame_c->IsEndOfStream());
+ EXPECT_FALSE(output_frames[0]->IsEndOfStream());
+ EXPECT_FALSE(output_frames[1]->IsEndOfStream());
}
TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeError) {
Initialize();
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(ReturnBuffer(corrupt_i_frame_buffer_))
- .WillRepeatedly(ReturnBuffer(i_frame_buffer_));
+ InputBuffers input_buffers;
+ input_buffers.push_back(corrupt_i_frame_buffer_);
+ input_buffers.push_back(i_frame_buffer_);
+ input_buffers.push_back(i_frame_buffer_);
// The error is only raised on the second decode attempt, so we expect at
// least one successful decode but we don't expect FrameReady() to be
// executed as an error is raised instead.
EXPECT_CALL(statistics_cb_, OnStatistics(_));
- // Our read should still get satisfied with end of stream frame during an
- // error.
- VideoDecoder::Status status;
- scoped_refptr<VideoFrame> video_frame;
- Read(&status, &video_frame);
- EXPECT_EQ(VideoDecoder::kDecodeError, status);
- EXPECT_FALSE(video_frame.get());
+ OutputFrames output_frames;
+ VideoDecoder::Status status =
+ DecodeMultipleFrames(input_buffers, &output_frames);
- // After a decode error occurred, all following read will return kDecodeError.
- Read(&status, &video_frame);
EXPECT_EQ(VideoDecoder::kDecodeError, status);
- EXPECT_FALSE(video_frame.get());
+ // After a decode error occurred, all following decodes will return
+ // kDecodeError. Therefore, no |output_frames| will be available.
+ ASSERT_TRUE(output_frames.empty());
}
// Multi-threaded decoders have different behavior than single-threaded
@@ -452,25 +482,6 @@ TEST_F(FFmpegVideoDecoderTest, Reset_EndOfStream) {
Reset();
}
-// Test resetting when there is a pending read on the demuxer.
-TEST_F(FFmpegVideoDecoderTest, Reset_DuringPendingRead) {
- Initialize();
-
- // Request a read on the decoder and ensure the demuxer has been called.
- DemuxerStream::ReadCB read_cb;
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(SaveArg<0>(&read_cb));
- decoder_->Read(read_cb_);
- ASSERT_FALSE(read_cb.is_null());
-
- // Reset the decoder.
- Reset();
-
- EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
-
- read_cb.Run(DemuxerStream::kOk, i_frame_buffer_);
-}
-
// Test stopping when decoder has initialized but not decoded.
TEST_F(FFmpegVideoDecoderTest, Stop_Initialized) {
Initialize();
@@ -492,77 +503,4 @@ TEST_F(FFmpegVideoDecoderTest, Stop_EndOfStream) {
Stop();
}
-// Test stopping when there is a pending read on the demuxer.
-TEST_F(FFmpegVideoDecoderTest, Stop_DuringPendingRead) {
- Initialize();
-
- // Request a read on the decoder and ensure the demuxer has been called.
- DemuxerStream::ReadCB read_cb;
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(SaveArg<0>(&read_cb));
- decoder_->Read(read_cb_);
- ASSERT_FALSE(read_cb.is_null());
-
- EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
-
- Stop();
-
- read_cb.Run(DemuxerStream::kOk, i_frame_buffer_);
-}
-
-// Test stopping when there is a pending read on the demuxer.
-TEST_F(FFmpegVideoDecoderTest, Stop_DuringPendingReadAndReset) {
- Initialize();
-
- // Request a read on the decoder and ensure the demuxer has been called.
- DemuxerStream::ReadCB read_cb;
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(SaveArg<0>(&read_cb));
- decoder_->Read(read_cb_);
- ASSERT_FALSE(read_cb.is_null());
-
- Reset();
-
- EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
- Stop();
-
- read_cb.Run(DemuxerStream::kOk, i_frame_buffer_);
-}
-
-// Test aborted read on the demuxer stream.
-TEST_F(FFmpegVideoDecoderTest, DemuxerRead_Aborted) {
- Initialize();
-
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(ReturnBuffer(scoped_refptr<DecoderBuffer>()));
-
- VideoDecoder::Status status;
- scoped_refptr<VideoFrame> video_frame;
-
- Read(&status, &video_frame);
-
- EXPECT_EQ(VideoDecoder::kOk, status);
- EXPECT_FALSE(video_frame.get());
-}
-
-// Test aborted read on the demuxer stream during pending reset.
-TEST_F(FFmpegVideoDecoderTest, DemuxerRead_AbortedDuringReset) {
- Initialize();
-
- // Request a read on the decoder and ensure the demuxer has been called.
- DemuxerStream::ReadCB read_cb;
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(SaveArg<0>(&read_cb));
- decoder_->Read(read_cb_);
- ASSERT_FALSE(read_cb.is_null());
-
- // Reset while there is still an outstanding read on the demuxer.
- Reset();
-
- // Signal an aborted demuxer read: a NULL video frame should be returned.
- EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
- read_cb.Run(DemuxerStream::kAborted, NULL);
- message_loop_.RunUntilIdle();
-}
-
} // namespace media
« no previous file with comments | « media/filters/ffmpeg_video_decoder.cc ('k') | media/filters/gpu_video_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698