56 #include "vp9/common/vp9_common.h"
58 #include "./tools_common.h"
59 #include "./video_writer.h"
61 static const char *exec_name;
65 "Usage: %s <width> <height> <infile> <outfile> "
66 "<frame> <limit(optional)>\n",
71 static int compare_img(
const vpx_image_t *
const img1,
73 uint32_t l_w = img1->
d_w;
80 match &= (img1->
fmt == img2->
fmt);
81 match &= (img1->
d_w == img2->
d_w);
82 match &= (img1->
d_h == img2->
d_h);
84 for (i = 0; i < img1->
d_h; ++i)
89 for (i = 0; i < c_h; ++i)
94 for (i = 0; i < c_h; ++i)
102 #define mmin(a, b) ((a) < (b) ? (a) : (b))
103 static void find_mismatch(
const vpx_image_t *
const img1,
105 int uloc[4],
int vloc[4]) {
106 const uint32_t bsize = 64;
115 yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1;
116 for (i = 0, match = 1; match && i < img1->
d_h; i += bsize) {
117 for (j = 0; match && j < img1->
d_w; j += bsize) {
119 const int si = mmin(i + bsize, img1->
d_h) - i;
120 const int sj = mmin(j + bsize, img1->
d_w) - j;
121 for (k = 0; match && k < si; ++k) {
122 for (l = 0; match && l < sj; ++l) {
141 uloc[0] = uloc[1] = uloc[2] = uloc[3] = -1;
142 for (i = 0, match = 1; match && i < c_h; i += bsizey) {
143 for (j = 0; match && j < c_w; j += bsizex) {
145 const int si = mmin(i + bsizey, c_h - i);
146 const int sj = mmin(j + bsizex, c_w - j);
147 for (k = 0; match && k < si; ++k) {
148 for (l = 0; match && l < sj; ++l) {
166 vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1;
167 for (i = 0, match = 1; match && i < c_h; i += bsizey) {
168 for (j = 0; match && j < c_w; j += bsizex) {
170 const int si = mmin(i + bsizey, c_h - i);
171 const int sj = mmin(j + bsizex, c_w - j);
172 for (k = 0; match && k < si; ++k) {
173 for (l = 0; match && l < sj; ++l) {
194 unsigned int frame_out,
int *mismatch_seen) {
198 if (*mismatch_seen)
return;
203 die_codec(encoder,
"Failed to get encoder reference frame");
204 enc_img = ref_enc.img;
206 die_codec(decoder,
"Failed to get decoder reference frame");
207 dec_img = ref_dec.img;
209 if (!compare_img(&enc_img, &dec_img)) {
210 int y[4], u[4], v[4];
214 find_mismatch(&enc_img, &dec_img, y, u, v);
216 "Encode/decode mismatch on frame %d at"
217 " Y[%d, %d] {%d/%d},"
218 " U[%d, %d] {%d/%d},"
219 " V[%d, %d] {%d/%d}",
220 frame_out, y[0], y[1], y[2], y[3], u[0], u[1], u[2], u[3], v[0], v[1],
229 unsigned int frame_in, VpxVideoWriter *writer,
231 unsigned int *frame_out,
int *mismatch_seen) {
238 if (res !=
VPX_CODEC_OK) die_codec(ecodec,
"Failed to encode frame");
252 if (!vpx_video_writer_write_frame(writer, pkt->
data.
frame.buf,
255 die_codec(ecodec,
"Failed to write compressed frame");
257 printf(keyframe ?
"K" :
".");
264 (
unsigned int)pkt->
data.
frame.sz, NULL, 0))
265 die_codec(dcodec,
"Failed to decode frame.");
271 if (got_data && test_decode) {
272 testing_decode(ecodec, dcodec, *frame_out, mismatch_seen);
278 int main(
int argc,
char **argv) {
283 unsigned int frame_in = 0;
287 VpxVideoWriter *writer = NULL;
288 const VpxInterface *encoder = NULL;
294 unsigned int frame_out = 0;
297 unsigned int update_frame_num = 0;
298 int mismatch_seen = 0;
301 const int bitrate = 500;
303 const char *width_arg = NULL;
304 const char *height_arg = NULL;
305 const char *infile_arg = NULL;
306 const char *outfile_arg = NULL;
307 const char *update_frame_num_arg = NULL;
308 unsigned int limit = 0;
316 if (argc < 6) die(
"Invalid number of arguments");
319 height_arg = argv[2];
320 infile_arg = argv[3];
321 outfile_arg = argv[4];
322 update_frame_num_arg = argv[5];
324 encoder = get_vpx_encoder_by_name(
"vp9");
325 if (!encoder) die(
"Unsupported codec.");
327 update_frame_num = (
unsigned int)strtoul(update_frame_num_arg, NULL, 0);
331 if (update_frame_num <= 1) {
332 die(
"Couldn't parse frame number '%s'\n", update_frame_num_arg);
336 limit = (
unsigned int)strtoul(argv[6], NULL, 0);
337 if (update_frame_num > limit)
338 die(
"Update frame number couldn't larger than limit\n");
341 info.codec_fourcc = encoder->fourcc;
342 info.frame_width = (int)strtol(width_arg, NULL, 0);
343 info.frame_height = (int)strtol(height_arg, NULL, 0);
344 info.time_base.numerator = 1;
345 info.time_base.denominator = fps;
347 if (info.frame_width <= 0 || info.frame_height <= 0 ||
348 (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
349 die(
"Invalid frame size: %dx%d", info.frame_width, info.frame_height);
353 info.frame_height, 1)) {
354 die(
"Failed to allocate image.");
360 if (res) die_codec(&ecodec,
"Failed to get default codec config.");
362 cfg.
g_w = info.frame_width;
363 cfg.
g_h = info.frame_height;
369 writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
370 if (!writer) die(
"Failed to open %s for writing.", outfile_arg);
372 if (!(infile = fopen(infile_arg,
"rb")))
373 die(
"Failed to open %s for reading.", infile_arg);
376 die_codec(&ecodec,
"Failed to initialize encoder");
380 die_codec(&ecodec,
"Failed to set enable auto alt ref");
383 const VpxInterface *decoder = get_vpx_decoder_by_name(
"vp9");
385 die_codec(&dcodec,
"Failed to initialize decoder.");
389 while (vpx_img_read(&raw, infile)) {
390 if (limit && frame_in >= limit)
break;
391 if (update_frame_num > 1 && frame_out + 1 == update_frame_num) {
397 die_codec(&ecodec,
"Failed to set reference frame");
398 printf(
" <SET_REF>");
404 die_codec(&dcodec,
"Failed to set reference frame");
408 encode_frame(&ecodec, &raw, frame_in, writer, test_decode, &dcodec,
409 &frame_out, &mismatch_seen);
411 if (mismatch_seen)
break;
416 while (encode_frame(&ecodec, NULL, frame_in, writer, test_decode, &dcodec,
417 &frame_out, &mismatch_seen)) {
422 printf(
"Processed %d frames.\n", frame_out);
426 printf(
"Encoder/decoder results are matching.\n");
428 printf(
"Encoder/decoder results are NOT matching.\n");
433 die_codec(&dcodec,
"Failed to destroy decoder");
437 die_codec(&ecodec,
"Failed to destroy encoder.");
439 vpx_video_writer_close(writer);