vpxenc.c 88.1 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
/*
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
 *
 *  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.
John Koleszar's avatar
John Koleszar committed
 */

Christian Duvivier's avatar
Christian Duvivier committed
#include "vpx_config.h"
John Koleszar's avatar
John Koleszar committed

#if defined(_WIN32) || defined(__OS2__) || !CONFIG_OS_SUPPORT
#define USE_POSIX_MMAP 0
#else
#define USE_POSIX_MMAP 1
#endif
John Koleszar's avatar
John Koleszar committed

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#if CONFIG_DECODERS
John Koleszar's avatar
John Koleszar committed
#include "vpx/vpx_decoder.h"
John Koleszar's avatar
John Koleszar committed
#if USE_POSIX_MMAP
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#endif
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
John Koleszar's avatar
John Koleszar committed
#endif
#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
#include "vpx/vp8dx.h"
John Koleszar's avatar
John Koleszar committed
#endif

John Koleszar's avatar
John Koleszar committed
#include "vpx_ports/mem_ops.h"
#include "vpx_ports/vpx_timer.h"
#include "tools_common.h"
#include "libmkv/EbmlWriter.h"
#include "libmkv/EbmlIDs.h"
#include "third_party/libyuv/include/libyuv/scale.h"

/* Need special handling of these functions on Windows */
#if defined(_MSC_VER)
/* MSVS doesn't define off_t, and uses _f{seek,tell}i64 */
typedef __int64 off_t;
#define fseeko _fseeki64
#define ftello _ftelli64
#elif defined(_WIN32)
/* MinGW defines off_t as long
   and uses f{seek,tell}o64/off64_t for large files */
#define fseeko fseeko64
#define ftello ftello64
#define off_t off64_t
#define LITERALU64(hi,lo) ((((uint64_t)hi)<<32)|lo)
John Koleszar's avatar
John Koleszar committed

/* We should use 32-bit file operations in WebM file format
 * when building ARM executable file (.axf) with RVCT */
#if !CONFIG_OS_SUPPORT
typedef long off_t;
#define fseeko fseek
#define ftello ftell
#endif

/* Swallow warnings about unused results of fread/fwrite */
static size_t wrap_fread(void *ptr, size_t size, size_t nmemb,
John Koleszar's avatar
John Koleszar committed
                         FILE *stream) {
  return fread(ptr, size, nmemb, stream);
}
#define fread wrap_fread

static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb,
John Koleszar's avatar
John Koleszar committed
                          FILE *stream) {
  return fwrite(ptr, size, nmemb, stream);
}
#define fwrite wrap_fwrite


John Koleszar's avatar
John Koleszar committed
static const char *exec_name;

#define VP8_FOURCC (0x30385056)
#define VP9_FOURCC (0x30395056)
Jim Bankoski's avatar
Jim Bankoski committed
static const struct codec_item {
John Koleszar's avatar
John Koleszar committed
  char const              *name;
Jim Bankoski's avatar
Jim Bankoski committed
  const vpx_codec_iface_t *(*iface)(void);
John Koleszar's avatar
John Koleszar committed
  const vpx_codec_iface_t *(*dx_iface)(void);
Jim Bankoski's avatar
Jim Bankoski committed
  unsigned int             fourcc;
} codecs[] = {
#if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER
  {"vp8", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, VP8_FOURCC},
#elif CONFIG_VP8_ENCODER && !CONFIG_VP8_DECODER
  {"vp8", &vpx_codec_vp8_cx, NULL, VP8_FOURCC},
John Koleszar's avatar
John Koleszar committed
#if CONFIG_VP9_ENCODER && CONFIG_VP9_DECODER
  {"vp9", &vpx_codec_vp9_cx, &vpx_codec_vp9_dx, VP9_FOURCC},
#elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER
  {"vp9", &vpx_codec_vp9_cx, NULL, VP9_FOURCC},
John Koleszar's avatar
John Koleszar committed
#endif
};

static void usage_exit();

#define LOG_ERROR(label) do \
    const char *l=label;\
    va_list ap;\
    va_start(ap, fmt);\
    if(l)\
John Koleszar's avatar
John Koleszar committed
      fprintf(stderr, "%s: ", l);\
    vfprintf(stderr, fmt, ap);\
    fprintf(stderr, "\n");\
    va_end(ap);\
John Koleszar's avatar
John Koleszar committed
  } while(0)
John Koleszar's avatar
John Koleszar committed
void die(const char *fmt, ...) {
John Koleszar's avatar
John Koleszar committed
  LOG_ERROR(NULL);
John Koleszar's avatar
John Koleszar committed
  usage_exit();
John Koleszar's avatar
John Koleszar committed
void fatal(const char *fmt, ...) {
  LOG_ERROR("Fatal");
  exit(EXIT_FAILURE);
John Koleszar's avatar
John Koleszar committed
void warn(const char *fmt, ...) {
  LOG_ERROR("Warning");
static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
                                   const char *s, va_list ap) {
John Koleszar's avatar
John Koleszar committed
  if (ctx->err) {
    const char *detail = vpx_codec_error_detail(ctx);
John Koleszar's avatar
John Koleszar committed
    vfprintf(stderr, s, ap);
    fprintf(stderr, ": %s\n", vpx_codec_error(ctx));
John Koleszar's avatar
John Koleszar committed
    if (detail)
      fprintf(stderr, "    %s\n", detail);
    if (fatal)
      exit(EXIT_FAILURE);
John Koleszar's avatar
John Koleszar committed
  }
static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...) {
  va_list ap;

  va_start(ap, s);
  warn_or_exit_on_errorv(ctx, 1, s, ap);
  va_end(ap);
}

static void warn_or_exit_on_error(vpx_codec_ctx_t *ctx, int fatal,
                                  const char *s, ...) {
  va_list ap;

  va_start(ap, s);
  warn_or_exit_on_errorv(ctx, fatal, s, ap);
  va_end(ap);
}

John Koleszar's avatar
John Koleszar committed
/* This structure is used to abstract the different ways of handling
 * first pass statistics.
 */
John Koleszar's avatar
John Koleszar committed
typedef struct {
  vpx_fixed_buf_t buf;
  int             pass;
  FILE           *file;
  char           *buf_ptr;
  size_t          buf_alloc_sz;
John Koleszar's avatar
John Koleszar committed
} stats_io_t;

John Koleszar's avatar
John Koleszar committed
int stats_open_file(stats_io_t *stats, const char *fpf, int pass) {
  int res;
John Koleszar's avatar
John Koleszar committed
  stats->pass = pass;
John Koleszar's avatar
John Koleszar committed
  if (pass == 0) {
    stats->file = fopen(fpf, "wb");
    stats->buf.sz = 0;
    stats->buf.buf = NULL,
               res = (stats->file != NULL);
  } else {
John Koleszar's avatar
John Koleszar committed
#if 0
#elif USE_POSIX_MMAP
John Koleszar's avatar
John Koleszar committed
    struct stat stat_buf;
Loading full blame...