2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
10 #include "vpx_config.h"
11 #include "test/encode_test_driver.h"
12 #if CONFIG_VP8_DECODER
13 #include "test/decode_test_driver.h"
15 #include "test/register_state_check.h"
16 #include "test/video_source.h"
17 #include "third_party/googletest/src/include/gtest/gtest.h"
19 namespace libvpx_test
{
20 void Encoder::EncodeFrame(VideoSource
*video
, const unsigned long frame_flags
) {
22 EncodeFrameInternal(*video
, frame_flags
);
26 // Handle twopass stats
27 CxDataIterator iter
= GetCxData();
29 while (const vpx_codec_cx_pkt_t
*pkt
= iter
.Next()) {
30 if (pkt
->kind
!= VPX_CODEC_STATS_PKT
)
37 void Encoder::EncodeFrameInternal(const VideoSource
&video
,
38 const unsigned long frame_flags
) {
40 const vpx_image_t
*img
= video
.img();
42 // Handle first frame initialization
46 cfg_
.g_timebase
= video
.timebase();
47 cfg_
.rc_twopass_stats_in
= stats_
->buf();
48 res
= vpx_codec_enc_init(&encoder_
, &vpx_codec_vp8_cx_algo
, &cfg_
,
50 ASSERT_EQ(VPX_CODEC_OK
, res
) << EncoderError();
53 // Handle frame resizing
54 if (cfg_
.g_w
!= img
->d_w
|| cfg_
.g_h
!= img
->d_h
) {
57 res
= vpx_codec_enc_config_set(&encoder_
, &cfg_
);
58 ASSERT_EQ(VPX_CODEC_OK
, res
) << EncoderError();
63 res
= vpx_codec_encode(&encoder_
,
64 video
.img(), video
.pts(), video
.duration(),
65 frame_flags
, deadline_
));
66 ASSERT_EQ(VPX_CODEC_OK
, res
) << EncoderError();
69 void Encoder::Flush() {
70 const vpx_codec_err_t res
= vpx_codec_encode(&encoder_
, NULL
, 0, 0, 0,
72 ASSERT_EQ(VPX_CODEC_OK
, res
) << EncoderError();
75 void EncoderTest::SetMode(TestMode mode
) {
78 deadline_
= VPX_DL_REALTIME
;
83 deadline_
= VPX_DL_GOOD_QUALITY
;
88 deadline_
= VPX_DL_BEST_QUALITY
;
92 ASSERT_TRUE(false) << "Unexpected mode " << mode
;
95 if (mode
== kTwoPassGood
|| mode
== kTwoPassBest
)
100 // The function should return "true" most of the time, therefore no early
101 // break-out is implemented within the match checking process.
102 static bool compare_img(const vpx_image_t
*img1
,
103 const vpx_image_t
*img2
) {
104 bool match
= (img1
->fmt
== img2
->fmt
) &&
105 (img1
->d_w
== img2
->d_w
) &&
106 (img1
->d_h
== img2
->d_h
);
108 const unsigned int width_y
= img1
->d_w
;
109 const unsigned int height_y
= img1
->d_h
;
111 for (i
= 0; i
< height_y
; ++i
)
112 match
= ( memcmp(img1
->planes
[VPX_PLANE_Y
] + i
* img1
->stride
[VPX_PLANE_Y
],
113 img2
->planes
[VPX_PLANE_Y
] + i
* img2
->stride
[VPX_PLANE_Y
],
114 width_y
) == 0) && match
;
115 const unsigned int width_uv
= (img1
->d_w
+ 1) >> 1;
116 const unsigned int height_uv
= (img1
->d_h
+ 1) >> 1;
117 for (i
= 0; i
< height_uv
; ++i
)
118 match
= ( memcmp(img1
->planes
[VPX_PLANE_U
] + i
* img1
->stride
[VPX_PLANE_U
],
119 img2
->planes
[VPX_PLANE_U
] + i
* img2
->stride
[VPX_PLANE_U
],
120 width_uv
) == 0) && match
;
121 for (i
= 0; i
< height_uv
; ++i
)
122 match
= ( memcmp(img1
->planes
[VPX_PLANE_V
] + i
* img1
->stride
[VPX_PLANE_V
],
123 img2
->planes
[VPX_PLANE_V
] + i
* img2
->stride
[VPX_PLANE_V
],
124 width_uv
) == 0) && match
;
128 void EncoderTest::RunLoop(VideoSource
*video
) {
129 #if CONFIG_VP8_DECODER
130 vpx_codec_dec_cfg_t dec_cfg
= {0};
135 for (unsigned int pass
= 0; pass
< passes_
; pass
++) {
139 cfg_
.g_pass
= VPX_RC_ONE_PASS
;
141 cfg_
.g_pass
= VPX_RC_FIRST_PASS
;
143 cfg_
.g_pass
= VPX_RC_LAST_PASS
;
146 Encoder
encoder(cfg_
, deadline_
, init_flags_
, &stats_
);
147 #if CONFIG_VP8_DECODER
148 Decoder
decoder(dec_cfg
, 0);
149 bool has_cxdata
= false;
152 for (again
= true, video
->Begin(); again
; video
->Next()) {
153 again
= video
->img() != NULL
;
155 PreEncodeFrameHook(video
);
156 PreEncodeFrameHook(video
, &encoder
);
157 encoder
.EncodeFrame(video
, frame_flags_
);
159 CxDataIterator iter
= encoder
.GetCxData();
161 while (const vpx_codec_cx_pkt_t
*pkt
= iter
.Next()) {
165 case VPX_CODEC_CX_FRAME_PKT
:
166 #if CONFIG_VP8_DECODER
168 decoder
.DecodeFrame((const uint8_t*)pkt
->data
.frame
.buf
,
171 ASSERT_GE(pkt
->data
.frame
.pts
, last_pts_
);
172 last_pts_
= pkt
->data
.frame
.pts
;
176 case VPX_CODEC_PSNR_PKT
:
185 #if CONFIG_VP8_DECODER
187 const vpx_image_t
*img_enc
= encoder
.GetPreviewFrame();
188 DxDataIterator dec_iter
= decoder
.GetDxData();
189 const vpx_image_t
*img_dec
= dec_iter
.Next();
190 if(img_enc
&& img_dec
) {
191 const bool res
= compare_img(img_enc
, img_dec
);
192 ASSERT_TRUE(res
)<< "Encoder/Decoder mismatch found.";
206 } // namespace libvpx_test