/*
 *  Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */


/* This is a simple program showing how to initialize the decoder in XMA mode */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define VPX_CODEC_DISABLE_COMPAT 1
#include "vpx_config.h"
#include "vpx/vpx_decoder.h"
#include "vpx/vpx_integer.h"
#if CONFIG_VP8_DECODER
#include "vpx/vp8dx.h"
#endif

static char *exec_name;
static int   verbose = 0;

static const struct
{
    const char *name;
    const vpx_codec_iface_t *iface;
} ifaces[] =
{
#if CONFIG_VP8_DECODER
    {"vp8",  &vpx_codec_vp8_dx_algo},
#endif
};

static void usage_exit(void)
{
    int i;

    printf("Usage: %s <options>\n\n"
           "Options:\n"
           "\t--codec <name>\tCodec to use (default=%s)\n"
           "\t-h <height>\tHeight of the simulated video frame, in pixels\n"
           "\t-w <width> \tWidth of the simulated video frame, in pixels\n"
           "\t-v         \tVerbose mode (show individual segment sizes)\n"
           "\t--help     \tShow this message\n"
           "\n"
           "Included decoders:\n"
           "\n",
           exec_name,
           ifaces[0].name);

    for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
        printf("    %-6s - %s\n",
               ifaces[i].name,
               vpx_codec_iface_name(ifaces[i].iface));

    exit(EXIT_FAILURE);
}

static void usage_error(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vprintf(fmt, ap);
    printf("\n");
    usage_exit();
}

void my_mem_dtor(vpx_codec_mmap_t *mmap)
{
    if (verbose)
        printf("freeing segment %d\n", mmap->id);

    free(mmap->priv);
}

int main(int argc, char **argv)
{
    vpx_codec_ctx_t           decoder;
    vpx_codec_iface_t        *iface = ifaces[0].iface;
    vpx_codec_iter_t          iter;
    vpx_codec_dec_cfg_t       cfg;
    vpx_codec_err_t           res = VPX_CODEC_OK;
    unsigned int            alloc_sz = 0;
    unsigned int            w = 352;
    unsigned int            h = 288;
    int                     i;

    exec_name = argv[0];

    for (i = 1; i < argc; i++)
    {
        if (!strcmp(argv[i], "--codec"))
        {
            if (i + 1 < argc)
            {
                int j, k = -1;

                i++;

                for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
                    if (!strcmp(ifaces[j].name, argv[i]))
                        k = j;

                if (k >= 0)
                    iface = ifaces[k].iface;
                else
                    usage_error("Error: Unrecognized argument (%s) to --codec\n",
                                argv[i]);
            }
            else
                usage_error("Error: Option --codec requires argument.\n");
        }
        else if (!strcmp(argv[i], "-v"))
            verbose = 1;
        else if (!strcmp(argv[i], "-h"))
            if (i + 1 < argc)
            {
                h = atoi(argv[++i]);
            }
            else
                usage_error("Error: Option -h requires argument.\n");
        else if (!strcmp(argv[i], "-w"))
            if (i + 1 < argc)
            {
                w = atoi(argv[++i]);
            }
            else
                usage_error("Error: Option -w requires argument.\n");
        else if (!strcmp(argv[i], "--help"))
            usage_exit();
        else
            usage_error("Error: Unrecognized option %s\n\n", argv[i]);
    }

    if (argc == 1)
        printf("Using built-in defaults. For options, rerun with --help\n\n");

    /* XMA mode is not supported on all decoders! */
    if (!(vpx_codec_get_caps(iface) & VPX_CODEC_CAP_XMA))
    {
        printf("%s does not support XMA mode!\n", vpx_codec_iface_name(iface));
        return EXIT_FAILURE;
    }

    /* The codec knows how much memory to allocate based on the size of the
     * encoded frames. This data can be parsed from the bitstream with
     * vpx_codec_peek_stream_info() if a bitstream is available. Otherwise,
     * a fixed size can be used that will be the upper limit on the frame
     * size the decoder can decode.
     */
    cfg.w = w;
    cfg.h = h;

    /* Initialize the decoder in XMA mode. */
    if (vpx_codec_dec_init(&decoder, iface, &cfg, VPX_CODEC_USE_XMA))
    {
        printf("Failed to initialize decoder in XMA mode: %s\n", vpx_codec_error(&decoder));
        return EXIT_FAILURE;
    }

    /* Iterate through the list of memory maps, allocating them with the
     * requested alignment.
     */
    iter = NULL;

    do
    {
        vpx_codec_mmap_t  mmap;
        unsigned int    align;

        res = vpx_codec_get_mem_map(&decoder, &mmap, &iter);
        align = mmap.align ? mmap.align - 1 : 0;

        if (!res)
        {
            if (verbose)
                printf("Allocating segment %u, size %lu, align %u %s\n",
                       mmap.id, mmap.sz, mmap.align,
                       mmap.flags & VPX_CODEC_MEM_ZERO ? "(ZEROED)" : "");

            if (mmap.flags & VPX_CODEC_MEM_ZERO)
                mmap.priv = calloc(1, mmap.sz + align);
            else
                mmap.priv = malloc(mmap.sz + align);

            mmap.base = (void *)((((uintptr_t)mmap.priv) + align) & ~(uintptr_t)align);
            mmap.dtor = my_mem_dtor;
            alloc_sz += mmap.sz + align;

            if (vpx_codec_set_mem_map(&decoder, &mmap, 1))
            {
                printf("Failed to set mmap: %s\n", vpx_codec_error(&decoder));
                return EXIT_FAILURE;
            }
        }
        else if (res != VPX_CODEC_LIST_END)
        {
            printf("Failed to get mmap: %s\n", vpx_codec_error(&decoder));
            return EXIT_FAILURE;
        }
    }
    while (res != VPX_CODEC_LIST_END);

    printf("%s\n    %d bytes external memory required for %dx%d.\n",
           decoder.name, alloc_sz, cfg.w, cfg.h);
    vpx_codec_destroy(&decoder);
    return EXIT_SUCCESS;

}
