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 <stdint.h> | 5 #include <stdint.h> |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 } | 94 } |
95 | 95 |
96 void Destroy() { | 96 void Destroy() { |
97 decoder_.reset(); | 97 decoder_.reset(); |
98 message_loop_.RunUntilIdle(); | 98 message_loop_.RunUntilIdle(); |
99 } | 99 } |
100 | 100 |
101 // Sets up expectations and actions to put FFmpegVideoDecoder in an active | 101 // Sets up expectations and actions to put FFmpegVideoDecoder in an active |
102 // decoding state. | 102 // decoding state. |
103 void EnterDecodingState() { | 103 void EnterDecodingState() { |
104 EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(i_frame_buffer_)); | 104 EXPECT_EQ(DecodeStatus::OK, DecodeSingleFrame(i_frame_buffer_)); |
105 ASSERT_EQ(1U, output_frames_.size()); | 105 ASSERT_EQ(1U, output_frames_.size()); |
106 } | 106 } |
107 | 107 |
108 // Sets up expectations and actions to put FFmpegVideoDecoder in an end | 108 // Sets up expectations and actions to put FFmpegVideoDecoder in an end |
109 // of stream state. | 109 // of stream state. |
110 void EnterEndOfStreamState() { | 110 void EnterEndOfStreamState() { |
111 EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(end_of_stream_buffer_)); | 111 EXPECT_EQ(DecodeStatus::OK, DecodeSingleFrame(end_of_stream_buffer_)); |
112 ASSERT_FALSE(output_frames_.empty()); | 112 ASSERT_FALSE(output_frames_.empty()); |
113 } | 113 } |
114 | 114 |
115 typedef std::vector<scoped_refptr<DecoderBuffer> > InputBuffers; | 115 typedef std::vector<scoped_refptr<DecoderBuffer> > InputBuffers; |
116 typedef std::vector<scoped_refptr<VideoFrame> > OutputFrames; | 116 typedef std::vector<scoped_refptr<VideoFrame> > OutputFrames; |
117 | 117 |
118 // Decodes all buffers in |input_buffers| and push all successfully decoded | 118 // Decodes all buffers in |input_buffers| and push all successfully decoded |
119 // output frames into |output_frames|. | 119 // output frames into |output_frames|. |
120 // Returns the last decode status returned by the decoder. | 120 // Returns the last decode status returned by the decoder. |
121 VideoDecoder::Status DecodeMultipleFrames(const InputBuffers& input_buffers) { | 121 DecodeStatus DecodeMultipleFrames(const InputBuffers& input_buffers) { |
122 for (InputBuffers::const_iterator iter = input_buffers.begin(); | 122 for (InputBuffers::const_iterator iter = input_buffers.begin(); |
123 iter != input_buffers.end(); | 123 iter != input_buffers.end(); |
124 ++iter) { | 124 ++iter) { |
125 VideoDecoder::Status status = Decode(*iter); | 125 DecodeStatus status = Decode(*iter); |
126 switch (status) { | 126 switch (status) { |
127 case VideoDecoder::kOk: | 127 case DecodeStatus::OK: |
128 break; | 128 break; |
129 case VideoDecoder::kAborted: | 129 case DecodeStatus::ABORTED: |
130 NOTREACHED(); | 130 NOTREACHED(); |
131 case VideoDecoder::kDecodeError: | 131 case DecodeStatus::DECODE_ERROR: |
132 DCHECK(output_frames_.empty()); | 132 DCHECK(output_frames_.empty()); |
133 return status; | 133 return status; |
134 } | 134 } |
135 } | 135 } |
136 return VideoDecoder::kOk; | 136 return DecodeStatus::OK; |
137 } | 137 } |
138 | 138 |
139 // Decodes the single compressed frame in |buffer| and writes the | 139 // Decodes the single compressed frame in |buffer| and writes the |
140 // uncompressed output to |video_frame|. This method works with single | 140 // uncompressed output to |video_frame|. This method works with single |
141 // and multithreaded decoders. End of stream buffers are used to trigger | 141 // and multithreaded decoders. End of stream buffers are used to trigger |
142 // the frame to be returned in the multithreaded decoder case. | 142 // the frame to be returned in the multithreaded decoder case. |
143 VideoDecoder::Status DecodeSingleFrame( | 143 DecodeStatus DecodeSingleFrame(const scoped_refptr<DecoderBuffer>& buffer) { |
144 const scoped_refptr<DecoderBuffer>& buffer) { | |
145 InputBuffers input_buffers; | 144 InputBuffers input_buffers; |
146 input_buffers.push_back(buffer); | 145 input_buffers.push_back(buffer); |
147 input_buffers.push_back(end_of_stream_buffer_); | 146 input_buffers.push_back(end_of_stream_buffer_); |
148 | 147 |
149 return DecodeMultipleFrames(input_buffers); | 148 return DecodeMultipleFrames(input_buffers); |
150 } | 149 } |
151 | 150 |
152 // Decodes |i_frame_buffer_| and then decodes the data contained in | 151 // Decodes |i_frame_buffer_| and then decodes the data contained in |
153 // the file named |test_file_name|. This function expects both buffers | 152 // the file named |test_file_name|. This function expects both buffers |
154 // to decode to frames that are the same size. | 153 // to decode to frames that are the same size. |
155 void DecodeIFrameThenTestFile(const std::string& test_file_name, | 154 void DecodeIFrameThenTestFile(const std::string& test_file_name, |
156 int expected_width, | 155 int expected_width, |
157 int expected_height) { | 156 int expected_height) { |
158 Initialize(); | 157 Initialize(); |
159 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name); | 158 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name); |
160 | 159 |
161 InputBuffers input_buffers; | 160 InputBuffers input_buffers; |
162 input_buffers.push_back(i_frame_buffer_); | 161 input_buffers.push_back(i_frame_buffer_); |
163 input_buffers.push_back(buffer); | 162 input_buffers.push_back(buffer); |
164 input_buffers.push_back(end_of_stream_buffer_); | 163 input_buffers.push_back(end_of_stream_buffer_); |
165 | 164 |
166 VideoDecoder::Status status = | 165 DecodeStatus status = DecodeMultipleFrames(input_buffers); |
167 DecodeMultipleFrames(input_buffers); | |
168 | 166 |
169 EXPECT_EQ(VideoDecoder::kOk, status); | 167 EXPECT_EQ(DecodeStatus::OK, status); |
170 ASSERT_EQ(2U, output_frames_.size()); | 168 ASSERT_EQ(2U, output_frames_.size()); |
171 | 169 |
172 gfx::Size original_size = kVisibleRect.size(); | 170 gfx::Size original_size = kVisibleRect.size(); |
173 EXPECT_EQ(original_size.width(), | 171 EXPECT_EQ(original_size.width(), |
174 output_frames_[0]->visible_rect().size().width()); | 172 output_frames_[0]->visible_rect().size().width()); |
175 EXPECT_EQ(original_size.height(), | 173 EXPECT_EQ(original_size.height(), |
176 output_frames_[0]->visible_rect().size().height()); | 174 output_frames_[0]->visible_rect().size().height()); |
177 EXPECT_EQ(expected_width, | 175 EXPECT_EQ(expected_width, |
178 output_frames_[1]->visible_rect().size().width()); | 176 output_frames_[1]->visible_rect().size().width()); |
179 EXPECT_EQ(expected_height, | 177 EXPECT_EQ(expected_height, |
180 output_frames_[1]->visible_rect().size().height()); | 178 output_frames_[1]->visible_rect().size().height()); |
181 } | 179 } |
182 | 180 |
183 VideoDecoder::Status Decode(const scoped_refptr<DecoderBuffer>& buffer) { | 181 DecodeStatus Decode(const scoped_refptr<DecoderBuffer>& buffer) { |
184 VideoDecoder::Status status; | 182 DecodeStatus status; |
185 EXPECT_CALL(*this, DecodeDone(_)).WillOnce(SaveArg<0>(&status)); | 183 EXPECT_CALL(*this, DecodeDone(_)).WillOnce(SaveArg<0>(&status)); |
186 | 184 |
187 decoder_->Decode(buffer, decode_cb_); | 185 decoder_->Decode(buffer, decode_cb_); |
188 | 186 |
189 message_loop_.RunUntilIdle(); | 187 message_loop_.RunUntilIdle(); |
190 | 188 |
191 return status; | 189 return status; |
192 } | 190 } |
193 | 191 |
194 void FrameReady(const scoped_refptr<VideoFrame>& frame) { | 192 void FrameReady(const scoped_refptr<VideoFrame>& frame) { |
195 DCHECK(!frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)); | 193 DCHECK(!frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)); |
196 output_frames_.push_back(frame); | 194 output_frames_.push_back(frame); |
197 } | 195 } |
198 | 196 |
199 MOCK_METHOD1(DecodeDone, void(VideoDecoder::Status)); | 197 MOCK_METHOD1(DecodeDone, void(DecodeStatus)); |
200 | 198 |
201 base::MessageLoop message_loop_; | 199 base::MessageLoop message_loop_; |
202 scoped_ptr<FFmpegVideoDecoder> decoder_; | 200 scoped_ptr<FFmpegVideoDecoder> decoder_; |
203 | 201 |
204 VideoDecoder::DecodeCB decode_cb_; | 202 VideoDecoder::DecodeCB decode_cb_; |
205 | 203 |
206 // Various buffers for testing. | 204 // Various buffers for testing. |
207 scoped_ptr<uint8_t[]> frame_buffer_; | 205 scoped_ptr<uint8_t[]> frame_buffer_; |
208 scoped_refptr<DecoderBuffer> end_of_stream_buffer_; | 206 scoped_refptr<DecoderBuffer> end_of_stream_buffer_; |
209 scoped_refptr<DecoderBuffer> i_frame_buffer_; | 207 scoped_refptr<DecoderBuffer> i_frame_buffer_; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 Initialize(); | 241 Initialize(); |
244 EnterDecodingState(); | 242 EnterDecodingState(); |
245 Reset(); | 243 Reset(); |
246 Reinitialize(); | 244 Reinitialize(); |
247 } | 245 } |
248 | 246 |
249 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_Normal) { | 247 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_Normal) { |
250 Initialize(); | 248 Initialize(); |
251 | 249 |
252 // Simulate decoding a single frame. | 250 // Simulate decoding a single frame. |
253 EXPECT_EQ(VideoDecoder::kOk, DecodeSingleFrame(i_frame_buffer_)); | 251 EXPECT_EQ(DecodeStatus::OK, DecodeSingleFrame(i_frame_buffer_)); |
254 ASSERT_EQ(1U, output_frames_.size()); | 252 ASSERT_EQ(1U, output_frames_.size()); |
255 } | 253 } |
256 | 254 |
257 // Verify current behavior for 0 byte frames. FFmpeg simply ignores | 255 // Verify current behavior for 0 byte frames. FFmpeg simply ignores |
258 // the 0 byte frames. | 256 // the 0 byte frames. |
259 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_0ByteFrame) { | 257 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_0ByteFrame) { |
260 Initialize(); | 258 Initialize(); |
261 | 259 |
262 scoped_refptr<DecoderBuffer> zero_byte_buffer = new DecoderBuffer(0); | 260 scoped_refptr<DecoderBuffer> zero_byte_buffer = new DecoderBuffer(0); |
263 | 261 |
264 InputBuffers input_buffers; | 262 InputBuffers input_buffers; |
265 input_buffers.push_back(i_frame_buffer_); | 263 input_buffers.push_back(i_frame_buffer_); |
266 input_buffers.push_back(zero_byte_buffer); | 264 input_buffers.push_back(zero_byte_buffer); |
267 input_buffers.push_back(i_frame_buffer_); | 265 input_buffers.push_back(i_frame_buffer_); |
268 input_buffers.push_back(end_of_stream_buffer_); | 266 input_buffers.push_back(end_of_stream_buffer_); |
269 | 267 |
270 VideoDecoder::Status status = DecodeMultipleFrames(input_buffers); | 268 DecodeStatus status = DecodeMultipleFrames(input_buffers); |
271 | 269 |
272 EXPECT_EQ(VideoDecoder::kOk, status); | 270 EXPECT_EQ(DecodeStatus::OK, status); |
273 ASSERT_EQ(2U, output_frames_.size()); | 271 ASSERT_EQ(2U, output_frames_.size()); |
274 } | 272 } |
275 | 273 |
276 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeError) { | 274 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeError) { |
277 Initialize(); | 275 Initialize(); |
278 | 276 |
279 // The error is only raised on the second decode attempt, so we expect at | 277 // The error is only raised on the second decode attempt, so we expect at |
280 // least one successful decode but we don't expect valid frame to be decoded. | 278 // least one successful decode but we don't expect valid frame to be decoded. |
281 // During the second decode attempt an error is raised. | 279 // During the second decode attempt an error is raised. |
282 EXPECT_EQ(VideoDecoder::kOk, Decode(corrupt_i_frame_buffer_)); | 280 EXPECT_EQ(DecodeStatus::OK, Decode(corrupt_i_frame_buffer_)); |
283 EXPECT_TRUE(output_frames_.empty()); | 281 EXPECT_TRUE(output_frames_.empty()); |
284 EXPECT_EQ(VideoDecoder::kDecodeError, Decode(i_frame_buffer_)); | 282 EXPECT_EQ(DecodeStatus::DECODE_ERROR, Decode(i_frame_buffer_)); |
285 EXPECT_TRUE(output_frames_.empty()); | 283 EXPECT_TRUE(output_frames_.empty()); |
286 | 284 |
287 // After a decode error occurred, all following decodes will return | 285 // After a decode error occurred, all following decodes will return |
288 // kDecodeError. | 286 // DecodeStatus::DECODE_ERROR. |
289 EXPECT_EQ(VideoDecoder::kDecodeError, Decode(i_frame_buffer_)); | 287 EXPECT_EQ(DecodeStatus::DECODE_ERROR, Decode(i_frame_buffer_)); |
290 EXPECT_TRUE(output_frames_.empty()); | 288 EXPECT_TRUE(output_frames_.empty()); |
291 } | 289 } |
292 | 290 |
293 // A corrupt frame followed by an EOS buffer should raise a decode error. | 291 // A corrupt frame followed by an EOS buffer should raise a decode error. |
294 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeErrorAtEndOfStream) { | 292 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeErrorAtEndOfStream) { |
295 Initialize(); | 293 Initialize(); |
296 | 294 |
297 EXPECT_EQ(VideoDecoder::kDecodeError, | 295 EXPECT_EQ(DecodeStatus::DECODE_ERROR, |
298 DecodeSingleFrame(corrupt_i_frame_buffer_)); | 296 DecodeSingleFrame(corrupt_i_frame_buffer_)); |
299 } | 297 } |
300 | 298 |
301 // Decode |i_frame_buffer_| and then a frame with a larger width and verify | 299 // Decode |i_frame_buffer_| and then a frame with a larger width and verify |
302 // the output size was adjusted. | 300 // the output size was adjusted. |
303 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_LargerWidth) { | 301 TEST_F(FFmpegVideoDecoderTest, DecodeFrame_LargerWidth) { |
304 DecodeIFrameThenTestFile("vp8-I-frame-640x240", 640, 240); | 302 DecodeIFrameThenTestFile("vp8-I-frame-640x240", 640, 240); |
305 } | 303 } |
306 | 304 |
307 // Decode |i_frame_buffer_| and then a frame with a smaller width and verify | 305 // Decode |i_frame_buffer_| and then a frame with a smaller width and verify |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 | 356 |
359 // Test destruction when decoder has hit end of stream. | 357 // Test destruction when decoder has hit end of stream. |
360 TEST_F(FFmpegVideoDecoderTest, Destroy_EndOfStream) { | 358 TEST_F(FFmpegVideoDecoderTest, Destroy_EndOfStream) { |
361 Initialize(); | 359 Initialize(); |
362 EnterDecodingState(); | 360 EnterDecodingState(); |
363 EnterEndOfStreamState(); | 361 EnterEndOfStreamState(); |
364 Destroy(); | 362 Destroy(); |
365 } | 363 } |
366 | 364 |
367 } // namespace media | 365 } // namespace media |
OLD | NEW |