1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* This is a simple program showing how to initialize the decoder in XMA mode */
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdio.h>
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h>
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdarg.h>
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <string.h>
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define VPX_CODEC_DISABLE_COMPAT 1
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_config.h"
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_decoder.h"
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_integer.h"
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_DECODER
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vp8dx.h"
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan
25233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic char *exec_name;
26233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int   verbose = 0;
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan
28233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const struct {
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const char *name;
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_iface_t *iface;
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan} ifaces[] = {
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_DECODER
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"vp9",  &vpx_codec_vp8_dx_algo},
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan
37233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void usage_exit(void) {
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i;
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan  printf("Usage: %s <options>\n\n"
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan         "Options:\n"
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan         "\t--codec <name>\tCodec to use (default=%s)\n"
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan         "\t-h <height>\tHeight of the simulated video frame, in pixels\n"
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan         "\t-w <width> \tWidth of the simulated video frame, in pixels\n"
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan         "\t-v         \tVerbose mode (show individual segment sizes)\n"
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan         "\t--help     \tShow this message\n"
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan         "\n"
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan         "Included decoders:\n"
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan         "\n",
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan         exec_name,
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan         ifaces[0].name);
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan    printf("    %-6s - %s\n",
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan           ifaces[i].name,
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan           vpx_codec_iface_name(ifaces[i].iface));
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan  exit(EXIT_FAILURE);
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan
61233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void usage_error(const char *fmt, ...) {
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan  va_list ap;
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan  va_start(ap, fmt);
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vprintf(fmt, ap);
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan  printf("\n");
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan  usage_exit();
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan
69233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid my_mem_dtor(vpx_codec_mmap_t *mmap) {
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (verbose)
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan    printf("freeing segment %d\n", mmap->id);
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan  free(mmap->priv);
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan
76233d2500723e5594f3e7c70896ffeeef32b9c950ywanint main(int argc, char **argv) {
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_ctx_t           decoder;
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_iface_t        *iface = ifaces[0].iface;
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_iter_t          iter;
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_dec_cfg_t       cfg;
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_err_t           res = VPX_CODEC_OK;
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int            alloc_sz = 0;
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int            w = 352;
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int            h = 288;
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                     i;
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan  exec_name = argv[0];
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 1; i < argc; i++) {
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!strcmp(argv[i], "--codec")) {
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (i + 1 < argc) {
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int j, k = -1;
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan        i++;
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (!strcmp(ifaces[j].name, argv[i]))
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan            k = j;
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (k >= 0)
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan          iface = ifaces[k].iface;
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan          usage_error("Error: Unrecognized argument (%s) to --codec\n",
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      argv[i]);
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan        usage_error("Error: Option --codec requires argument.\n");
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (!strcmp(argv[i], "-v"))
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan      verbose = 1;
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (!strcmp(argv[i], "-h"))
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (i + 1 < argc) {
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan        h = atoi(argv[++i]);
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan        usage_error("Error: Option -h requires argument.\n");
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (!strcmp(argv[i], "-w"))
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (i + 1 < argc) {
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan        w = atoi(argv[++i]);
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan        usage_error("Error: Option -w requires argument.\n");
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (!strcmp(argv[i], "--help"))
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan      usage_exit();
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan      usage_error("Error: Unrecognized option %s\n\n", argv[i]);
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (argc == 1)
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan    printf("Using built-in defaults. For options, rerun with --help\n\n");
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* XMA mode is not supported on all decoders! */
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!(vpx_codec_get_caps(iface) & VPX_CODEC_CAP_XMA)) {
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan    printf("%s does not support XMA mode!\n", vpx_codec_iface_name(iface));
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return EXIT_FAILURE;
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* The codec knows how much memory to allocate based on the size of the
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * encoded frames. This data can be parsed from the bitstream with
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * vpx_codec_peek_stream_info() if a bitstream is available. Otherwise,
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * a fixed size can be used that will be the upper limit on the frame
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * size the decoder can decode.
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan   */
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cfg.w = w;
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cfg.h = h;
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Initialize the decoder in XMA mode. */
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (vpx_codec_dec_init(&decoder, iface, &cfg, VPX_CODEC_USE_XMA)) {
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan    printf("Failed to initialize decoder in XMA mode: %s\n",
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan           vpx_codec_error(&decoder));
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return EXIT_FAILURE;
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Iterate through the list of memory maps, allocating them with the
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * requested alignment.
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan   */
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan  iter = NULL;
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  do {
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_mmap_t  mmap;
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int    align;
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan    res = vpx_codec_get_mem_map(&decoder, &mmap, &iter);
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan    align = mmap.align ? mmap.align - 1 : 0;
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!res) {
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (verbose)
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan        printf("Allocating segment %u, size %lu, align %u %s\n",
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan               mmap.id, mmap.sz, mmap.align,
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan               mmap.flags & VPX_CODEC_MEM_ZERO ? "(ZEROED)" : "");
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mmap.flags & VPX_CODEC_MEM_ZERO)
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mmap.priv = calloc(1, mmap.sz + align);
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan      else
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mmap.priv = malloc(mmap.sz + align);
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mmap.base = (void *)((((uintptr_t)mmap.priv) + align) &
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  ~(uintptr_t)align);
175233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mmap.dtor = my_mem_dtor;
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan      alloc_sz += mmap.sz + align;
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (vpx_codec_set_mem_map(&decoder, &mmap, 1)) {
179233d2500723e5594f3e7c70896ffeeef32b9c950ywan        printf("Failed to set mmap: %s\n", vpx_codec_error(&decoder));
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return EXIT_FAILURE;
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (res != VPX_CODEC_LIST_END) {
183233d2500723e5594f3e7c70896ffeeef32b9c950ywan      printf("Failed to get mmap: %s\n", vpx_codec_error(&decoder));
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return EXIT_FAILURE;
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } while (res != VPX_CODEC_LIST_END);
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan  printf("%s\n    %d bytes external memory required for %dx%d.\n",
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan         decoder.name, alloc_sz, cfg.w, cfg.h);
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_destroy(&decoder);
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return EXIT_SUCCESS;
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
194