From 7ec2769687194982e0e95523665e447f277814b9 Mon Sep 17 00:00:00 2001 From: Dmitry Kovalev Date: Mon, 27 Jan 2014 13:40:29 -0800 Subject: [PATCH] Adapting simple_decoder to use new file reading API. Change-Id: I374a0c4bb4a66c0d3dc874c6e57fdee9d1ab72df --- examples.mk | 6 +- examples/decode_to_md5.c | 23 ------ examples/simple_decoder.c | 136 +++++++++++++-------------------- tools_common.c | 44 +++++++++++ tools_common.h | 9 +++ vp9_spatial_scalable_encoder.c | 8 -- 6 files changed, 111 insertions(+), 115 deletions(-) diff --git a/examples.mk b/examples.mk index 2337d1ece..c08ebec71 100644 --- a/examples.mk +++ b/examples.mk @@ -70,8 +70,10 @@ vp9_spatial_scalable_encoder.DESCRIPTION = Spatial Scalable Encoder #example_xma.DESCRIPTION = External Memory Allocation mode usage GEN_EXAMPLES-$(CONFIG_VP8_DECODER) += simple_decoder.c -simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC -simple_decoder.DESCRIPTION = Simplified decoder loop +simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC +simple_decoder.SRCS += ivfdec.h ivfdec.c +simple_decoder.SRCS += tools_common.h tools_common.c +simple_decoder.DESCRIPTION = Simplified decoder loop GEN_EXAMPLES-$(CONFIG_VP8_DECODER) += postproc.c postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7 postproc.DESCRIPTION = Decoder postprocessor control diff --git a/examples/decode_to_md5.c b/examples/decode_to_md5.c index 67cbd6c63..bba218209 100644 --- a/examples/decode_to_md5.c +++ b/examples/decode_to_md5.c @@ -29,7 +29,6 @@ // is processed, then U, then V. It is important to honor the image's `stride` // values. -#include #include #include #include @@ -44,28 +43,6 @@ #include "./tools_common.h" #include "./vpx_config.h" -#define VP8_FOURCC 0x30385056 -#define VP9_FOURCC 0x30395056 - -static vpx_codec_iface_t *get_codec_interface(unsigned int fourcc) { - switch (fourcc) { - case VP8_FOURCC: - return vpx_codec_vp8_dx(); - case VP9_FOURCC: - return vpx_codec_vp9_dx(); - } - return NULL; -} - -static void die_codec(vpx_codec_ctx_t *ctx, const char *s) { - const char *detail = vpx_codec_error_detail(ctx); - - printf("%s: %s\n", s, vpx_codec_error(ctx)); - if(detail) - printf(" %s\n",detail); - exit(EXIT_FAILURE); -} - static void get_image_md5(const vpx_image_t *img, unsigned char digest[16]) { int plane, y; MD5Context md5; diff --git a/examples/simple_decoder.c b/examples/simple_decoder.c index 17a598739..23399f44f 100644 --- a/examples/simple_decoder.c +++ b/examples/simple_decoder.c @@ -77,110 +77,82 @@ // few exeptions, vpx_codec functions return an enumerated error status, // with the value `0` indicating success. -#include #include #include #include + #define VPX_CODEC_DISABLE_COMPAT 1 -#include "./vpx_config.h" + #include "vpx/vp8dx.h" #include "vpx/vpx_decoder.h" -#define interface (vpx_codec_vp8_dx()) +#include "./ivfdec.h" +#include "./tools_common.h" +#include "./vpx_config.h" -#define IVF_FILE_HDR_SZ (32) -#define IVF_FRAME_HDR_SZ (12) +static const char *exec_name; -static unsigned int mem_get_le32(const unsigned char *mem) { - return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]); +void usage_exit() { + fprintf(stderr, "Usage: %s \n", exec_name); + exit(EXIT_FAILURE); } -static void die(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vprintf(fmt, ap); - if(fmt[strlen(fmt)-1] != '\n') - printf("\n"); - exit(EXIT_FAILURE); -} - -static void die_codec(vpx_codec_ctx_t *ctx, const char *s) { - const char *detail = vpx_codec_error_detail(ctx); - - printf("%s: %s\n", s, vpx_codec_error(ctx)); - if(detail) - printf(" %s\n",detail); - exit(EXIT_FAILURE); -} - - int main(int argc, char **argv) { - FILE *infile, *outfile; - vpx_codec_ctx_t codec; - int flags = 0, frame_cnt = 0; - unsigned char file_hdr[IVF_FILE_HDR_SZ]; - unsigned char frame_hdr[IVF_FRAME_HDR_SZ]; - unsigned char frame[256*1024]; - vpx_codec_err_t res; + FILE *infile, *outfile; + vpx_codec_ctx_t codec; + vpx_codec_iface_t *iface; + int flags = 0, frame_cnt = 0; + vpx_video_t *video; - (void)res; - /* Open files */ - if(argc!=3) - die("Usage: %s \n", argv[0]); - if(!(infile = fopen(argv[1], "rb"))) - die("Failed to open %s for reading", argv[1]); - if(!(outfile = fopen(argv[2], "wb"))) - die("Failed to open %s for writing", argv[2]); + exec_name = argv[0]; - /* Read file header */ - if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ - && file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I' - && file_hdr[3]=='F')) - die("%s is not an IVF file.", argv[1]); + if (argc != 3) + die("Invalid number of arguments"); - printf("Using %s\n",vpx_codec_iface_name(interface)); - /* Initialize codec */ - if(vpx_codec_dec_init(&codec, interface, NULL, flags)) - die_codec(&codec, "Failed to initialize decoder"); + if (!(infile = fopen(argv[1], "rb"))) + die("Failed to open %s for reading", argv[1]); - /* Read each frame */ - while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) { - int frame_sz = mem_get_le32(frame_hdr); - vpx_codec_iter_t iter = NULL; - vpx_image_t *img; + if (!(outfile = fopen(argv[2], "wb"))) + die("Failed to open %s for writing", argv[2]); + video = vpx_video_open_file(infile); + if (!video) + die("%s is not an IVF file.", argv[1]); - frame_cnt++; - if(frame_sz > sizeof(frame)) - die("Frame %d data too big for example code buffer", frame_sz); - if(fread(frame, 1, frame_sz, infile) != frame_sz) - die("Frame %d failed to read complete frame", frame_cnt); + iface = get_codec_interface(vpx_video_get_fourcc(video)); + if (!iface) + die("Unknown FOURCC code."); - /* Decode the frame */ - if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0)) - die_codec(&codec, "Failed to decode frame"); + printf("Using %s\n", vpx_codec_iface_name(iface)); - /* Write decoded data to disk */ - while((img = vpx_codec_get_frame(&codec, &iter))) { - unsigned int plane, y; + if (vpx_codec_dec_init(&codec, iface, NULL, flags)) + die_codec(&codec, "Failed to initialize decoder"); - for(plane=0; plane < 3; plane++) { - unsigned char *buf =img->planes[plane]; + while (vpx_video_read_frame(video)) { + vpx_codec_iter_t iter = NULL; + vpx_image_t *img = NULL; + size_t frame_size = 0; + const unsigned char *frame = vpx_video_get_frame(video, &frame_size); + if (vpx_codec_decode(&codec, frame, frame_size, NULL, 0)) + die_codec(&codec, "Failed to decode frame"); - for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) { - (void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w), - outfile); - buf += img->stride[plane]; - } - } - } + while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) { + vpx_img_write(img, outfile); + ++frame_cnt; } - printf("Processed %d frames.\n",frame_cnt); - if(vpx_codec_destroy(&codec)) - die_codec(&codec, "Failed to destroy codec"); + } - fclose(outfile); - fclose(infile); - return EXIT_SUCCESS; + printf("Processed %d frames.\n", frame_cnt); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec"); + + printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n", + vpx_video_get_width(video), vpx_video_get_height(video), argv[2]); + + vpx_video_close(video); + + fclose(outfile); + fclose(infile); + + return EXIT_SUCCESS; } diff --git a/tools_common.c b/tools_common.c index 9c24983de..85bedc99d 100644 --- a/tools_common.c +++ b/tools_common.c @@ -15,6 +15,10 @@ #include #include +#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER +#include "vpx/vp8dx.h" +#endif + #if defined(_WIN32) || defined(__OS2__) #include #include @@ -60,6 +64,15 @@ void warn(const char *fmt, ...) { LOG_ERROR("Warning"); } +void die_codec(vpx_codec_ctx_t *ctx, const char *s) { + const char *detail = vpx_codec_error_detail(ctx); + + printf("%s: %s\n", s, vpx_codec_error(ctx)); + if (detail) + printf(" %s\n", detail); + exit(EXIT_FAILURE); +} + uint16_t mem_get_le16(const void *data) { uint16_t val; const uint8_t *mem = (const uint8_t*)data; @@ -130,3 +143,34 @@ int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame) { return shortread; } + +vpx_codec_iface_t *get_codec_interface(unsigned int fourcc) { + switch (fourcc) { +#if CONFIG_VP8_DECODER + case VP8_FOURCC: + return vpx_codec_vp8_dx(); +#endif +#if CONFIG_VP9_DECODER + case VP9_FOURCC: + return vpx_codec_vp9_dx(); +#endif + default: + return NULL; + } + return NULL; +} + +void vpx_img_write(const vpx_image_t *img, FILE *file) { + int plane, y; + + for (plane = 0; plane < 3; ++plane) { + const unsigned char *buf = img->planes[plane]; + const int stride = img->stride[plane]; + const int w = plane ? (img->d_w + 1) >> 1 : img->d_w; + const int h = plane ? (img->d_h + 1) >> 1 : img->d_h; + for (y = 0; y < h; ++y) { + fwrite(buf, 1, w, file); + buf += stride; + } + } +} diff --git a/tools_common.h b/tools_common.h index 1d70ab5e8..967b7a1fb 100644 --- a/tools_common.h +++ b/tools_common.h @@ -13,6 +13,7 @@ #include #include "./vpx_config.h" +#include "vpx/vpx_codec.h" #include "vpx/vpx_image.h" #include "vpx/vpx_integer.h" @@ -112,6 +113,8 @@ void die(const char *fmt, ...); void fatal(const char *fmt, ...); void warn(const char *fmt, ...); +void die_codec(vpx_codec_ctx_t *ctx, const char *s); + /* The tool including this file must define usage_exit() */ void usage_exit(); @@ -120,6 +123,12 @@ uint32_t mem_get_le32(const void *data); int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame); +vpx_codec_iface_t *get_codec_interface(unsigned int fourcc); + +// TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part +// of vpx_image_t support +void vpx_img_write(const vpx_image_t *img, FILE *file); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/vp9_spatial_scalable_encoder.c b/vp9_spatial_scalable_encoder.c index b637331c3..e71094abc 100644 --- a/vp9_spatial_scalable_encoder.c +++ b/vp9_spatial_scalable_encoder.c @@ -89,14 +89,6 @@ void usage_exit() { exit(EXIT_FAILURE); } -static void die_codec(vpx_codec_ctx_t *ctx, const char *s) { - const char *detail = vpx_codec_error_detail(ctx); - - printf("%s: %s\n", s, vpx_codec_error(ctx)); - if (detail) printf(" %s\n", detail); - exit(EXIT_FAILURE); -} - static void parse_command_line(int argc, const char **argv_, AppInput *app_input, SvcContext *svc_ctx, vpx_codec_enc_cfg_t *enc_cfg) {