#include "vpx/vp8dx.h"
#endif
-#if CONFIG_MD5
#include "./md5_utils.h"
-#endif
#include "./tools_common.h"
#include "./webmdec.h"
+#include "./y4menc.h"
static const char *exec_name;
-static const struct {
- char const *name;
- const vpx_codec_iface_t *(*iface)(void);
- uint32_t fourcc;
- uint32_t fourcc_mask;
-} ifaces[] = {
-#if CONFIG_VP8_DECODER
- {"vp8", vpx_codec_vp8_dx, VP8_FOURCC_MASK, 0x00FFFFFF},
-#endif
-#if CONFIG_VP9_DECODER
- {"vp9", vpx_codec_vp9_dx, VP9_FOURCC_MASK, 0x00FFFFFF},
-#endif
-};
-
struct VpxDecInputContext {
struct VpxInputContext *vpx_input_ctx;
struct WebmInputContext *webm_ctx;
"Enable decoder error-concealment");
static const arg_def_t scalearg = ARG_DEF("S", "scale", 0,
"Scale output frames uniformly");
+
static const arg_def_t fb_arg =
ARG_DEF(NULL, "frame-buffers", 1, "Number of frame buffers to use");
-static const arg_def_t fb_lru_arg =
- ARG_DEF(NULL, "frame-buffers-lru", 1, "Turn on/off frame buffer lru");
-
-#if CONFIG_MD5
static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
"Compute the MD5 sum of the decoded frame");
-#endif
+
static const arg_def_t *all_args[] = {
&codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
&progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile,
- &threadsarg, &verbosearg, &scalearg, &fb_arg, &fb_lru_arg,
-#if CONFIG_MD5
+ &threadsarg, &verbosearg, &scalearg, &fb_arg,
&md5arg,
-#endif
&error_concealment,
NULL
};
};
#endif
+static int vpx_image_scale(vpx_image_t *src, vpx_image_t *dst,
+ FilterMode mode) {
+ assert(src->fmt == VPX_IMG_FMT_I420);
+ assert(dst->fmt == VPX_IMG_FMT_I420);
+ return I420Scale(src->planes[VPX_PLANE_Y], src->stride[VPX_PLANE_Y],
+ src->planes[VPX_PLANE_U], src->stride[VPX_PLANE_U],
+ src->planes[VPX_PLANE_V], src->stride[VPX_PLANE_V],
+ src->d_w, src->d_h,
+ dst->planes[VPX_PLANE_Y], dst->stride[VPX_PLANE_Y],
+ dst->planes[VPX_PLANE_U], dst->stride[VPX_PLANE_U],
+ dst->planes[VPX_PLANE_V], dst->stride[VPX_PLANE_V],
+ dst->d_w, dst->d_h,
+ mode);
+}
+
void usage_exit() {
int i;
);
fprintf(stderr, "\nIncluded decoders:\n\n");
- for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
+ for (i = 0; i < get_vpx_decoder_count(); ++i) {
+ const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
fprintf(stderr, " %-6s - %s\n",
- ifaces[i].name,
- vpx_codec_iface_name(ifaces[i].iface()));
+ decoder->name, vpx_codec_iface_name(decoder->interface()));
+ }
exit(EXIT_FAILURE);
}
-static int read_frame(struct VpxDecInputContext *input,
- uint8_t **buf,
- size_t *bytes_in_buffer,
- size_t *buffer_size) {
+static int raw_read_frame(FILE *infile, uint8_t **buffer,
+ size_t *bytes_read, size_t *buffer_size) {
char raw_hdr[RAW_FRAME_HDR_SZ];
- size_t bytes_to_read = 0;
- FILE *infile = input->vpx_input_ctx->file;
- enum VideoFileType kind = input->vpx_input_ctx->file_type;
- if (kind == FILE_TYPE_WEBM) {
- return webm_read_frame(input->webm_ctx,
- buf, bytes_in_buffer, buffer_size);
- } else if (kind == FILE_TYPE_RAW) {
- if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) {
- if (!feof(infile))
- warn("Failed to read RAW frame size\n");
- } else {
- const int kCorruptFrameThreshold = 256 * 1024 * 1024;
- const int kFrameTooSmallThreshold = 256 * 1024;
- bytes_to_read = mem_get_le32(raw_hdr);
-
- if (bytes_to_read > kCorruptFrameThreshold) {
- warn("Read invalid frame size (%u)\n", (unsigned int)bytes_to_read);
- bytes_to_read = 0;
- }
+ size_t frame_size = 0;
- if (kind == FILE_TYPE_RAW && bytes_to_read < kFrameTooSmallThreshold) {
- warn("Warning: Read invalid frame size (%u) - not a raw file?\n",
- (unsigned int)bytes_to_read);
- }
+ if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) {
+ if (!feof(infile))
+ warn("Failed to read RAW frame size\n");
+ } else {
+ const size_t kCorruptFrameThreshold = 256 * 1024 * 1024;
+ const size_t kFrameTooSmallThreshold = 256 * 1024;
+ frame_size = mem_get_le32(raw_hdr);
- if (bytes_to_read > *buffer_size) {
- uint8_t *new_buf = realloc(*buf, 2 * bytes_to_read);
+ if (frame_size > kCorruptFrameThreshold) {
+ warn("Read invalid frame size (%u)\n", (unsigned int)frame_size);
+ frame_size = 0;
+ }
- if (new_buf) {
- *buf = new_buf;
- *buffer_size = 2 * bytes_to_read;
- } else {
- warn("Failed to allocate compressed data buffer\n");
- bytes_to_read = 0;
- }
- }
+ if (frame_size < kFrameTooSmallThreshold) {
+ warn("Warning: Read invalid frame size (%u) - not a raw file?\n",
+ (unsigned int)frame_size);
}
- if (!feof(infile)) {
- if (fread(*buf, 1, bytes_to_read, infile) != bytes_to_read) {
- warn("Failed to read full frame\n");
- return 1;
+ if (frame_size > *buffer_size) {
+ uint8_t *new_buf = realloc(*buffer, 2 * frame_size);
+ if (new_buf) {
+ *buffer = new_buf;
+ *buffer_size = 2 * frame_size;
+ } else {
+ warn("Failed to allocate compressed data buffer\n");
+ frame_size = 0;
}
- *bytes_in_buffer = bytes_to_read;
}
-
- return 0;
- } else if (kind == FILE_TYPE_IVF) {
- return ivf_read_frame(input->vpx_input_ctx,
- buf, bytes_in_buffer, buffer_size);
}
- return 1;
-}
-
-void *out_open(const char *out_fn, int do_md5) {
- void *out = NULL;
-
- if (do_md5) {
-#if CONFIG_MD5
- MD5Context *md5_ctx = out = malloc(sizeof(MD5Context));
- (void)out_fn;
- MD5Init(md5_ctx);
-#endif
- } else {
- FILE *outfile = out = strcmp("-", out_fn) ? fopen(out_fn, "wb")
- : set_binary_mode(stdout);
-
- if (!outfile) {
- fatal("Failed to output file");
+ if (!feof(infile)) {
+ if (fread(*buffer, 1, frame_size, infile) != frame_size) {
+ warn("Failed to read full frame\n");
+ return 1;
}
+ *bytes_read = frame_size;
}
- return out;
+ return 0;
}
-void out_put(void *out, const uint8_t *buf, unsigned int len, int do_md5) {
- if (do_md5) {
-#if CONFIG_MD5
- MD5Update(out, buf, len);
-#endif
- } else {
- (void) fwrite(buf, 1, len, out);
+static int read_frame(struct VpxDecInputContext *input, uint8_t **buf,
+ size_t *bytes_in_buffer, size_t *buffer_size) {
+ switch (input->vpx_input_ctx->file_type) {
+ case FILE_TYPE_WEBM:
+ return webm_read_frame(input->webm_ctx,
+ buf, bytes_in_buffer, buffer_size);
+ case FILE_TYPE_RAW:
+ return raw_read_frame(input->vpx_input_ctx->file,
+ buf, bytes_in_buffer, buffer_size);
+ case FILE_TYPE_IVF:
+ return ivf_read_frame(input->vpx_input_ctx->file,
+ buf, bytes_in_buffer, buffer_size);
+ default:
+ return 1;
}
}
-void out_close(void *out, const char *out_fn, int do_md5) {
- if (do_md5) {
-#if CONFIG_MD5
- uint8_t md5[16];
- int i;
+static void update_image_md5(const vpx_image_t *img, const int planes[3],
+ MD5Context *md5) {
+ int i, y;
- MD5Final(md5, out);
- free(out);
+ for (i = 0; i < 3; ++i) {
+ const int plane = planes[i];
+ const unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int w = vpx_img_plane_width(img, plane);
+ const int h = vpx_img_plane_height(img, plane);
- for (i = 0; i < 16; i++)
- printf("%02x", md5[i]);
+ for (y = 0; y < h; ++y) {
+ MD5Update(md5, buf, w);
+ buf += stride;
+ }
+ }
+}
- printf(" %s\n", out_fn);
-#endif
- } else {
- fclose(out);
+static void write_image_file(const vpx_image_t *img, const int planes[3],
+ FILE *file) {
+ int i, y;
+
+ for (i = 0; i < 3; ++i) {
+ const int plane = planes[i];
+ const unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int w = vpx_img_plane_width(img, plane);
+ const int h = vpx_img_plane_height(img, plane);
+
+ for (y = 0; y < h; ++y) {
+ fwrite(buf, 1, w, file);
+ buf += stride;
+ }
}
}
int i;
if (mem_get_le32(buf) < 256 * 1024 * 1024) {
- for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) {
- if (!vpx_codec_peek_stream_info(ifaces[i].iface(),
+ for (i = 0; i < get_vpx_decoder_count(); ++i) {
+ const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+ if (!vpx_codec_peek_stream_info(decoder->interface(),
buf + 4, 32 - 4, &si)) {
is_raw = 1;
- input->fourcc = ifaces[i].fourcc;
+ input->fourcc = decoder->fourcc;
input->width = si.w;
input->height = si.h;
input->framerate.numerator = 30;
(float)frame_out * 1000000.0 / (float)dx_time);
}
-// Called by libvpx if the frame buffer size needs to increase.
-//
-// Parameters:
-// user_priv Data passed into libvpx.
-// new_size Minimum size needed by libvpx to decompress the next frame.
-// fb Pointer to the frame buffer to update.
-//
-// Returns 0 on success. Returns < 0 on failure.
-int realloc_vp9_frame_buffer(void *user_priv, size_t new_size,
- vpx_codec_frame_buffer_t *fb) {
- (void)user_priv;
- if (!fb)
+struct ExternalFrameBuffer {
+ uint8_t* data;
+ size_t size;
+ int in_use;
+};
+
+struct ExternalFrameBufferList {
+ int num_external_frame_buffers;
+ struct ExternalFrameBuffer *ext_fb;
+};
+
+// Callback used by libvpx to request an external frame buffer. |cb_priv|
+// Application private data passed into the set function. |min_size| is the
+// minimum size in bytes needed to decode the next frame. |fb| pointer to the
+// frame buffer.
+int get_vp9_frame_buffer(void *cb_priv, size_t min_size,
+ vpx_codec_frame_buffer_t *fb) {
+ int i;
+ struct ExternalFrameBufferList *const ext_fb_list =
+ (struct ExternalFrameBufferList *)cb_priv;
+ if (ext_fb_list == NULL)
return -1;
- free(fb->data);
- fb->data = (uint8_t*)malloc(new_size);
- if (!fb->data) {
- fb->size = 0;
+ // Find a free frame buffer.
+ for (i = 0; i < ext_fb_list->num_external_frame_buffers; ++i) {
+ if (!ext_fb_list->ext_fb[i].in_use)
+ break;
+ }
+
+ if (i == ext_fb_list->num_external_frame_buffers)
return -1;
+
+ if (ext_fb_list->ext_fb[i].size < min_size) {
+ free(ext_fb_list->ext_fb[i].data);
+ ext_fb_list->ext_fb[i].data = (uint8_t *)malloc(min_size);
+ if (!ext_fb_list->ext_fb[i].data)
+ return -1;
+
+ ext_fb_list->ext_fb[i].size = min_size;
}
- fb->size = new_size;
+ fb->data = ext_fb_list->ext_fb[i].data;
+ fb->size = ext_fb_list->ext_fb[i].size;
+ ext_fb_list->ext_fb[i].in_use = 1;
+
+ // Set the frame buffer's private data to point at the external frame buffer.
+ fb->priv = &ext_fb_list->ext_fb[i];
+ return 0;
+}
+
+// Callback used by libvpx when there are no references to the frame buffer.
+// |cb_priv| user private data passed into the set function. |fb| pointer
+// to the frame buffer.
+int release_vp9_frame_buffer(void *cb_priv,
+ vpx_codec_frame_buffer_t *fb) {
+ struct ExternalFrameBuffer *const ext_fb =
+ (struct ExternalFrameBuffer *)fb->priv;
+ (void)cb_priv;
+ ext_fb->in_use = 0;
return 0;
}
} while (*p);
}
+static int is_single_file(const char *outfile_pattern) {
+ const char *p = outfile_pattern;
+
+ do {
+ p = strchr(p, '%');
+ if (p && p[1] >= '1' && p[1] <= '9')
+ return 0; // pattern contains sequence number, so it's not unique
+ if (p)
+ p++;
+ } while (p);
+
+ return 1;
+}
+
+static void print_md5(unsigned char digest[16], const char *filename) {
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ printf("%02x", digest[i]);
+ printf(" %s\n", filename);
+}
+
+static FILE *open_outfile(const char *name) {
+ if (strcmp("-", name) == 0) {
+ set_binary_mode(stdout);
+ return stdout;
+ } else {
+ FILE *file = fopen(name, "wb");
+ if (!file)
+ fatal("Failed to output file %s", name);
+ return file;
+ }
+}
int main_loop(int argc, const char **argv_) {
vpx_codec_ctx_t decoder;
char *fn = NULL;
- int i;
uint8_t *buf = NULL;
size_t bytes_in_buffer = 0, buffer_size = 0;
FILE *infile;
int stop_after = 0, postproc = 0, summary = 0, quiet = 1;
int arg_skip = 0;
int ec_enabled = 0;
- vpx_codec_iface_t *iface = NULL;
+ const VpxInterface *interface = NULL;
+ const VpxInterface *fourcc_interface = NULL;
unsigned long dx_time = 0;
struct arg arg;
char **argv, **argi, **argj;
- const char *outfile_pattern = 0;
- char outfile[PATH_MAX];
+
int single_file;
int use_y4m = 1;
- void *out = NULL;
vpx_codec_dec_cfg_t cfg = {0};
#if CONFIG_VP8_DECODER
vp8_postproc_cfg_t vp8_pp_cfg = {0};
vpx_image_t *scaled_img = NULL;
int frame_avail, got_data;
int num_external_frame_buffers = 0;
- int fb_lru_cache = 0;
- vpx_codec_frame_buffer_t *frame_buffers = NULL;
+ struct ExternalFrameBufferList ext_fb_list = {0};
+
+ const char *outfile_pattern = NULL;
+ char outfile_name[PATH_MAX] = {0};
+ FILE *outfile = NULL;
+
+ MD5Context md5_ctx;
+ unsigned char md5_digest[16];
struct VpxDecInputContext input = {0};
struct VpxInputContext vpx_input_ctx = {0};
arg.argv_step = 1;
if (arg_match(&arg, &codecarg, argi)) {
- int j, k = -1;
-
- for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
- if (!strcmp(ifaces[j].name, arg.val))
- k = j;
-
- if (k >= 0)
- iface = ifaces[k].iface();
- else
- die("Error: Unrecognized argument (%s) to --codec\n",
- arg.val);
+ interface = get_vpx_decoder_by_name(arg.val);
+ if (!interface)
+ die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
} else if (arg_match(&arg, &looparg, argi)) {
// no-op
} else if (arg_match(&arg, &outputfile, argi))
do_scale = 1;
else if (arg_match(&arg, &fb_arg, argi))
num_external_frame_buffers = arg_parse_uint(&arg);
- else if (arg_match(&arg, &fb_lru_arg, argi))
- fb_lru_cache = arg_parse_uint(&arg);
#if CONFIG_VP8_DECODER
else if (arg_match(&arg, &addnoise_level, argi)) {
infile = strcmp(fn, "-") ? fopen(fn, "rb") : set_binary_mode(stdin);
if (!infile) {
- fprintf(stderr, "Failed to open file '%s'",
- strcmp(fn, "-") ? fn : "stdin");
+ fprintf(stderr, "Failed to open file '%s'", strcmp(fn, "-") ? fn : "stdin");
return EXIT_FAILURE;
}
#if CONFIG_OS_SUPPORT
return EXIT_FAILURE;
}
- /* If the output file is not set or doesn't have a sequence number in
- * it, then we only open it once.
- */
outfile_pattern = outfile_pattern ? outfile_pattern : "-";
- single_file = 1;
- {
- const char *p = outfile_pattern;
- do {
- p = strchr(p, '%');
- if (p && p[1] >= '1' && p[1] <= '9') {
- /* pattern contains sequence number, so it's not unique. */
- single_file = 0;
- break;
- }
- if (p)
- p++;
- } while (p);
- }
+ single_file = is_single_file(outfile_pattern);
- if (single_file && !noblit) {
- generate_filename(outfile_pattern, outfile, sizeof(outfile) - 1,
+ if (!noblit && single_file) {
+ generate_filename(outfile_pattern, outfile_name, PATH_MAX,
vpx_input_ctx.width, vpx_input_ctx.height, 0);
- out = out_open(outfile, do_md5);
+ if (do_md5)
+ MD5Init(&md5_ctx);
+ else
+ outfile = open_outfile(outfile_name);
}
if (use_y4m && !noblit) {
- char buffer[128];
-
if (!single_file) {
fprintf(stderr, "YUV4MPEG2 not supported with output patterns,"
" try --i420 or --yv12.\n");
return EXIT_FAILURE;
}
- if (vpx_input_ctx.file_type == FILE_TYPE_WEBM)
+ if (vpx_input_ctx.file_type == FILE_TYPE_WEBM) {
if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) {
fprintf(stderr, "Failed to guess framerate -- error parsing "
"webm file?\n");
return EXIT_FAILURE;
}
-
-
- /*Note: We can't output an aspect ratio here because IVF doesn't
- store one, and neither does VP8.
- That will have to wait until these tools support WebM natively.*/
- snprintf(buffer, sizeof(buffer), "YUV4MPEG2 W%u H%u F%u:%u I%c ",
- vpx_input_ctx.width, vpx_input_ctx.height,
- vpx_input_ctx.framerate.numerator,
- vpx_input_ctx.framerate.denominator,
- 'p');
- out_put(out, (unsigned char *)buffer,
- (unsigned int)strlen(buffer), do_md5);
+ }
}
- /* Try to determine the codec from the fourcc. */
- for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
- if ((vpx_input_ctx.fourcc & ifaces[i].fourcc_mask) == ifaces[i].fourcc) {
- vpx_codec_iface_t *vpx_iface = ifaces[i].iface();
+ fourcc_interface = get_vpx_decoder_by_fourcc(vpx_input_ctx.fourcc);
+ if (interface && fourcc_interface && interface != fourcc_interface)
+ warn("Header indicates codec: %s\n", fourcc_interface->name);
+ else
+ interface = fourcc_interface;
- if (iface && iface != vpx_iface)
- warn("Header indicates codec: %s\n", ifaces[i].name);
- else
- iface = vpx_iface;
-
- break;
- }
+ if (!interface)
+ interface = get_vpx_decoder_by_index(0);
dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
(ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
- if (vpx_codec_dec_init(&decoder, iface ? iface : ifaces[0].iface(), &cfg,
- dec_flags)) {
- fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder));
+ if (vpx_codec_dec_init(&decoder, interface->interface(), &cfg, dec_flags)) {
+ fprintf(stderr, "Failed to initialize decoder: %s\n",
+ vpx_codec_error(&decoder));
return EXIT_FAILURE;
}
}
if (num_external_frame_buffers > 0) {
- // Allocate the frame buffer list, setting all of the values to 0.
- // Including the size of frame buffers. Libvpx will request the
- // application to realloc the frame buffer data if the size is too small.
- frame_buffers = (vpx_codec_frame_buffer_t*)calloc(
- num_external_frame_buffers, sizeof(*frame_buffers));
- if (vpx_codec_set_frame_buffers(&decoder, frame_buffers,
- num_external_frame_buffers,
- realloc_vp9_frame_buffer,
- NULL)) {
+ ext_fb_list.num_external_frame_buffers = num_external_frame_buffers;
+ ext_fb_list.ext_fb = (struct ExternalFrameBuffer *)calloc(
+ num_external_frame_buffers, sizeof(*ext_fb_list.ext_fb));
+ if (vpx_codec_set_frame_buffer_functions(
+ &decoder, get_vp9_frame_buffer, release_vp9_frame_buffer,
+ &ext_fb_list)) {
fprintf(stderr, "Failed to configure external frame buffers: %s\n",
vpx_codec_error(&decoder));
return EXIT_FAILURE;
}
}
- if (fb_lru_cache > 0 &&
- vpx_codec_control(&decoder, VP9D_SET_FRAME_BUFFER_LRU_CACHE,
- fb_lru_cache)) {
- fprintf(stderr, "Failed to set frame buffer lru cache: %s\n",
- vpx_codec_error(&decoder));
- return EXIT_FAILURE;
- }
-
frame_avail = 1;
got_data = 0;
if (progress)
show_progress(frame_in, frame_out, dx_time);
- if (!noblit) {
- if (frame_out == 1 && img && use_y4m) {
- /* Write out the color format to terminate the header line */
- const char *color =
- img->fmt == VPX_IMG_FMT_444A ? "C444alpha\n" :
- img->fmt == VPX_IMG_FMT_I444 ? "C444\n" :
- img->fmt == VPX_IMG_FMT_I422 ? "C422\n" :
- "C420jpeg\n";
-
- out_put(out, (const unsigned char*)color, strlen(color), do_md5);
- }
+ if (!noblit && img) {
+ const int PLANES_YUV[] = {VPX_PLANE_Y, VPX_PLANE_U, VPX_PLANE_V};
+ const int PLANES_YVU[] = {VPX_PLANE_Y, VPX_PLANE_V, VPX_PLANE_U};
+ const int *planes = flipuv ? PLANES_YVU : PLANES_YUV;
if (do_scale) {
- int stream_w = 0, stream_h = 0;
- if (img && frame_out == 1) {
- int display_size[2];
- if (vpx_codec_control(&decoder, VP9D_GET_DISPLAY_SIZE,
- display_size)) {
- // Fallback to use raw image size if display size not available.
- stream_w = img->d_w;
- stream_h = img->d_h;
- } else {
- stream_w = display_size[0];
- stream_h = display_size[1];
+ 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 display_width = vpx_input_ctx.width;
+ int display_height = vpx_input_ctx.height;
+ if (!display_width || !display_height) {
+ int display_size[2];
+ if (vpx_codec_control(&decoder, VP9D_GET_DISPLAY_SIZE,
+ display_size)) {
+ // As last resort use size of first frame as display size.
+ display_width = img->d_w;
+ display_height = img->d_h;
+ } else {
+ display_width = display_size[0];
+ display_height = display_size[1];
+ }
}
- scaled_img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420,
- stream_w, stream_h, 16);
+ scaled_img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, display_width,
+ display_height, 16);
}
- if (img && (img->d_w != stream_w || img->d_h != stream_h)) {
- assert(img->fmt == VPX_IMG_FMT_I420);
- I420Scale(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
- img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],
- img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
- img->d_w, img->d_h,
- scaled_img->planes[VPX_PLANE_Y],
- scaled_img->stride[VPX_PLANE_Y],
- scaled_img->planes[VPX_PLANE_U],
- scaled_img->stride[VPX_PLANE_U],
- scaled_img->planes[VPX_PLANE_V],
- scaled_img->stride[VPX_PLANE_V],
- stream_w, stream_h,
- kFilterBox);
+
+ if (img->d_w != scaled_img->d_w || img->d_h != scaled_img->d_h) {
+ vpx_image_scale(img, scaled_img, kFilterBox);
img = scaled_img;
}
}
- if (img) {
- unsigned int y;
- char out_fn[PATH_MAX];
- uint8_t *buf;
- unsigned int c_w =
- img->x_chroma_shift ? (1 + img->d_w) >> img->x_chroma_shift
- : img->d_w;
- unsigned int c_h =
- img->y_chroma_shift ? (1 + img->d_h) >> img->y_chroma_shift
- : img->d_h;
-
- if (!single_file) {
- size_t len = sizeof(out_fn) - 1;
-
- out_fn[len] = '\0';
- generate_filename(outfile_pattern, out_fn, len - 1,
- img->d_w, img->d_h, frame_in);
- out = out_open(out_fn, do_md5);
- } else if (use_y4m)
- out_put(out, (unsigned char *)"FRAME\n", 6, do_md5);
-
- buf = img->planes[VPX_PLANE_Y];
-
- for (y = 0; y < img->d_h; y++) {
- out_put(out, buf, img->d_w, do_md5);
- buf += img->stride[VPX_PLANE_Y];
- }
- buf = img->planes[flipuv ? VPX_PLANE_V : VPX_PLANE_U];
+ if (single_file) {
+ if (use_y4m) {
+ char buf[Y4M_BUFFER_SIZE] = {0};
+ size_t len = 0;
+ if (frame_out == 1) {
+ // Y4M file header
+ len = y4m_write_file_header(buf, sizeof(buf),
+ vpx_input_ctx.width,
+ vpx_input_ctx.height,
+ &vpx_input_ctx.framerate, img->fmt);
+ if (do_md5) {
+ MD5Update(&md5_ctx, (md5byte *)buf, len);
+ } else {
+ fputs(buf, outfile);
+ }
+ }
- for (y = 0; y < c_h; y++) {
- out_put(out, buf, c_w, do_md5);
- buf += img->stride[VPX_PLANE_U];
+ // Y4M frame header
+ len = y4m_write_frame_header(buf, sizeof(buf));
+ if (do_md5) {
+ MD5Update(&md5_ctx, (md5byte *)buf, len);
+ } else {
+ fputs(buf, outfile);
+ }
}
- buf = img->planes[flipuv ? VPX_PLANE_U : VPX_PLANE_V];
-
- for (y = 0; y < c_h; y++) {
- out_put(out, buf, c_w, do_md5);
- buf += img->stride[VPX_PLANE_V];
+ if (do_md5) {
+ update_image_md5(img, planes, &md5_ctx);
+ } else {
+ write_image_file(img, 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, outfile);
+ fclose(outfile);
}
-
- if (!single_file)
- out_close(out, out_fn, do_md5);
}
}
return EXIT_FAILURE;
}
- if (single_file && !noblit)
- out_close(out, outfile, do_md5);
+ if (!noblit && single_file) {
+ if (do_md5) {
+ MD5Final(md5_digest, &md5_ctx);
+ print_md5(md5_digest, outfile_name);
+ } else {
+ fclose(outfile);
+ }
+ }
if (input.vpx_input_ctx->file_type == FILE_TYPE_WEBM)
webm_free(input.webm_ctx);
free(buf);
if (scaled_img) vpx_img_free(scaled_img);
- for (i = 0; i < num_external_frame_buffers; ++i) {
- free(frame_buffers[i].data);
+
+ for (i = 0; i < ext_fb_list.num_external_frame_buffers; ++i) {
+ free(ext_fb_list.ext_fb[i].data);
}
- free(frame_buffers);
+ free(ext_fb_list.ext_fb);
fclose(infile);
free(argv);