| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 <list> |
| 5 #include <string> | 6 #include <string> |
| 6 #include <vector> | 7 #include <vector> |
| 7 | 8 |
| 8 #include "base/bind.h" | 9 #include "base/bind.h" |
| 9 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 10 #include "base/memory/singleton.h" | 11 #include "base/memory/singleton.h" |
| 11 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
| 12 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 13 #include "media/base/decoder_buffer.h" | 14 #include "media/base/decoder_buffer.h" |
| 14 #include "media/base/gmock_callback_support.h" | 15 #include "media/base/gmock_callback_support.h" |
| 15 #include "media/base/limits.h" | 16 #include "media/base/limits.h" |
| 16 #include "media/base/mock_filters.h" | 17 #include "media/base/mock_filters.h" |
| 17 #include "media/base/test_data_util.h" | 18 #include "media/base/test_data_util.h" |
| 18 #include "media/base/test_helpers.h" | 19 #include "media/base/test_helpers.h" |
| 19 #include "media/base/video_decoder.h" | 20 #include "media/base/video_decoder.h" |
| 20 #include "media/base/video_frame.h" | 21 #include "media/base/video_frame.h" |
| 21 #include "media/base/video_util.h" | 22 #include "media/base/video_util.h" |
| 22 #include "media/ffmpeg/ffmpeg_common.h" | 23 #include "media/ffmpeg/ffmpeg_common.h" |
| 23 #include "media/filters/ffmpeg_glue.h" | 24 #include "media/filters/ffmpeg_glue.h" |
| 24 #include "media/filters/ffmpeg_video_decoder.h" | 25 #include "media/filters/ffmpeg_video_decoder.h" |
| 25 #include "testing/gmock/include/gmock/gmock.h" | 26 #include "testing/gmock/include/gmock/gmock.h" |
| 26 | 27 |
| 27 using ::testing::_; | 28 using ::testing::_; |
| 28 using ::testing::AtLeast; | 29 using ::testing::AtLeast; |
| 30 using ::testing::AtMost; |
| 29 using ::testing::InSequence; | 31 using ::testing::InSequence; |
| 30 using ::testing::IsNull; | 32 using ::testing::IsNull; |
| 31 using ::testing::Return; | 33 using ::testing::Return; |
| 32 using ::testing::SaveArg; | 34 using ::testing::SaveArg; |
| 33 using ::testing::StrictMock; | 35 using ::testing::StrictMock; |
| 34 | 36 |
| 35 namespace media { | 37 namespace media { |
| 36 | 38 |
| 37 static const VideoFrame::Format kVideoFormat = VideoFrame::YV12; | 39 static const VideoFrame::Format kVideoFormat = VideoFrame::YV12; |
| 38 static const gfx::Size kCodedSize(320, 240); | 40 static const gfx::Size kCodedSize(320, 240); |
| 39 static const gfx::Rect kVisibleRect(320, 240); | 41 static const gfx::Rect kVisibleRect(320, 240); |
| 40 static const gfx::Size kNaturalSize(320, 240); | 42 static const gfx::Size kNaturalSize(320, 240); |
| 41 | 43 |
| 42 ACTION_P(ReturnBuffer, buffer) { | 44 ACTION_P(ReturnBuffer, buffer) { |
| 43 arg0.Run(buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer); | 45 arg0.Run(buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer); |
| 44 } | 46 } |
| 45 | 47 |
| 46 class FFmpegVideoDecoderTest : public testing::Test { | 48 class FFmpegVideoDecoderTest : public testing::Test { |
| 47 public: | 49 public: |
| 48 FFmpegVideoDecoderTest() | 50 FFmpegVideoDecoderTest() |
| 49 : decoder_(new FFmpegVideoDecoder(message_loop_.message_loop_proxy())), | 51 : decoder_(new FFmpegVideoDecoder(message_loop_.message_loop_proxy())), |
| 50 decode_cb_(base::Bind(&FFmpegVideoDecoderTest::FrameReady, | 52 decode_cb_(base::Bind(&FFmpegVideoDecoderTest::DecodeDone, |
| 51 base::Unretained(this))) { | 53 base::Unretained(this))) { |
| 52 FFmpegGlue::InitializeFFmpeg(); | 54 FFmpegGlue::InitializeFFmpeg(); |
| 53 | 55 |
| 54 // Initialize various test buffers. | 56 // Initialize various test buffers. |
| 55 frame_buffer_.reset(new uint8[kCodedSize.GetArea()]); | 57 frame_buffer_.reset(new uint8[kCodedSize.GetArea()]); |
| 56 end_of_stream_buffer_ = DecoderBuffer::CreateEOSBuffer(); | 58 end_of_stream_buffer_ = DecoderBuffer::CreateEOSBuffer(); |
| 57 i_frame_buffer_ = ReadTestDataFile("vp8-I-frame-320x240"); | 59 i_frame_buffer_ = ReadTestDataFile("vp8-I-frame-320x240"); |
| 58 corrupt_i_frame_buffer_ = ReadTestDataFile("vp8-corrupt-I-frame"); | 60 corrupt_i_frame_buffer_ = ReadTestDataFile("vp8-corrupt-I-frame"); |
| 59 } | 61 } |
| 60 | 62 |
| 61 virtual ~FFmpegVideoDecoderTest() { | 63 virtual ~FFmpegVideoDecoderTest() { |
| 62 Stop(); | 64 Stop(); |
| 63 } | 65 } |
| 64 | 66 |
| 65 void Initialize() { | 67 void Initialize() { |
| 66 InitializeWithConfig(TestVideoConfig::Normal()); | 68 InitializeWithConfig(TestVideoConfig::Normal()); |
| 67 } | 69 } |
| 68 | 70 |
| 69 void InitializeWithConfigAndStatus(const VideoDecoderConfig& config, | 71 void InitializeWithConfigAndStatus(const VideoDecoderConfig& config, |
| 70 PipelineStatus status) { | 72 PipelineStatus status) { |
| 71 decoder_->Initialize(config, false, NewExpectedStatusCB(status)); | 73 decoder_->Initialize(config, false, NewExpectedStatusCB(status), |
| 74 base::Bind(&FFmpegVideoDecoderTest::FrameReady, |
| 75 base::Unretained(this))); |
| 72 message_loop_.RunUntilIdle(); | 76 message_loop_.RunUntilIdle(); |
| 73 } | 77 } |
| 74 | 78 |
| 75 void InitializeWithConfig(const VideoDecoderConfig& config) { | 79 void InitializeWithConfig(const VideoDecoderConfig& config) { |
| 76 InitializeWithConfigAndStatus(config, PIPELINE_OK); | 80 InitializeWithConfigAndStatus(config, PIPELINE_OK); |
| 77 } | 81 } |
| 78 | 82 |
| 79 void Reinitialize() { | 83 void Reinitialize() { |
| 80 InitializeWithConfig(TestVideoConfig::Large()); | 84 InitializeWithConfig(TestVideoConfig::Large()); |
| 81 } | 85 } |
| 82 | 86 |
| 83 void Reset() { | 87 void Reset() { |
| 84 decoder_->Reset(NewExpectedClosure()); | 88 decoder_->Reset(NewExpectedClosure()); |
| 85 message_loop_.RunUntilIdle(); | 89 message_loop_.RunUntilIdle(); |
| 86 } | 90 } |
| 87 | 91 |
| 88 void Stop() { | 92 void Stop() { |
| 89 decoder_->Stop(); | 93 decoder_->Stop(); |
| 90 message_loop_.RunUntilIdle(); | 94 message_loop_.RunUntilIdle(); |
| 91 } | 95 } |
| 92 | 96 |
| 93 // Sets up expectations and actions to put FFmpegVideoDecoder in an active | 97 // Sets up expectations and actions to put FFmpegVideoDecoder in an active |
| 94 // decoding state. | 98 // decoding state. |
| 95 void EnterDecodingState() { | 99 void EnterDecodingState() { |
| 96 VideoDecoder::Status status; | 100 EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(i_frame_buffer_)); |
| 97 scoped_refptr<VideoFrame> video_frame; | 101 ASSERT_EQ(2U, output_frames_.size()); |
| 98 DecodeSingleFrame(i_frame_buffer_, &status, &video_frame); | 102 EXPECT_FALSE(output_frames_[0]->end_of_stream()); |
| 99 | 103 EXPECT_TRUE(output_frames_[1]->end_of_stream()); |
| 100 EXPECT_EQ(VideoDecoder::kOk, status); | |
| 101 ASSERT_TRUE(video_frame.get()); | |
| 102 EXPECT_FALSE(video_frame->end_of_stream()); | |
| 103 } | 104 } |
| 104 | 105 |
| 105 // Sets up expectations and actions to put FFmpegVideoDecoder in an end | 106 // Sets up expectations and actions to put FFmpegVideoDecoder in an end |
| 106 // of stream state. | 107 // of stream state. |
| 107 void EnterEndOfStreamState() { | 108 void EnterEndOfStreamState() { |
| 108 VideoDecoder::Status status; | 109 EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(end_of_stream_buffer_)); |
| 109 scoped_refptr<VideoFrame> video_frame; | 110 ASSERT_FALSE(output_frames_.empty()); |
| 110 DecodeSingleFrame(end_of_stream_buffer_, &status, &video_frame); | 111 EXPECT_TRUE(output_frames_.back()->end_of_stream()); |
| 111 EXPECT_EQ(VideoDecoder::kOk, status); | |
| 112 ASSERT_TRUE(video_frame.get()); | |
| 113 EXPECT_TRUE(video_frame->end_of_stream()); | |
| 114 } | 112 } |
| 115 | 113 |
| 116 typedef std::vector<scoped_refptr<DecoderBuffer> > InputBuffers; | 114 typedef std::vector<scoped_refptr<DecoderBuffer> > InputBuffers; |
| 117 typedef std::vector<scoped_refptr<VideoFrame> > OutputFrames; | 115 typedef std::vector<scoped_refptr<VideoFrame> > OutputFrames; |
| 118 | 116 |
| 119 // Decodes all buffers in |input_buffers| and push all successfully decoded | 117 // Decodes all buffers in |input_buffers| and push all successfully decoded |
| 120 // output frames (excluding EOS frames) into |output_frames|. | 118 // output frames (excluding EOS frames) into |output_frames|. |
| 121 // Returns the last decode status returned by the decoder. | 119 // Returns the last decode status returned by the decoder. |
| 122 VideoDecoder::Status DecodeMultipleFrames(const InputBuffers& input_buffers, | 120 VideoDecoder::Status DecodeMultipleFrames(const InputBuffers& input_buffers) { |
| 123 OutputFrames* output_frames) { | |
| 124 InputBuffers::const_iterator input_iter = input_buffers.begin(); | 121 InputBuffers::const_iterator input_iter = input_buffers.begin(); |
| 125 | 122 |
| 126 for (;;) { | 123 while (output_frames_.empty() || !output_frames_.back()->end_of_stream()) { |
| 127 // Prepare input buffer. | 124 // Prepare input buffer. |
| 128 scoped_refptr<DecoderBuffer> buffer; | 125 scoped_refptr<DecoderBuffer> buffer; |
| 129 if (input_iter != input_buffers.end()) { | 126 if (input_iter != input_buffers.end()) { |
| 130 buffer = *input_iter; | 127 buffer = *input_iter; |
| 131 ++input_iter; | 128 ++input_iter; |
| 132 } else { | 129 } else { |
| 133 buffer = end_of_stream_buffer_; | 130 buffer = end_of_stream_buffer_; |
| 134 } | 131 } |
| 135 | 132 |
| 136 VideoDecoder::Status status; | 133 VideoDecoder::Status status = Decode(buffer); |
| 137 scoped_refptr<VideoFrame> frame; | |
| 138 Decode(buffer, &status, &frame); | |
| 139 | 134 |
| 140 switch (status) { | 135 switch (status) { |
| 141 case VideoDecoder::kOk: | 136 case VideoDecoder::kOk: |
| 142 DCHECK(frame); | 137 break; |
| 143 if (!frame->end_of_stream()) { | |
| 144 output_frames->push_back(frame); | |
| 145 continue; | |
| 146 } else { // EOS | |
| 147 return status; | |
| 148 } | |
| 149 case VideoDecoder::kNotEnoughData: | |
| 150 DCHECK(!frame); | |
| 151 continue; | |
| 152 case VideoDecoder::kAborted: | 138 case VideoDecoder::kAborted: |
| 153 NOTREACHED(); | 139 NOTREACHED(); |
| 154 case VideoDecoder::kDecodeError: | 140 case VideoDecoder::kDecodeError: |
| 155 case VideoDecoder::kDecryptError: | 141 case VideoDecoder::kDecryptError: |
| 156 DCHECK(!frame); | 142 DCHECK(output_frames_.empty()); |
| 157 return status; | 143 return status; |
| 158 } | 144 } |
| 159 } | 145 } |
| 146 |
| 147 return VideoDecoder::kOk; |
| 160 } | 148 } |
| 161 | 149 |
| 162 // Decodes the single compressed frame in |buffer| and writes the | 150 // Decodes the single compressed frame in |buffer| and writes the |
| 163 // uncompressed output to |video_frame|. This method works with single | 151 // uncompressed output to |video_frame|. This method works with single |
| 164 // and multithreaded decoders. End of stream buffers are used to trigger | 152 // and multithreaded decoders. End of stream buffers are used to trigger |
| 165 // the frame to be returned in the multithreaded decoder case. | 153 // the frame to be returned in the multithreaded decoder case. |
| 166 void DecodeSingleFrame(const scoped_refptr<DecoderBuffer>& buffer, | 154 VideoDecoder::Status DecodeSingleFrame( |
| 167 VideoDecoder::Status* status, | 155 const scoped_refptr<DecoderBuffer>& buffer) { |
| 168 scoped_refptr<VideoFrame>* video_frame) { | |
| 169 InputBuffers input_buffers; | 156 InputBuffers input_buffers; |
| 170 input_buffers.push_back(buffer); | 157 input_buffers.push_back(buffer); |
| 171 | 158 |
| 172 OutputFrames output_frames; | 159 return DecodeMultipleFrames(input_buffers); |
| 173 *status = DecodeMultipleFrames(input_buffers, &output_frames); | |
| 174 | |
| 175 if (*status != VideoDecoder::kOk) | |
| 176 return; | |
| 177 | |
| 178 ASSERT_LE(output_frames.size(), 1U); | |
| 179 if (output_frames.size() == 1U) | |
| 180 *video_frame = output_frames[0]; | |
| 181 else | |
| 182 *video_frame = VideoFrame::CreateEOSFrame(); | |
| 183 } | 160 } |
| 184 | 161 |
| 185 // Decodes |i_frame_buffer_| and then decodes the data contained in | 162 // Decodes |i_frame_buffer_| and then decodes the data contained in |
| 186 // the file named |test_file_name|. This function expects both buffers | 163 // the file named |test_file_name|. This function expects both buffers |
| 187 // to decode to frames that are the same size. | 164 // to decode to frames that are the same size. |
| 188 void DecodeIFrameThenTestFile(const std::string& test_file_name, | 165 void DecodeIFrameThenTestFile(const std::string& test_file_name, |
| 189 int expected_width, | 166 int expected_width, |
| 190 int expected_height) { | 167 int expected_height) { |
| 191 Initialize(); | 168 Initialize(); |
| 192 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name); | 169 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name); |
| 193 | 170 |
| 194 InputBuffers input_buffers; | 171 InputBuffers input_buffers; |
| 195 input_buffers.push_back(i_frame_buffer_); | 172 input_buffers.push_back(i_frame_buffer_); |
| 196 input_buffers.push_back(buffer); | 173 input_buffers.push_back(buffer); |
| 197 | 174 |
| 198 OutputFrames output_frames; | |
| 199 VideoDecoder::Status status = | 175 VideoDecoder::Status status = |
| 200 DecodeMultipleFrames(input_buffers, &output_frames); | 176 DecodeMultipleFrames(input_buffers); |
| 201 | 177 |
| 202 EXPECT_EQ(VideoDecoder::kOk, status); | 178 EXPECT_EQ(VideoDecoder::kOk, status); |
| 203 ASSERT_EQ(2U, output_frames.size()); | 179 ASSERT_EQ(3U, output_frames_.size()); |
| 204 | 180 |
| 205 gfx::Size original_size = kVisibleRect.size(); | 181 gfx::Size original_size = kVisibleRect.size(); |
| 206 EXPECT_EQ(original_size.width(), | 182 EXPECT_EQ(original_size.width(), |
| 207 output_frames[0]->visible_rect().size().width()); | 183 output_frames_[0]->visible_rect().size().width()); |
| 208 EXPECT_EQ(original_size.height(), | 184 EXPECT_EQ(original_size.height(), |
| 209 output_frames[0]->visible_rect().size().height()); | 185 output_frames_[0]->visible_rect().size().height()); |
| 210 EXPECT_EQ(expected_width, | 186 EXPECT_EQ(expected_width, |
| 211 output_frames[1]->visible_rect().size().width()); | 187 output_frames_[1]->visible_rect().size().width()); |
| 212 EXPECT_EQ(expected_height, | 188 EXPECT_EQ(expected_height, |
| 213 output_frames[1]->visible_rect().size().height()); | 189 output_frames_[1]->visible_rect().size().height()); |
| 190 EXPECT_TRUE(output_frames_[2]->end_of_stream()); |
| 214 } | 191 } |
| 215 | 192 |
| 216 void Decode(const scoped_refptr<DecoderBuffer>& buffer, | 193 VideoDecoder::Status Decode(const scoped_refptr<DecoderBuffer>& buffer) { |
| 217 VideoDecoder::Status* status, | 194 VideoDecoder::Status status; |
| 218 scoped_refptr<VideoFrame>* video_frame) { | 195 EXPECT_CALL(*this, DecodeDone(_)).WillOnce(SaveArg<0>(&status)); |
| 219 EXPECT_CALL(*this, FrameReady(_, _)) | |
| 220 .WillOnce(DoAll(SaveArg<0>(status), SaveArg<1>(video_frame))); | |
| 221 | 196 |
| 222 decoder_->Decode(buffer, decode_cb_); | 197 decoder_->Decode(buffer, decode_cb_); |
| 223 | 198 |
| 224 message_loop_.RunUntilIdle(); | 199 message_loop_.RunUntilIdle(); |
| 200 |
| 201 return status; |
| 225 } | 202 } |
| 226 | 203 |
| 227 MOCK_METHOD2(FrameReady, void(VideoDecoder::Status, | 204 void FrameReady(const scoped_refptr<VideoFrame>& frame) { |
| 228 const scoped_refptr<VideoFrame>&)); | 205 output_frames_.push_back(frame); |
| 206 } |
| 207 |
| 208 MOCK_METHOD1(DecodeDone, void(VideoDecoder::Status)); |
| 229 | 209 |
| 230 base::MessageLoop message_loop_; | 210 base::MessageLoop message_loop_; |
| 231 scoped_ptr<FFmpegVideoDecoder> decoder_; | 211 scoped_ptr<FFmpegVideoDecoder> decoder_; |
| 232 | 212 |
| 233 VideoDecoder::DecodeCB decode_cb_; | 213 VideoDecoder::DecodeCB decode_cb_; |
| 234 | 214 |
| 235 // Various buffers for testing. | 215 // Various buffers for testing. |
| 236 scoped_ptr<uint8_t[]> frame_buffer_; | 216 scoped_ptr<uint8_t[]> frame_buffer_; |
| 237 scoped_refptr<DecoderBuffer> end_of_stream_buffer_; | 217 scoped_refptr<DecoderBuffer> end_of_stream_buffer_; |
| 238 scoped_refptr<DecoderBuffer> i_frame_buffer_; | 218 scoped_refptr<DecoderBuffer> i_frame_buffer_; |
| 239 scoped_refptr<DecoderBuffer> corrupt_i_frame_buffer_; | 219 scoped_refptr<DecoderBuffer> corrupt_i_frame_buffer_; |
| 240 | 220 |
| 221 OutputFrames output_frames_; |
| 222 |
| 241 private: | 223 private: |
| 242 DISALLOW_COPY_AND_ASSIGN(FFmpegVideoDecoderTest); | 224 DISALLOW_COPY_AND_ASSIGN(FFmpegVideoDecoderTest); |
| 243 }; | 225 }; |
| 244 | 226 |
| 245 TEST_F(FFmpegVideoDecoderTest, Initialize_Normal) { | 227 TEST_F(FFmpegVideoDecoderTest, Initialize_Normal) { |
| 246 Initialize(); | 228 Initialize(); |
| 247 } | 229 } |
| 248 | 230 |
| 249 TEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedDecoder) { | 231 TEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedDecoder) { |
| 250 // Test avcodec_find_decoder() returning NULL. | 232 // Test avcodec_find_decoder() returning NULL. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 Initialize(); | 330 Initialize(); |
| 349 EnterDecodingState(); | 331 EnterDecodingState(); |
| 350 Reset(); | 332 Reset(); |
| 351 Reinitialize(); | 333 Reinitialize(); |
| 352 } | 334 } |
| 353 | 335 |
| 354 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_Normal) { | 336 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_Normal) { |
| 355 Initialize(); | 337 Initialize(); |
| 356 | 338 |
| 357 // Simulate decoding a single frame. | 339 // Simulate decoding a single frame. |
| 358 VideoDecoder::Status status; | 340 EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(i_frame_buffer_)); |
| 359 scoped_refptr<VideoFrame> video_frame; | 341 ASSERT_EQ(2U, output_frames_.size()); |
| 360 DecodeSingleFrame(i_frame_buffer_, &status, &video_frame); | 342 EXPECT_FALSE(output_frames_[0]->end_of_stream()); |
| 361 | 343 EXPECT_TRUE(output_frames_[1]->end_of_stream()); |
| 362 EXPECT_EQ(VideoDecoder::kOk, status); | |
| 363 ASSERT_TRUE(video_frame.get()); | |
| 364 EXPECT_FALSE(video_frame->end_of_stream()); | |
| 365 } | 344 } |
| 366 | 345 |
| 367 // Verify current behavior for 0 byte frames. FFmpeg simply ignores | 346 // Verify current behavior for 0 byte frames. FFmpeg simply ignores |
| 368 // the 0 byte frames. | 347 // the 0 byte frames. |
| 369 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_0ByteFrame) { | 348 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_0ByteFrame) { |
| 370 Initialize(); | 349 Initialize(); |
| 371 | 350 |
| 372 scoped_refptr<DecoderBuffer> zero_byte_buffer = new DecoderBuffer(0); | 351 scoped_refptr<DecoderBuffer> zero_byte_buffer = new DecoderBuffer(0); |
| 373 | 352 |
| 374 InputBuffers input_buffers; | 353 InputBuffers input_buffers; |
| 375 input_buffers.push_back(i_frame_buffer_); | 354 input_buffers.push_back(i_frame_buffer_); |
| 376 input_buffers.push_back(zero_byte_buffer); | 355 input_buffers.push_back(zero_byte_buffer); |
| 377 input_buffers.push_back(i_frame_buffer_); | 356 input_buffers.push_back(i_frame_buffer_); |
| 378 | 357 |
| 379 OutputFrames output_frames; | 358 VideoDecoder::Status status = DecodeMultipleFrames(input_buffers); |
| 380 VideoDecoder::Status status = | |
| 381 DecodeMultipleFrames(input_buffers, &output_frames); | |
| 382 | 359 |
| 383 EXPECT_EQ(VideoDecoder::kOk, status); | 360 EXPECT_EQ(VideoDecoder::kOk, status); |
| 384 ASSERT_EQ(2U, output_frames.size()); | 361 ASSERT_EQ(3U, output_frames_.size()); |
| 385 | 362 |
| 386 EXPECT_FALSE(output_frames[0]->end_of_stream()); | 363 EXPECT_FALSE(output_frames_[0]->end_of_stream()); |
| 387 EXPECT_FALSE(output_frames[1]->end_of_stream()); | 364 EXPECT_FALSE(output_frames_[1]->end_of_stream()); |
| 365 EXPECT_TRUE(output_frames_[2]->end_of_stream()); |
| 388 } | 366 } |
| 389 | 367 |
| 390 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeError) { | 368 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeError) { |
| 391 Initialize(); | 369 Initialize(); |
| 392 | 370 |
| 393 VideoDecoder::Status status; | |
| 394 scoped_refptr<VideoFrame> frame; | |
| 395 | |
| 396 // The error is only raised on the second decode attempt, so we expect at | 371 // The error is only raised on the second decode attempt, so we expect at |
| 397 // least one successful decode but we don't expect valid frame to be decoded. | 372 // least one successful decode but we don't expect valid frame to be decoded. |
| 398 // During the second decode attempt an error is raised. | 373 // During the second decode attempt an error is raised. |
| 399 Decode(corrupt_i_frame_buffer_, &status, &frame); | 374 EXPECT_EQ(VideoDecoder::kOk, Decode(corrupt_i_frame_buffer_)); |
| 400 DCHECK(!frame); | 375 EXPECT_TRUE(output_frames_.empty()); |
| 401 DCHECK_EQ(VideoDecoder::kNotEnoughData, status); | 376 EXPECT_EQ(VideoDecoder::kDecodeError, Decode(i_frame_buffer_)); |
| 402 Decode(i_frame_buffer_, &status, &frame); | 377 EXPECT_TRUE(output_frames_.empty()); |
| 403 DCHECK(!frame); | |
| 404 DCHECK_EQ(VideoDecoder::kDecodeError, status); | |
| 405 | 378 |
| 406 // After a decode error occurred, all following decodes will return | 379 // After a decode error occurred, all following decodes will return |
| 407 // kDecodeError. | 380 // kDecodeError. |
| 408 Decode(i_frame_buffer_, &status, &frame); | 381 EXPECT_EQ(VideoDecoder::kDecodeError, Decode(i_frame_buffer_)); |
| 409 DCHECK(!frame); | 382 EXPECT_TRUE(output_frames_.empty()); |
| 410 DCHECK_EQ(VideoDecoder::kDecodeError, status); | |
| 411 } | 383 } |
| 412 | 384 |
| 413 // Multi-threaded decoders have different behavior than single-threaded | 385 // Multi-threaded decoders have different behavior than single-threaded |
| 414 // decoders at the end of the stream. Multithreaded decoders hide errors | 386 // decoders at the end of the stream. Multithreaded decoders hide errors |
| 415 // that happen on the last |codec_context_->thread_count| frames to avoid | 387 // that happen on the last |codec_context_->thread_count| frames to avoid |
| 416 // prematurely signalling EOS. This test just exposes that behavior so we can | 388 // prematurely signalling EOS. This test just exposes that behavior so we can |
| 417 // detect if it changes. | 389 // detect if it changes. |
| 418 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeErrorAtEndOfStream) { | 390 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeErrorAtEndOfStream) { |
| 419 Initialize(); | 391 Initialize(); |
| 420 | 392 |
| 421 VideoDecoder::Status status; | 393 EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(corrupt_i_frame_buffer_)); |
| 422 scoped_refptr<VideoFrame> video_frame; | 394 ASSERT_FALSE(output_frames_.empty()); |
| 423 DecodeSingleFrame(corrupt_i_frame_buffer_, &status, &video_frame); | 395 EXPECT_TRUE(output_frames_.back()->end_of_stream()); |
| 424 | |
| 425 EXPECT_EQ(VideoDecoder::kOk, status); | |
| 426 ASSERT_TRUE(video_frame.get()); | |
| 427 EXPECT_TRUE(video_frame->end_of_stream()); | |
| 428 } | 396 } |
| 429 | 397 |
| 430 // Decode |i_frame_buffer_| and then a frame with a larger width and verify | 398 // Decode |i_frame_buffer_| and then a frame with a larger width and verify |
| 431 // the output size was adjusted. | 399 // the output size was adjusted. |
| 432 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_LargerWidth) { | 400 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_LargerWidth) { |
| 433 DecodeIFrameThenTestFile("vp8-I-frame-640x240", 640, 240); | 401 DecodeIFrameThenTestFile("vp8-I-frame-640x240", 640, 240); |
| 434 } | 402 } |
| 435 | 403 |
| 436 // Decode |i_frame_buffer_| and then a frame with a smaller width and verify | 404 // Decode |i_frame_buffer_| and then a frame with a smaller width and verify |
| 437 // the output size was adjusted. | 405 // the output size was adjusted. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 | 455 |
| 488 // Test stopping when decoder has hit end of stream. | 456 // Test stopping when decoder has hit end of stream. |
| 489 TEST_F(FFmpegVideoDecoderTest, Stop_EndOfStream) { | 457 TEST_F(FFmpegVideoDecoderTest, Stop_EndOfStream) { |
| 490 Initialize(); | 458 Initialize(); |
| 491 EnterDecodingState(); | 459 EnterDecodingState(); |
| 492 EnterEndOfStreamState(); | 460 EnterEndOfStreamState(); |
| 493 Stop(); | 461 Stop(); |
| 494 } | 462 } |
| 495 | 463 |
| 496 } // namespace media | 464 } // namespace media |
| OLD | NEW |