/*
 *  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;

}
