Follow documented decoder API in apps and examples
The current logic in a few of the examples (including aomdec)
doesn't seem to follow the decoder API as documented in
aom/aom_decoder.h.
The decoder API suggests that, after each call to aom_codec_decode(),
we should repeatedly call aom_codec_get_frame() until it returns NULL.
But at the moment, some examples are only calling aom_codec_get_frame()
once, relying on the fact that the decoder currently produces at most
one output frame for each call to aom_codec_decode().
However, this assumption will soon be false, per the linked issue.
So we need to transform the logic from (schematically)
'img = ...; if (img) { do stuff }'
to
'while ((img = ...)) { do stuff }'
BUG=aomedia:1941
Change-Id: Id0c24437afa0c49974aa74c112c94d225721665c
diff --git a/apps/aomdec.c b/apps/aomdec.c
index 8523aa0..c5be76a 100644
--- a/apps/aomdec.c
+++ b/apps/aomdec.c
@@ -834,170 +834,173 @@
}
}
- got_data = 0;
- if ((img = aom_codec_get_frame(&decoder, &iter))) {
- ++frame_out;
- got_data = 1;
- }
-
aom_usec_timer_mark(&timer);
dx_time += aom_usec_timer_elapsed(&timer);
- if (aom_codec_control(&decoder, AOMD_GET_FRAME_CORRUPTED, &corrupted)) {
- warn("Failed AOM_GET_FRAME_CORRUPTED: %s", aom_codec_error(&decoder));
- if (!keep_going) goto fail;
- }
- frames_corrupted += corrupted;
+ got_data = 0;
+ while ((img = aom_codec_get_frame(&decoder, &iter))) {
+ ++frame_out;
+ got_data = 1;
- if (progress) show_progress(frame_in, frame_out, dx_time);
-
- if (!noblit && img) {
- const int PLANES_YUV[] = { AOM_PLANE_Y, AOM_PLANE_U, AOM_PLANE_V };
- const int PLANES_YVU[] = { AOM_PLANE_Y, AOM_PLANE_V, AOM_PLANE_U };
- const int *planes = flipuv ? PLANES_YVU : PLANES_YUV;
-
- if (do_scale) {
- if (frame_out == 1) {
- // If the output frames are to be scaled to a fixed display size then
- // use the width and height specified in the container. If either of
- // these is set to 0, use the display size set in the first frame
- // header. If that is unavailable, use the raw decoded size of the
- // first decoded frame.
- int render_width = aom_input_ctx.width;
- int render_height = aom_input_ctx.height;
- if (!render_width || !render_height) {
- int render_size[2];
- if (aom_codec_control(&decoder, AV1D_GET_DISPLAY_SIZE,
- render_size)) {
- // As last resort use size of first frame as display size.
- render_width = img->d_w;
- render_height = img->d_h;
- } else {
- render_width = render_size[0];
- render_height = render_size[1];
- }
- }
- scaled_img =
- aom_img_alloc(NULL, img->fmt, render_width, render_height, 16);
- scaled_img->bit_depth = img->bit_depth;
- }
-
- if (img->d_w != scaled_img->d_w || img->d_h != scaled_img->d_h) {
-#if CONFIG_LIBYUV
- libyuv_scale(img, scaled_img, kFilterBox);
- img = scaled_img;
-#else
- fprintf(stderr,
- "Failed to scale output frame: %s.\n"
- "libyuv is required for scaling but is currently disabled.\n"
- "Be sure to specify -DCONFIG_LIBYUV=1 when running cmake.\n",
- aom_codec_error(&decoder));
- goto fail;
-#endif
- }
+ if (aom_codec_control(&decoder, AOMD_GET_FRAME_CORRUPTED, &corrupted)) {
+ warn("Failed AOM_GET_FRAME_CORRUPTED: %s", aom_codec_error(&decoder));
+ if (!keep_going) goto fail;
}
- // Default to codec bit depth if output bit depth not set
- if (!output_bit_depth && single_file && !do_md5) {
- output_bit_depth = img->bit_depth;
- }
- // Shift up or down if necessary
- if (output_bit_depth != 0) {
- const aom_img_fmt_t shifted_fmt =
- output_bit_depth == 8
- ? img->fmt ^ (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH)
- : img->fmt | AOM_IMG_FMT_HIGHBITDEPTH;
+ frames_corrupted += corrupted;
- if (shifted_fmt != img->fmt || output_bit_depth != img->bit_depth) {
- if (img_shifted &&
- img_shifted_realloc_required(img, img_shifted, shifted_fmt)) {
- aom_img_free(img_shifted);
- img_shifted = NULL;
- }
- if (!img_shifted) {
- img_shifted =
- aom_img_alloc(NULL, shifted_fmt, img->d_w, img->d_h, 16);
- img_shifted->bit_depth = output_bit_depth;
- img_shifted->monochrome = img->monochrome;
- }
- if (output_bit_depth > img->bit_depth) {
- aom_img_upshift(img_shifted, img,
- output_bit_depth - img->bit_depth);
- } else {
- aom_img_downshift(img_shifted, img,
- img->bit_depth - output_bit_depth);
- }
- img = img_shifted;
- }
- }
+ if (progress) show_progress(frame_in, frame_out, dx_time);
- aom_input_ctx.width = img->d_w;
- aom_input_ctx.height = img->d_h;
+ if (!noblit) {
+ const int PLANES_YUV[] = { AOM_PLANE_Y, AOM_PLANE_U, AOM_PLANE_V };
+ const int PLANES_YVU[] = { AOM_PLANE_Y, AOM_PLANE_V, AOM_PLANE_U };
+ const int *planes = flipuv ? PLANES_YVU : PLANES_YUV;
- int num_planes = (!use_y4m && opt_raw && img->monochrome) ? 1 : 3;
-
- if (single_file) {
- if (use_y4m) {
- char y4m_buf[Y4M_BUFFER_SIZE] = { 0 };
- size_t len = 0;
+ if (do_scale) {
if (frame_out == 1) {
- // Y4M file header
- len = y4m_write_file_header(
- y4m_buf, sizeof(y4m_buf), aom_input_ctx.width,
- aom_input_ctx.height, &aom_input_ctx.framerate, img->fmt,
- img->bit_depth);
+ // If the output frames are to be scaled to a fixed display size
+ // then use the width and height specified in the container. If
+ // either of these is set to 0, use the display size set in the
+ // first frame header. If that is unavailable, use the raw decoded
+ // size of the first decoded frame.
+ int render_width = aom_input_ctx.width;
+ int render_height = aom_input_ctx.height;
+ if (!render_width || !render_height) {
+ int render_size[2];
+ if (aom_codec_control(&decoder, AV1D_GET_DISPLAY_SIZE,
+ render_size)) {
+ // As last resort use size of first frame as display size.
+ render_width = img->d_w;
+ render_height = img->d_h;
+ } else {
+ render_width = render_size[0];
+ render_height = render_size[1];
+ }
+ }
+ scaled_img =
+ aom_img_alloc(NULL, img->fmt, render_width, render_height, 16);
+ scaled_img->bit_depth = img->bit_depth;
+ }
+
+ if (img->d_w != scaled_img->d_w || img->d_h != scaled_img->d_h) {
+#if CONFIG_LIBYUV
+ libyuv_scale(img, scaled_img, kFilterBox);
+ img = scaled_img;
+#else
+ fprintf(
+ stderr,
+ "Failed to scale output frame: %s.\n"
+ "libyuv is required for scaling but is currently disabled.\n"
+ "Be sure to specify -DCONFIG_LIBYUV=1 when running cmake.\n",
+ aom_codec_error(&decoder));
+ goto fail;
+#endif
+ }
+ }
+ // Default to codec bit depth if output bit depth not set
+ if (!output_bit_depth && single_file && !do_md5) {
+ output_bit_depth = img->bit_depth;
+ }
+ // Shift up or down if necessary
+ if (output_bit_depth != 0) {
+ const aom_img_fmt_t shifted_fmt =
+ output_bit_depth == 8
+ ? img->fmt ^ (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH)
+ : img->fmt | AOM_IMG_FMT_HIGHBITDEPTH;
+
+ if (shifted_fmt != img->fmt || output_bit_depth != img->bit_depth) {
+ if (img_shifted &&
+ img_shifted_realloc_required(img, img_shifted, shifted_fmt)) {
+ aom_img_free(img_shifted);
+ img_shifted = NULL;
+ }
+ if (!img_shifted) {
+ img_shifted =
+ aom_img_alloc(NULL, shifted_fmt, img->d_w, img->d_h, 16);
+ img_shifted->bit_depth = output_bit_depth;
+ img_shifted->monochrome = img->monochrome;
+ }
+ if (output_bit_depth > img->bit_depth) {
+ aom_img_upshift(img_shifted, img,
+ output_bit_depth - img->bit_depth);
+ } else {
+ aom_img_downshift(img_shifted, img,
+ img->bit_depth - output_bit_depth);
+ }
+ img = img_shifted;
+ }
+ }
+
+ aom_input_ctx.width = img->d_w;
+ aom_input_ctx.height = img->d_h;
+
+ int num_planes = (!use_y4m && opt_raw && img->monochrome) ? 1 : 3;
+
+ if (single_file) {
+ if (use_y4m) {
+ char y4m_buf[Y4M_BUFFER_SIZE] = { 0 };
+ size_t len = 0;
+ if (frame_out == 1) {
+ // Y4M file header
+ len = y4m_write_file_header(
+ y4m_buf, sizeof(y4m_buf), aom_input_ctx.width,
+ aom_input_ctx.height, &aom_input_ctx.framerate, img->fmt,
+ img->bit_depth);
+ if (do_md5) {
+ MD5Update(&md5_ctx, (md5byte *)y4m_buf, (unsigned int)len);
+ } else {
+ fputs(y4m_buf, outfile);
+ }
+ }
+
+ // Y4M frame header
+ len = y4m_write_frame_header(y4m_buf, sizeof(y4m_buf));
if (do_md5) {
MD5Update(&md5_ctx, (md5byte *)y4m_buf, (unsigned int)len);
} else {
fputs(y4m_buf, outfile);
}
- }
-
- // Y4M frame header
- len = y4m_write_frame_header(y4m_buf, sizeof(y4m_buf));
- if (do_md5) {
- MD5Update(&md5_ctx, (md5byte *)y4m_buf, (unsigned int)len);
} else {
- fputs(y4m_buf, outfile);
- }
- } else {
- if (frame_out == 1) {
- // Check if --yv12 or --i420 options are consistent with the
- // bit-stream decoded
- if (opt_i420) {
- if (img->fmt != AOM_IMG_FMT_I420 &&
- img->fmt != AOM_IMG_FMT_I42016) {
- fprintf(stderr, "Cannot produce i420 output for bit-stream.\n");
- goto fail;
+ if (frame_out == 1) {
+ // Check if --yv12 or --i420 options are consistent with the
+ // bit-stream decoded
+ if (opt_i420) {
+ if (img->fmt != AOM_IMG_FMT_I420 &&
+ img->fmt != AOM_IMG_FMT_I42016) {
+ fprintf(stderr,
+ "Cannot produce i420 output for bit-stream.\n");
+ goto fail;
+ }
}
- }
- if (opt_yv12) {
- if ((img->fmt != AOM_IMG_FMT_I420 &&
- img->fmt != AOM_IMG_FMT_YV12) ||
- img->bit_depth != 8) {
- fprintf(stderr, "Cannot produce yv12 output for bit-stream.\n");
- goto fail;
+ if (opt_yv12) {
+ if ((img->fmt != AOM_IMG_FMT_I420 &&
+ img->fmt != AOM_IMG_FMT_YV12) ||
+ img->bit_depth != 8) {
+ fprintf(stderr,
+ "Cannot produce yv12 output for bit-stream.\n");
+ goto fail;
+ }
}
}
}
- }
- if (do_md5) {
- update_image_md5(img, planes, &md5_ctx);
+ if (do_md5) {
+ update_image_md5(img, planes, &md5_ctx);
+ } else {
+ write_image_file(img, planes, num_planes, outfile);
+ }
} else {
- write_image_file(img, planes, num_planes, outfile);
- }
- } else {
- generate_filename(outfile_pattern, outfile_name, PATH_MAX, img->d_w,
- img->d_h, frame_in);
- if (do_md5) {
- MD5Init(&md5_ctx);
- update_image_md5(img, planes, &md5_ctx);
- MD5Final(md5_digest, &md5_ctx);
- print_md5(md5_digest, outfile_name);
- } else {
- outfile = open_outfile(outfile_name);
- write_image_file(img, planes, num_planes, outfile);
- fclose(outfile);
+ generate_filename(outfile_pattern, outfile_name, PATH_MAX, img->d_w,
+ img->d_h, frame_in);
+ if (do_md5) {
+ MD5Init(&md5_ctx);
+ update_image_md5(img, planes, &md5_ctx);
+ MD5Final(md5_digest, &md5_ctx);
+ print_md5(md5_digest, outfile_name);
+ } else {
+ outfile = open_outfile(outfile_name);
+ write_image_file(img, planes, num_planes, outfile);
+ fclose(outfile);
+ }
}
}
}
diff --git a/examples/inspect.c b/examples/inspect.c
index 2b459e1..4887fc4 100644
--- a/examples/inspect.c
+++ b/examples/inspect.c
@@ -629,11 +629,14 @@
AOM_CODEC_OK) {
die_codec(&codec, "Failed to decode frame.");
}
- img = aom_codec_get_frame(&codec, &iter);
- if (img == NULL) {
+ int got_any_frames = 0;
+ while ((img = aom_codec_get_frame(&codec, &iter))) {
+ ++frame_count;
+ got_any_frames = 1;
+ }
+ if (!got_any_frames) {
return EXIT_FAILURE;
}
- ++frame_count;
return EXIT_SUCCESS;
}
diff --git a/examples/lightfield_tile_list_decoder.c b/examples/lightfield_tile_list_decoder.c
index 1b48fa1..aa0d3d6 100644
--- a/examples/lightfield_tile_list_decoder.c
+++ b/examples/lightfield_tile_list_decoder.c
@@ -158,8 +158,10 @@
die_codec(&codec, "Failed to decode the tile list.");
aom_codec_iter_t iter = NULL;
- aom_image_t *img = aom_codec_get_frame(&codec, &iter);
- aom_img_write(img, outfile);
+ aom_image_t *img;
+ while ((img = aom_codec_get_frame(&codec, &iter))) {
+ aom_img_write(img, outfile);
+ }
}
for (i = 0; i < num_references; i++) aom_img_free(&reference_images[i]);