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

Side by Side Diff: media/video/ffmpeg_video_decode_engine_unittest.cc

Issue 6156002: Merge 70703 - Handle changes in video frame size.... (Closed) Base URL: svn://svn.chromium.org/chrome/branches/597/src/
Patch Set: Created 9 years, 11 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/video/ffmpeg_video_decode_engine.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "base/message_loop.h" 5 #include "base/message_loop.h"
6 #include "base/scoped_ptr.h" 6 #include "base/scoped_ptr.h"
7 #include "media/base/data_buffer.h" 7 #include "media/base/data_buffer.h"
8 #include "media/base/mock_ffmpeg.h" 8 #include "media/base/mock_ffmpeg.h"
9 #include "media/base/mock_task.h" 9 #include "media/base/mock_task.h"
10 #include "media/video/ffmpeg_video_decode_engine.h" 10 #include "media/video/ffmpeg_video_decode_engine.h"
11 #include "testing/gmock/include/gmock/gmock.h" 11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h" 12 #include "testing/gtest/include/gtest/gtest.h"
13 13
14 using ::testing::_; 14 using ::testing::_;
15 using ::testing::DoAll; 15 using ::testing::DoAll;
16 using ::testing::Return; 16 using ::testing::Return;
17 using ::testing::ReturnNull; 17 using ::testing::ReturnNull;
18 using ::testing::SetArgumentPointee; 18 using ::testing::SetArgumentPointee;
19 using ::testing::StrictMock; 19 using ::testing::StrictMock;
20 20
21 namespace media { 21 namespace media {
22 22
23 static const int kWidth = 320; 23 static const int kWidth = 320;
24 static const int kHeight = 240; 24 static const int kHeight = 240;
25 static const AVRational kTimeBase = { 1, 100 }; 25 static const AVRational kTimeBase = { 1, 100 };
26 26
27 static void InitializeFrame(uint8_t* data, int width, AVFrame* frame) {
28 frame->data[0] = data;
29 frame->data[1] = data;
30 frame->data[2] = data;
31 frame->linesize[0] = width;
32 frame->linesize[1] = width / 2;
33 frame->linesize[2] = width / 2;
34 }
35
36 ACTION_P(DecodeComplete, decoder) {
37 decoder->video_frame_ = arg0;
38 }
39
40 ACTION_P2(DemuxComplete, engine, buffer) {
41 engine->ConsumeVideoSample(buffer);
42 }
43
27 ACTION_P(SaveInitializeResult, engine) { 44 ACTION_P(SaveInitializeResult, engine) {
28 engine->info_ = arg0; 45 engine->info_ = arg0;
29 } 46 }
30 47
31 class FFmpegVideoDecodeEngineTest : public testing::Test, 48 class FFmpegVideoDecodeEngineTest : public testing::Test,
32 public VideoDecodeEngine::EventHandler { 49 public VideoDecodeEngine::EventHandler {
33 protected: 50 protected:
34 FFmpegVideoDecodeEngineTest() { 51 FFmpegVideoDecodeEngineTest() {
35 // Setup FFmpeg structures. 52 // Setup FFmpeg structures.
36 frame_buffer_.reset(new uint8[kWidth * kHeight]); 53 frame_buffer_.reset(new uint8[kWidth * kHeight]);
37 memset(&yuv_frame_, 0, sizeof(yuv_frame_)); 54 memset(&yuv_frame_, 0, sizeof(yuv_frame_));
38 55 InitializeFrame(frame_buffer_.get(), kWidth, &yuv_frame_);
39 // DecodeFrame will check these pointers as non-NULL value.
40 yuv_frame_.data[0] = yuv_frame_.data[1] = yuv_frame_.data[2]
41 = frame_buffer_.get();
42 yuv_frame_.linesize[0] = kWidth;
43 yuv_frame_.linesize[1] = yuv_frame_.linesize[2] = kWidth >> 1;
44 56
45 memset(&codec_context_, 0, sizeof(codec_context_)); 57 memset(&codec_context_, 0, sizeof(codec_context_));
46 codec_context_.width = kWidth; 58 codec_context_.width = kWidth;
47 codec_context_.height = kHeight; 59 codec_context_.height = kHeight;
48 codec_context_.time_base = kTimeBase; 60 codec_context_.time_base = kTimeBase;
49 61
50 memset(&codec_, 0, sizeof(codec_)); 62 memset(&codec_, 0, sizeof(codec_));
51 memset(&stream_, 0, sizeof(stream_)); 63 memset(&stream_, 0, sizeof(stream_));
52 stream_.codec = &codec_context_; 64 stream_.codec = &codec_context_;
53 stream_.r_frame_rate.num = kTimeBase.den; 65 stream_.r_frame_rate.num = kTimeBase.den;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 config_.codec = kCodecH264; 101 config_.codec = kCodecH264;
90 config_.opaque_context = &stream_; 102 config_.opaque_context = &stream_;
91 config_.width = kWidth; 103 config_.width = kWidth;
92 config_.height = kHeight; 104 config_.height = kHeight;
93 EXPECT_CALL(*this, OnInitializeComplete(_)) 105 EXPECT_CALL(*this, OnInitializeComplete(_))
94 .WillOnce(SaveInitializeResult(this)); 106 .WillOnce(SaveInitializeResult(this));
95 test_engine_->Initialize(MessageLoop::current(), this, NULL, config_); 107 test_engine_->Initialize(MessageLoop::current(), this, NULL, config_);
96 EXPECT_TRUE(info_.success); 108 EXPECT_TRUE(info_.success);
97 } 109 }
98 110
111 void Decode() {
112 EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_));
113 EXPECT_CALL(mock_ffmpeg_,
114 AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
115 .WillOnce(DoAll(SetArgumentPointee<2>(1), // Simulate 1 byte frame.
116 Return(0)));
117
118 EXPECT_CALL(*this, ProduceVideoSample(_))
119 .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
120 EXPECT_CALL(*this, ConsumeVideoFrame(_))
121 .WillOnce(DecodeComplete(this));
122 test_engine_->ProduceVideoFrame(video_frame_);
123 }
124
125 void ChangeDimensions(int width, int height) {
126 frame_buffer_.reset(new uint8[width * height]);
127 InitializeFrame(frame_buffer_.get(), width, &yuv_frame_);
128 codec_context_.width = width;
129 codec_context_.height = height;
130 }
131
99 public: 132 public:
100 MOCK_METHOD1(ConsumeVideoFrame, 133 MOCK_METHOD1(ConsumeVideoFrame,
101 void(scoped_refptr<VideoFrame> video_frame)); 134 void(scoped_refptr<VideoFrame> video_frame));
102 MOCK_METHOD1(ProduceVideoSample, 135 MOCK_METHOD1(ProduceVideoSample,
103 void(scoped_refptr<Buffer> buffer)); 136 void(scoped_refptr<Buffer> buffer));
104 MOCK_METHOD1(OnInitializeComplete, 137 MOCK_METHOD1(OnInitializeComplete,
105 void(const VideoCodecInfo& info)); 138 void(const VideoCodecInfo& info));
106 MOCK_METHOD0(OnUninitializeComplete, void()); 139 MOCK_METHOD0(OnUninitializeComplete, void());
107 MOCK_METHOD0(OnFlushComplete, void()); 140 MOCK_METHOD0(OnFlushComplete, void());
108 MOCK_METHOD0(OnSeekComplete, void()); 141 MOCK_METHOD0(OnSeekComplete, void());
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 config_.codec = kCodecH264; 219 config_.codec = kCodecH264;
187 config_.opaque_context = &stream_; 220 config_.opaque_context = &stream_;
188 config_.width = kWidth; 221 config_.width = kWidth;
189 config_.height = kHeight; 222 config_.height = kHeight;
190 EXPECT_CALL(*this, OnInitializeComplete(_)) 223 EXPECT_CALL(*this, OnInitializeComplete(_))
191 .WillOnce(SaveInitializeResult(this)); 224 .WillOnce(SaveInitializeResult(this));
192 test_engine_->Initialize(MessageLoop::current(), this, NULL, config_); 225 test_engine_->Initialize(MessageLoop::current(), this, NULL, config_);
193 EXPECT_FALSE(info_.success); 226 EXPECT_FALSE(info_.success);
194 } 227 }
195 228
196 ACTION_P2(DemuxComplete, engine, buffer) {
197 engine->ConsumeVideoSample(buffer);
198 }
199
200 ACTION_P(DecodeComplete, decoder) {
201 decoder->video_frame_ = arg0;
202 }
203
204 TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_Normal) { 229 TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_Normal) {
205 Initialize(); 230 Initialize();
206 231
207 // We rely on FFmpeg for timestamp and duration reporting. The one tricky 232 // We rely on FFmpeg for timestamp and duration reporting. The one tricky
208 // bit is calculating the duration when |repeat_pict| > 0. 233 // bit is calculating the duration when |repeat_pict| > 0.
209 const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(123); 234 const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(123);
210 const base::TimeDelta kDuration = base::TimeDelta::FromMicroseconds(15000); 235 const base::TimeDelta kDuration = base::TimeDelta::FromMicroseconds(15000);
211 yuv_frame_.repeat_pict = 1; 236 yuv_frame_.repeat_pict = 1;
212 yuv_frame_.reordered_opaque = kTimestamp.InMicroseconds(); 237 yuv_frame_.reordered_opaque = kTimestamp.InMicroseconds();
213 238
214 // Expect a bunch of avcodec calls. 239 // Simulate decoding a single frame.
215 EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_)); 240 Decode();
216 EXPECT_CALL(mock_ffmpeg_,
217 AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
218 .WillOnce(DoAll(SetArgumentPointee<2>(1), // Simulate 1 byte frame.
219 Return(0)));
220
221 EXPECT_CALL(*this, ProduceVideoSample(_))
222 .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
223 EXPECT_CALL(*this, ConsumeVideoFrame(_))
224 .WillOnce(DecodeComplete(this));
225 test_engine_->ProduceVideoFrame(video_frame_);
226 241
227 // |video_frame_| timestamp is 0 because we set the timestamp based off 242 // |video_frame_| timestamp is 0 because we set the timestamp based off
228 // the buffer timestamp. 243 // the buffer timestamp.
229 EXPECT_EQ(0, video_frame_->GetTimestamp().ToInternalValue()); 244 EXPECT_EQ(0, video_frame_->GetTimestamp().ToInternalValue());
230 EXPECT_EQ(kDuration.ToInternalValue(), 245 EXPECT_EQ(kDuration.ToInternalValue(),
231 video_frame_->GetDuration().ToInternalValue()); 246 video_frame_->GetDuration().ToInternalValue());
232 } 247 }
233 248
234 TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_0ByteFrame) { 249 TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_0ByteFrame) {
235 Initialize(); 250 Initialize();
(...skipping 29 matching lines...) Expand all
265 280
266 EXPECT_CALL(*this, ProduceVideoSample(_)) 281 EXPECT_CALL(*this, ProduceVideoSample(_))
267 .WillOnce(DemuxComplete(test_engine_.get(), buffer_)); 282 .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
268 EXPECT_CALL(*this, ConsumeVideoFrame(_)) 283 EXPECT_CALL(*this, ConsumeVideoFrame(_))
269 .WillOnce(DecodeComplete(this)); 284 .WillOnce(DecodeComplete(this));
270 test_engine_->ProduceVideoFrame(video_frame_); 285 test_engine_->ProduceVideoFrame(video_frame_);
271 286
272 EXPECT_FALSE(video_frame_.get()); 287 EXPECT_FALSE(video_frame_.get());
273 } 288 }
274 289
290 TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_LargerWidth) {
291 Initialize();
292 ChangeDimensions(kWidth * 2, kHeight);
293 Decode();
294 }
295
296 TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_SmallerWidth) {
297 Initialize();
298 ChangeDimensions(kWidth / 2, kHeight);
299 Decode();
300 }
301
302 TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_LargerHeight) {
303 Initialize();
304 ChangeDimensions(kWidth, kHeight * 2);
305 Decode();
306 }
307
308 TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_SmallerHeight) {
309 Initialize();
310 ChangeDimensions(kWidth, kHeight / 2);
311 Decode();
312 }
313
275 TEST_F(FFmpegVideoDecodeEngineTest, GetSurfaceFormat) { 314 TEST_F(FFmpegVideoDecodeEngineTest, GetSurfaceFormat) {
276 // YV12 formats. 315 // YV12 formats.
277 codec_context_.pix_fmt = PIX_FMT_YUV420P; 316 codec_context_.pix_fmt = PIX_FMT_YUV420P;
278 EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat()); 317 EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat());
279 codec_context_.pix_fmt = PIX_FMT_YUVJ420P; 318 codec_context_.pix_fmt = PIX_FMT_YUVJ420P;
280 EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat()); 319 EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat());
281 320
282 // YV16 formats. 321 // YV16 formats.
283 codec_context_.pix_fmt = PIX_FMT_YUV422P; 322 codec_context_.pix_fmt = PIX_FMT_YUV422P;
284 EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat()); 323 EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat());
285 codec_context_.pix_fmt = PIX_FMT_YUVJ422P; 324 codec_context_.pix_fmt = PIX_FMT_YUVJ422P;
286 EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat()); 325 EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat());
287 326
288 // Invalid value. 327 // Invalid value.
289 codec_context_.pix_fmt = PIX_FMT_NONE; 328 codec_context_.pix_fmt = PIX_FMT_NONE;
290 EXPECT_EQ(VideoFrame::INVALID, test_engine_->GetSurfaceFormat()); 329 EXPECT_EQ(VideoFrame::INVALID, test_engine_->GetSurfaceFormat());
291 } 330 }
292 331
293 } // namespace media 332 } // namespace media
OLDNEW
« no previous file with comments | « media/video/ffmpeg_video_decode_engine.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698