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#include "./vpxenc.h" 12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_config.h" 13233d2500723e5594f3e7c70896ffeeef32b9c950ywan 14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <assert.h> 15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <limits.h> 16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <math.h> 17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdarg.h> 18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdio.h> 19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h> 20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <string.h> 21233d2500723e5594f3e7c70896ffeeef32b9c950ywan 22233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_encoder.h" 23233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_DECODERS 24233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_decoder.h" 25233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 26233d2500723e5594f3e7c70896ffeeef32b9c950ywan 27233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "third_party/libyuv/include/libyuv/scale.h" 28233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./args.h" 29233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./ivfenc.h" 30233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./tools_common.h" 31233d2500723e5594f3e7c70896ffeeef32b9c950ywan 32233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER 33233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vp8cx.h" 34233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 35233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER 36233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vp8dx.h" 37233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 38233d2500723e5594f3e7c70896ffeeef32b9c950ywan 39233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_integer.h" 40233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_ports/mem_ops.h" 41233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_ports/vpx_timer.h" 42233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./rate_hist.h" 43233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpxstats.h" 44233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./warnings.h" 45233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./webmenc.h" 46233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./y4minput.h" 47233d2500723e5594f3e7c70896ffeeef32b9c950ywan 48233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Swallow warnings about unused results of fread/fwrite */ 49233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic size_t wrap_fread(void *ptr, size_t size, size_t nmemb, 50233d2500723e5594f3e7c70896ffeeef32b9c950ywan FILE *stream) { 51233d2500723e5594f3e7c70896ffeeef32b9c950ywan return fread(ptr, size, nmemb, stream); 52233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 53233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define fread wrap_fread 54233d2500723e5594f3e7c70896ffeeef32b9c950ywan 55233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb, 56233d2500723e5594f3e7c70896ffeeef32b9c950ywan FILE *stream) { 57233d2500723e5594f3e7c70896ffeeef32b9c950ywan return fwrite(ptr, size, nmemb, stream); 58233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 59233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define fwrite wrap_fwrite 60233d2500723e5594f3e7c70896ffeeef32b9c950ywan 61233d2500723e5594f3e7c70896ffeeef32b9c950ywan 62233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const char *exec_name; 63233d2500723e5594f3e7c70896ffeeef32b9c950ywan 64233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal, 65233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *s, va_list ap) { 66233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (ctx->err) { 67233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *detail = vpx_codec_error_detail(ctx); 68233d2500723e5594f3e7c70896ffeeef32b9c950ywan 69233d2500723e5594f3e7c70896ffeeef32b9c950ywan vfprintf(stderr, s, ap); 70233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, ": %s\n", vpx_codec_error(ctx)); 71233d2500723e5594f3e7c70896ffeeef32b9c950ywan 72233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (detail) 73233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, " %s\n", detail); 74233d2500723e5594f3e7c70896ffeeef32b9c950ywan 75233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (fatal) 76233d2500723e5594f3e7c70896ffeeef32b9c950ywan exit(EXIT_FAILURE); 77233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 78233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 79233d2500723e5594f3e7c70896ffeeef32b9c950ywan 80233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...) { 81233d2500723e5594f3e7c70896ffeeef32b9c950ywan va_list ap; 82233d2500723e5594f3e7c70896ffeeef32b9c950ywan 83233d2500723e5594f3e7c70896ffeeef32b9c950ywan va_start(ap, s); 84233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn_or_exit_on_errorv(ctx, 1, s, ap); 85233d2500723e5594f3e7c70896ffeeef32b9c950ywan va_end(ap); 86233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 87233d2500723e5594f3e7c70896ffeeef32b9c950ywan 88233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void warn_or_exit_on_error(vpx_codec_ctx_t *ctx, int fatal, 89233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *s, ...) { 90233d2500723e5594f3e7c70896ffeeef32b9c950ywan va_list ap; 91233d2500723e5594f3e7c70896ffeeef32b9c950ywan 92233d2500723e5594f3e7c70896ffeeef32b9c950ywan va_start(ap, s); 93233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn_or_exit_on_errorv(ctx, fatal, s, ap); 94233d2500723e5594f3e7c70896ffeeef32b9c950ywan va_end(ap); 95233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 96233d2500723e5594f3e7c70896ffeeef32b9c950ywan 97233d2500723e5594f3e7c70896ffeeef32b9c950ywanint read_frame(struct VpxInputContext *input_ctx, vpx_image_t *img) { 98233d2500723e5594f3e7c70896ffeeef32b9c950ywan FILE *f = input_ctx->file; 99233d2500723e5594f3e7c70896ffeeef32b9c950ywan y4m_input *y4m = &input_ctx->y4m; 100233d2500723e5594f3e7c70896ffeeef32b9c950ywan int shortread = 0; 101233d2500723e5594f3e7c70896ffeeef32b9c950ywan 102233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (input_ctx->file_type == FILE_TYPE_Y4M) { 103233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (y4m_input_fetch_frame(y4m, f, img) < 1) 104233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 105233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 106233d2500723e5594f3e7c70896ffeeef32b9c950ywan shortread = read_yuv_frame(input_ctx, img); 107233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 108233d2500723e5594f3e7c70896ffeeef32b9c950ywan 109233d2500723e5594f3e7c70896ffeeef32b9c950ywan return !shortread; 110233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 111233d2500723e5594f3e7c70896ffeeef32b9c950ywan 112233d2500723e5594f3e7c70896ffeeef32b9c950ywanint file_is_y4m(const char detect[4]) { 113233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (memcmp(detect, "YUV4", 4) == 0) { 114233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1; 115233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 116233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 117233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 118233d2500723e5594f3e7c70896ffeeef32b9c950ywan 119233d2500723e5594f3e7c70896ffeeef32b9c950ywanint fourcc_is_ivf(const char detect[4]) { 120233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (memcmp(detect, "DKIF", 4) == 0) { 121233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1; 122233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 123233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 124233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 125233d2500723e5594f3e7c70896ffeeef32b9c950ywan 126233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO 127233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Murmur hash derived from public domain reference implementation at 128233d2500723e5594f3e7c70896ffeeef32b9c950ywan * http:// sites.google.com/site/murmurhash/ 129233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 130233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned int murmur(const void *key, int len, unsigned int seed) { 131233d2500723e5594f3e7c70896ffeeef32b9c950ywan const unsigned int m = 0x5bd1e995; 132233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int r = 24; 133233d2500723e5594f3e7c70896ffeeef32b9c950ywan 134233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int h = seed ^ len; 135233d2500723e5594f3e7c70896ffeeef32b9c950ywan 136233d2500723e5594f3e7c70896ffeeef32b9c950ywan const unsigned char *data = (const unsigned char *)key; 137233d2500723e5594f3e7c70896ffeeef32b9c950ywan 138233d2500723e5594f3e7c70896ffeeef32b9c950ywan while (len >= 4) { 139233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int k; 140233d2500723e5594f3e7c70896ffeeef32b9c950ywan 141233d2500723e5594f3e7c70896ffeeef32b9c950ywan k = (unsigned int)data[0]; 142233d2500723e5594f3e7c70896ffeeef32b9c950ywan k |= (unsigned int)data[1] << 8; 143233d2500723e5594f3e7c70896ffeeef32b9c950ywan k |= (unsigned int)data[2] << 16; 144233d2500723e5594f3e7c70896ffeeef32b9c950ywan k |= (unsigned int)data[3] << 24; 145233d2500723e5594f3e7c70896ffeeef32b9c950ywan 146233d2500723e5594f3e7c70896ffeeef32b9c950ywan k *= m; 147233d2500723e5594f3e7c70896ffeeef32b9c950ywan k ^= k >> r; 148233d2500723e5594f3e7c70896ffeeef32b9c950ywan k *= m; 149233d2500723e5594f3e7c70896ffeeef32b9c950ywan 150233d2500723e5594f3e7c70896ffeeef32b9c950ywan h *= m; 151233d2500723e5594f3e7c70896ffeeef32b9c950ywan h ^= k; 152233d2500723e5594f3e7c70896ffeeef32b9c950ywan 153233d2500723e5594f3e7c70896ffeeef32b9c950ywan data += 4; 154233d2500723e5594f3e7c70896ffeeef32b9c950ywan len -= 4; 155233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 156233d2500723e5594f3e7c70896ffeeef32b9c950ywan 157233d2500723e5594f3e7c70896ffeeef32b9c950ywan switch (len) { 158233d2500723e5594f3e7c70896ffeeef32b9c950ywan case 3: 159233d2500723e5594f3e7c70896ffeeef32b9c950ywan h ^= data[2] << 16; 160233d2500723e5594f3e7c70896ffeeef32b9c950ywan case 2: 161233d2500723e5594f3e7c70896ffeeef32b9c950ywan h ^= data[1] << 8; 162233d2500723e5594f3e7c70896ffeeef32b9c950ywan case 1: 163233d2500723e5594f3e7c70896ffeeef32b9c950ywan h ^= data[0]; 164233d2500723e5594f3e7c70896ffeeef32b9c950ywan h *= m; 165233d2500723e5594f3e7c70896ffeeef32b9c950ywan }; 166233d2500723e5594f3e7c70896ffeeef32b9c950ywan 167233d2500723e5594f3e7c70896ffeeef32b9c950ywan h ^= h >> 13; 168233d2500723e5594f3e7c70896ffeeef32b9c950ywan h *= m; 169233d2500723e5594f3e7c70896ffeeef32b9c950ywan h ^= h >> 15; 170233d2500723e5594f3e7c70896ffeeef32b9c950ywan 171233d2500723e5594f3e7c70896ffeeef32b9c950ywan return h; 172233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 173233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif // CONFIG_WEBM_IO 174233d2500723e5594f3e7c70896ffeeef32b9c950ywan 175233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t debugmode = ARG_DEF("D", "debug", 0, 176233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Debug mode (makes output deterministic)"); 177233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t outputfile = ARG_DEF("o", "output", 1, 178233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Output filename"); 179233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0, 180233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Input file is YV12 "); 181233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0, 182233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Input file is I420 (default)"); 183233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, 184233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Codec to use"); 185233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t passes = ARG_DEF("p", "passes", 1, 186233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Number of passes (1/2)"); 187233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t pass_arg = ARG_DEF(NULL, "pass", 1, 188233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Pass to execute (1/2)"); 189233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t fpf_name = ARG_DEF(NULL, "fpf", 1, 190233d2500723e5594f3e7c70896ffeeef32b9c950ywan "First pass statistics file name"); 191233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t limit = ARG_DEF(NULL, "limit", 1, 192233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Stop encoding after n input frames"); 193233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t skip = ARG_DEF(NULL, "skip", 1, 194233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Skip the first n input frames"); 195233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t deadline = ARG_DEF("d", "deadline", 1, 196233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Deadline per frame (usec)"); 197233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t best_dl = ARG_DEF(NULL, "best", 0, 198233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Use Best Quality Deadline"); 199233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t good_dl = ARG_DEF(NULL, "good", 0, 200233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Use Good Quality Deadline"); 201233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t rt_dl = ARG_DEF(NULL, "rt", 0, 202233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Use Realtime Quality Deadline"); 203233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t quietarg = ARG_DEF("q", "quiet", 0, 204233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Do not print encode progress"); 205233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0, 206233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Show encoder parameters"); 207233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t psnrarg = ARG_DEF(NULL, "psnr", 0, 208233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Show PSNR in status line"); 209233d2500723e5594f3e7c70896ffeeef32b9c950ywan 210233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const struct arg_enum_list test_decode_enum[] = { 211233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"off", TEST_DECODE_OFF}, 212233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"fatal", TEST_DECODE_FATAL}, 213233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"warn", TEST_DECODE_WARN}, 214233d2500723e5594f3e7c70896ffeeef32b9c950ywan {NULL, 0} 215233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 216233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t recontest = ARG_DEF_ENUM(NULL, "test-decode", 1, 217233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Test encode/decode mismatch", 218233d2500723e5594f3e7c70896ffeeef32b9c950ywan test_decode_enum); 219233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t framerate = ARG_DEF(NULL, "fps", 1, 220233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Stream frame rate (rate/scale)"); 221233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t use_ivf = ARG_DEF(NULL, "ivf", 0, 222233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Output IVF (default is WebM if WebM IO is enabled)"); 223233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0, 224233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Makes encoder output partitions. Requires IVF output!"); 225233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t q_hist_n = ARG_DEF(NULL, "q-hist", 1, 226233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Show quantizer histogram (n-buckets)"); 227233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t rate_hist_n = ARG_DEF(NULL, "rate-hist", 1, 228233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Show rate histogram (n-buckets)"); 229233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t disable_warnings = 230233d2500723e5594f3e7c70896ffeeef32b9c950ywan ARG_DEF(NULL, "disable-warnings", 0, 231233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Disable warnings about potentially incorrect encode settings."); 232233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t disable_warning_prompt = 233233d2500723e5594f3e7c70896ffeeef32b9c950ywan ARG_DEF("y", "disable-warning-prompt", 0, 234233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Display warnings, but do not prompt user to continue."); 235233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t experimental_bitstream = 236233d2500723e5594f3e7c70896ffeeef32b9c950ywan ARG_DEF(NULL, "experimental-bitstream", 0, 237233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Allow experimental bitstream features."); 238233d2500723e5594f3e7c70896ffeeef32b9c950ywan 239233d2500723e5594f3e7c70896ffeeef32b9c950ywan 240233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *main_args[] = { 241233d2500723e5594f3e7c70896ffeeef32b9c950ywan &debugmode, 242233d2500723e5594f3e7c70896ffeeef32b9c950ywan &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &skip, 243233d2500723e5594f3e7c70896ffeeef32b9c950ywan &deadline, &best_dl, &good_dl, &rt_dl, 244233d2500723e5594f3e7c70896ffeeef32b9c950ywan &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, 245233d2500723e5594f3e7c70896ffeeef32b9c950ywan &rate_hist_n, &disable_warnings, &disable_warning_prompt, 246233d2500723e5594f3e7c70896ffeeef32b9c950ywan NULL 247233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 248233d2500723e5594f3e7c70896ffeeef32b9c950ywan 249233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t usage = ARG_DEF("u", "usage", 1, 250233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Usage profile number to use"); 251233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t threads = ARG_DEF("t", "threads", 1, 252233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Max number of threads to use"); 253233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t profile = ARG_DEF(NULL, "profile", 1, 254233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Bitstream profile number to use"); 255233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t width = ARG_DEF("w", "width", 1, 256233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Frame width"); 257233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t height = ARG_DEF("h", "height", 1, 258233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Frame height"); 259233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const struct arg_enum_list stereo_mode_enum[] = { 260233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"mono", STEREO_FORMAT_MONO}, 261233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"left-right", STEREO_FORMAT_LEFT_RIGHT}, 262233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"bottom-top", STEREO_FORMAT_BOTTOM_TOP}, 263233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"top-bottom", STEREO_FORMAT_TOP_BOTTOM}, 264233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"right-left", STEREO_FORMAT_RIGHT_LEFT}, 265233d2500723e5594f3e7c70896ffeeef32b9c950ywan {NULL, 0} 266233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 267233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t stereo_mode = ARG_DEF_ENUM(NULL, "stereo-mode", 1, 268233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Stereo 3D video format", stereo_mode_enum); 269233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t timebase = ARG_DEF(NULL, "timebase", 1, 270233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Output timestamp precision (fractional seconds)"); 271233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t error_resilient = ARG_DEF(NULL, "error-resilient", 1, 272233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Enable error resiliency features"); 273233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t lag_in_frames = ARG_DEF(NULL, "lag-in-frames", 1, 274233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Max number of frames to lag"); 275233d2500723e5594f3e7c70896ffeeef32b9c950ywan 276233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *global_args[] = { 277233d2500723e5594f3e7c70896ffeeef32b9c950ywan &use_yv12, &use_i420, &usage, &threads, &profile, 278233d2500723e5594f3e7c70896ffeeef32b9c950ywan &width, &height, &stereo_mode, &timebase, &framerate, 279233d2500723e5594f3e7c70896ffeeef32b9c950ywan &error_resilient, 280233d2500723e5594f3e7c70896ffeeef32b9c950ywan &lag_in_frames, NULL 281233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 282233d2500723e5594f3e7c70896ffeeef32b9c950ywan 283233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t dropframe_thresh = ARG_DEF(NULL, "drop-frame", 1, 284233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Temporal resampling threshold (buf %)"); 285233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t resize_allowed = ARG_DEF(NULL, "resize-allowed", 1, 286233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Spatial resampling enabled (bool)"); 287233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t resize_up_thresh = ARG_DEF(NULL, "resize-up", 1, 288233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Upscale threshold (buf %)"); 289233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t resize_down_thresh = ARG_DEF(NULL, "resize-down", 1, 290233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Downscale threshold (buf %)"); 291233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const struct arg_enum_list end_usage_enum[] = { 292233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"vbr", VPX_VBR}, 293233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"cbr", VPX_CBR}, 294233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"cq", VPX_CQ}, 295233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"q", VPX_Q}, 296233d2500723e5594f3e7c70896ffeeef32b9c950ywan {NULL, 0} 297233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 298233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t end_usage = ARG_DEF_ENUM(NULL, "end-usage", 1, 299233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Rate control mode", end_usage_enum); 300233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t target_bitrate = ARG_DEF(NULL, "target-bitrate", 1, 301233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Bitrate (kbps)"); 302233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t min_quantizer = ARG_DEF(NULL, "min-q", 1, 303233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Minimum (best) quantizer"); 304233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t max_quantizer = ARG_DEF(NULL, "max-q", 1, 305233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Maximum (worst) quantizer"); 306233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t undershoot_pct = ARG_DEF(NULL, "undershoot-pct", 1, 307233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Datarate undershoot (min) target (%)"); 308233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t overshoot_pct = ARG_DEF(NULL, "overshoot-pct", 1, 309233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Datarate overshoot (max) target (%)"); 310233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t buf_sz = ARG_DEF(NULL, "buf-sz", 1, 311233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Client buffer size (ms)"); 312233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t buf_initial_sz = ARG_DEF(NULL, "buf-initial-sz", 1, 313233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Client initial buffer size (ms)"); 314233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t buf_optimal_sz = ARG_DEF(NULL, "buf-optimal-sz", 1, 315233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Client optimal buffer size (ms)"); 316233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *rc_args[] = { 317233d2500723e5594f3e7c70896ffeeef32b9c950ywan &dropframe_thresh, &resize_allowed, &resize_up_thresh, &resize_down_thresh, 318233d2500723e5594f3e7c70896ffeeef32b9c950ywan &end_usage, &target_bitrate, &min_quantizer, &max_quantizer, 319233d2500723e5594f3e7c70896ffeeef32b9c950ywan &undershoot_pct, &overshoot_pct, &buf_sz, &buf_initial_sz, &buf_optimal_sz, 320233d2500723e5594f3e7c70896ffeeef32b9c950ywan NULL 321233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 322233d2500723e5594f3e7c70896ffeeef32b9c950ywan 323233d2500723e5594f3e7c70896ffeeef32b9c950ywan 324233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t bias_pct = ARG_DEF(NULL, "bias-pct", 1, 325233d2500723e5594f3e7c70896ffeeef32b9c950ywan "CBR/VBR bias (0=CBR, 100=VBR)"); 326233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t minsection_pct = ARG_DEF(NULL, "minsection-pct", 1, 327233d2500723e5594f3e7c70896ffeeef32b9c950ywan "GOP min bitrate (% of target)"); 328233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t maxsection_pct = ARG_DEF(NULL, "maxsection-pct", 1, 329233d2500723e5594f3e7c70896ffeeef32b9c950ywan "GOP max bitrate (% of target)"); 330233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *rc_twopass_args[] = { 331233d2500723e5594f3e7c70896ffeeef32b9c950ywan &bias_pct, &minsection_pct, &maxsection_pct, NULL 332233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 333233d2500723e5594f3e7c70896ffeeef32b9c950ywan 334233d2500723e5594f3e7c70896ffeeef32b9c950ywan 335233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t kf_min_dist = ARG_DEF(NULL, "kf-min-dist", 1, 336233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Minimum keyframe interval (frames)"); 337233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t kf_max_dist = ARG_DEF(NULL, "kf-max-dist", 1, 338233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Maximum keyframe interval (frames)"); 339233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t kf_disabled = ARG_DEF(NULL, "disable-kf", 0, 340233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Disable keyframe placement"); 341233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *kf_args[] = { 342233d2500723e5594f3e7c70896ffeeef32b9c950ywan &kf_min_dist, &kf_max_dist, &kf_disabled, NULL 343233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 344233d2500723e5594f3e7c70896ffeeef32b9c950ywan 345233d2500723e5594f3e7c70896ffeeef32b9c950ywan 346233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t noise_sens = ARG_DEF(NULL, "noise-sensitivity", 1, 347233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Noise sensitivity (frames to blur)"); 348233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t sharpness = ARG_DEF(NULL, "sharpness", 1, 349233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Filter sharpness (0-7)"); 350233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t static_thresh = ARG_DEF(NULL, "static-thresh", 1, 351233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Motion detection threshold"); 352233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t cpu_used = ARG_DEF(NULL, "cpu-used", 1, 353233d2500723e5594f3e7c70896ffeeef32b9c950ywan "CPU Used (-16..16)"); 354233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t auto_altref = ARG_DEF(NULL, "auto-alt-ref", 1, 355233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Enable automatic alt reference frames"); 356233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t arnr_maxframes = ARG_DEF(NULL, "arnr-maxframes", 1, 357233d2500723e5594f3e7c70896ffeeef32b9c950ywan "AltRef Max Frames"); 358233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t arnr_strength = ARG_DEF(NULL, "arnr-strength", 1, 359233d2500723e5594f3e7c70896ffeeef32b9c950ywan "AltRef Strength"); 360233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t arnr_type = ARG_DEF(NULL, "arnr-type", 1, 361233d2500723e5594f3e7c70896ffeeef32b9c950ywan "AltRef Type"); 362233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const struct arg_enum_list tuning_enum[] = { 363233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"psnr", VP8_TUNE_PSNR}, 364233d2500723e5594f3e7c70896ffeeef32b9c950ywan {"ssim", VP8_TUNE_SSIM}, 365233d2500723e5594f3e7c70896ffeeef32b9c950ywan {NULL, 0} 366233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 367233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1, 368233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Material to favor", tuning_enum); 369233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1, 370233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Constant/Constrained Quality level"); 371233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1, 372233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Max I-frame bitrate (pct)"); 373233d2500723e5594f3e7c70896ffeeef32b9c950ywan 374233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER 375233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t token_parts = 376233d2500723e5594f3e7c70896ffeeef32b9c950ywan ARG_DEF(NULL, "token-parts", 1, "Number of token partitions to use, log2"); 377233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *vp8_args[] = { 378233d2500723e5594f3e7c70896ffeeef32b9c950ywan &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh, 379233d2500723e5594f3e7c70896ffeeef32b9c950ywan &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type, 380233d2500723e5594f3e7c70896ffeeef32b9c950ywan &tune_ssim, &cq_level, &max_intra_rate_pct, 381233d2500723e5594f3e7c70896ffeeef32b9c950ywan NULL 382233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 383233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const int vp8_arg_ctrl_map[] = { 384233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF, 385233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD, 386233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8E_SET_TOKEN_PARTITIONS, 387233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE, 388233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT, 389233d2500723e5594f3e7c70896ffeeef32b9c950ywan 0 390233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 391233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 392233d2500723e5594f3e7c70896ffeeef32b9c950ywan 393233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_ENCODER 394233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t tile_cols = 395233d2500723e5594f3e7c70896ffeeef32b9c950ywan ARG_DEF(NULL, "tile-columns", 1, "Number of tile columns to use, log2"); 396233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t tile_rows = 397233d2500723e5594f3e7c70896ffeeef32b9c950ywan ARG_DEF(NULL, "tile-rows", 1, "Number of tile rows to use, log2"); 398233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t lossless = ARG_DEF(NULL, "lossless", 1, "Lossless mode"); 399233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t frame_parallel_decoding = ARG_DEF( 400233d2500723e5594f3e7c70896ffeeef32b9c950ywan NULL, "frame-parallel", 1, "Enable frame parallel decodability features"); 401233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t aq_mode = ARG_DEF( 402233d2500723e5594f3e7c70896ffeeef32b9c950ywan NULL, "aq-mode", 1, 403233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Adaptive q mode (0: off (by default), 1: variance 2: complexity, " 404233d2500723e5594f3e7c70896ffeeef32b9c950ywan "3: cyclic refresh)"); 405233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t frame_periodic_boost = ARG_DEF( 406233d2500723e5594f3e7c70896ffeeef32b9c950ywan NULL, "frame_boost", 1, 407233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Enable frame periodic boost (0: off (by default), 1: on)"); 408233d2500723e5594f3e7c70896ffeeef32b9c950ywan 409233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *vp9_args[] = { 410233d2500723e5594f3e7c70896ffeeef32b9c950ywan &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh, 411233d2500723e5594f3e7c70896ffeeef32b9c950ywan &tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type, 412233d2500723e5594f3e7c70896ffeeef32b9c950ywan &tune_ssim, &cq_level, &max_intra_rate_pct, &lossless, 413233d2500723e5594f3e7c70896ffeeef32b9c950ywan &frame_parallel_decoding, &aq_mode, &frame_periodic_boost, 414233d2500723e5594f3e7c70896ffeeef32b9c950ywan NULL 415233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 416233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const int vp9_arg_ctrl_map[] = { 417233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF, 418233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD, 419233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS, 420233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE, 421233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT, 422233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE, 423233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP9E_SET_FRAME_PERIODIC_BOOST, 424233d2500723e5594f3e7c70896ffeeef32b9c950ywan 0 425233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 426233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 427233d2500723e5594f3e7c70896ffeeef32b9c950ywan 428233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *no_args[] = { NULL }; 429233d2500723e5594f3e7c70896ffeeef32b9c950ywan 430233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid usage_exit() { 431233d2500723e5594f3e7c70896ffeeef32b9c950ywan int i; 432233d2500723e5594f3e7c70896ffeeef32b9c950ywan 433233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n", 434233d2500723e5594f3e7c70896ffeeef32b9c950ywan exec_name); 435233d2500723e5594f3e7c70896ffeeef32b9c950ywan 436233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nOptions:\n"); 437233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg_show_usage(stderr, main_args); 438233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nEncoder Global Options:\n"); 439233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg_show_usage(stderr, global_args); 440233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nRate Control Options:\n"); 441233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg_show_usage(stderr, rc_args); 442233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nTwopass Rate Control Options:\n"); 443233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg_show_usage(stderr, rc_twopass_args); 444233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nKeyframe Placement Options:\n"); 445233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg_show_usage(stderr, kf_args); 446233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER 447233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nVP8 Specific Options:\n"); 448233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg_show_usage(stderr, vp8_args); 449233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 450233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_ENCODER 451233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nVP9 Specific Options:\n"); 452233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg_show_usage(stderr, vp9_args); 453233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 454233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nStream timebase (--timebase):\n" 455233d2500723e5594f3e7c70896ffeeef32b9c950ywan " The desired precision of timestamps in the output, expressed\n" 456233d2500723e5594f3e7c70896ffeeef32b9c950ywan " in fractional seconds. Default is 1/1000.\n"); 457233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nIncluded encoders:\n\n"); 458233d2500723e5594f3e7c70896ffeeef32b9c950ywan 459233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < get_vpx_encoder_count(); ++i) { 460233d2500723e5594f3e7c70896ffeeef32b9c950ywan const VpxInterface *const encoder = get_vpx_encoder_by_index(i); 461233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, " %-6s - %s\n", 462233d2500723e5594f3e7c70896ffeeef32b9c950ywan encoder->name, vpx_codec_iface_name(encoder->interface())); 463233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 464233d2500723e5594f3e7c70896ffeeef32b9c950ywan 465233d2500723e5594f3e7c70896ffeeef32b9c950ywan exit(EXIT_FAILURE); 466233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 467233d2500723e5594f3e7c70896ffeeef32b9c950ywan 468233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define mmin(a, b) ((a) < (b) ? (a) : (b)) 469233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void find_mismatch(const vpx_image_t *const img1, 470233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_image_t *const img2, 471233d2500723e5594f3e7c70896ffeeef32b9c950ywan int yloc[4], int uloc[4], int vloc[4]) { 472233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint32_t bsize = 64; 473233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint32_t bsizey = bsize >> img1->y_chroma_shift; 474233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint32_t bsizex = bsize >> img1->x_chroma_shift; 475233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint32_t c_w = 476233d2500723e5594f3e7c70896ffeeef32b9c950ywan (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift; 477233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint32_t c_h = 478233d2500723e5594f3e7c70896ffeeef32b9c950ywan (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift; 479233d2500723e5594f3e7c70896ffeeef32b9c950ywan int match = 1; 480233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint32_t i, j; 481233d2500723e5594f3e7c70896ffeeef32b9c950ywan yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1; 482233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0, match = 1; match && i < img1->d_h; i += bsize) { 483233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (j = 0; match && j < img1->d_w; j += bsize) { 484233d2500723e5594f3e7c70896ffeeef32b9c950ywan int k, l; 485233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int si = mmin(i + bsize, img1->d_h) - i; 486233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int sj = mmin(j + bsize, img1->d_w) - j; 487233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (k = 0; match && k < si; ++k) { 488233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (l = 0; match && l < sj; ++l) { 489233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (*(img1->planes[VPX_PLANE_Y] + 490233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img1->stride[VPX_PLANE_Y] + j + l) != 491233d2500723e5594f3e7c70896ffeeef32b9c950ywan *(img2->planes[VPX_PLANE_Y] + 492233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img2->stride[VPX_PLANE_Y] + j + l)) { 493233d2500723e5594f3e7c70896ffeeef32b9c950ywan yloc[0] = i + k; 494233d2500723e5594f3e7c70896ffeeef32b9c950ywan yloc[1] = j + l; 495233d2500723e5594f3e7c70896ffeeef32b9c950ywan yloc[2] = *(img1->planes[VPX_PLANE_Y] + 496233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img1->stride[VPX_PLANE_Y] + j + l); 497233d2500723e5594f3e7c70896ffeeef32b9c950ywan yloc[3] = *(img2->planes[VPX_PLANE_Y] + 498233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img2->stride[VPX_PLANE_Y] + j + l); 499233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = 0; 500233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 501233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 502233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 503233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 504233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 505233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 506233d2500723e5594f3e7c70896ffeeef32b9c950ywan 507233d2500723e5594f3e7c70896ffeeef32b9c950ywan uloc[0] = uloc[1] = uloc[2] = uloc[3] = -1; 508233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0, match = 1; match && i < c_h; i += bsizey) { 509233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (j = 0; match && j < c_w; j += bsizex) { 510233d2500723e5594f3e7c70896ffeeef32b9c950ywan int k, l; 511233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int si = mmin(i + bsizey, c_h - i); 512233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int sj = mmin(j + bsizex, c_w - j); 513233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (k = 0; match && k < si; ++k) { 514233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (l = 0; match && l < sj; ++l) { 515233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (*(img1->planes[VPX_PLANE_U] + 516233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img1->stride[VPX_PLANE_U] + j + l) != 517233d2500723e5594f3e7c70896ffeeef32b9c950ywan *(img2->planes[VPX_PLANE_U] + 518233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img2->stride[VPX_PLANE_U] + j + l)) { 519233d2500723e5594f3e7c70896ffeeef32b9c950ywan uloc[0] = i + k; 520233d2500723e5594f3e7c70896ffeeef32b9c950ywan uloc[1] = j + l; 521233d2500723e5594f3e7c70896ffeeef32b9c950ywan uloc[2] = *(img1->planes[VPX_PLANE_U] + 522233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img1->stride[VPX_PLANE_U] + j + l); 523233d2500723e5594f3e7c70896ffeeef32b9c950ywan uloc[3] = *(img2->planes[VPX_PLANE_U] + 524233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img2->stride[VPX_PLANE_U] + j + l); 525233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = 0; 526233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 527233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 528233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 529233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 530233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 531233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 532233d2500723e5594f3e7c70896ffeeef32b9c950ywan vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1; 533233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0, match = 1; match && i < c_h; i += bsizey) { 534233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (j = 0; match && j < c_w; j += bsizex) { 535233d2500723e5594f3e7c70896ffeeef32b9c950ywan int k, l; 536233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int si = mmin(i + bsizey, c_h - i); 537233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int sj = mmin(j + bsizex, c_w - j); 538233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (k = 0; match && k < si; ++k) { 539233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (l = 0; match && l < sj; ++l) { 540233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (*(img1->planes[VPX_PLANE_V] + 541233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img1->stride[VPX_PLANE_V] + j + l) != 542233d2500723e5594f3e7c70896ffeeef32b9c950ywan *(img2->planes[VPX_PLANE_V] + 543233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img2->stride[VPX_PLANE_V] + j + l)) { 544233d2500723e5594f3e7c70896ffeeef32b9c950ywan vloc[0] = i + k; 545233d2500723e5594f3e7c70896ffeeef32b9c950ywan vloc[1] = j + l; 546233d2500723e5594f3e7c70896ffeeef32b9c950ywan vloc[2] = *(img1->planes[VPX_PLANE_V] + 547233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img1->stride[VPX_PLANE_V] + j + l); 548233d2500723e5594f3e7c70896ffeeef32b9c950ywan vloc[3] = *(img2->planes[VPX_PLANE_V] + 549233d2500723e5594f3e7c70896ffeeef32b9c950ywan (i + k) * img2->stride[VPX_PLANE_V] + j + l); 550233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = 0; 551233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 552233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 553233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 554233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 555233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 556233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 557233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 558233d2500723e5594f3e7c70896ffeeef32b9c950ywan 559233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int compare_img(const vpx_image_t *const img1, 560233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_image_t *const img2) { 561233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint32_t c_w = 562233d2500723e5594f3e7c70896ffeeef32b9c950ywan (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift; 563233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint32_t c_h = 564233d2500723e5594f3e7c70896ffeeef32b9c950ywan (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift; 565233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint32_t i; 566233d2500723e5594f3e7c70896ffeeef32b9c950ywan int match = 1; 567233d2500723e5594f3e7c70896ffeeef32b9c950ywan 568233d2500723e5594f3e7c70896ffeeef32b9c950ywan match &= (img1->fmt == img2->fmt); 569233d2500723e5594f3e7c70896ffeeef32b9c950ywan match &= (img1->d_w == img2->d_w); 570233d2500723e5594f3e7c70896ffeeef32b9c950ywan match &= (img1->d_h == img2->d_h); 571233d2500723e5594f3e7c70896ffeeef32b9c950ywan 572233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < img1->d_h; ++i) 573233d2500723e5594f3e7c70896ffeeef32b9c950ywan match &= (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y], 574233d2500723e5594f3e7c70896ffeeef32b9c950ywan img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y], 575233d2500723e5594f3e7c70896ffeeef32b9c950ywan img1->d_w) == 0); 576233d2500723e5594f3e7c70896ffeeef32b9c950ywan 577233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < c_h; ++i) 578233d2500723e5594f3e7c70896ffeeef32b9c950ywan match &= (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U], 579233d2500723e5594f3e7c70896ffeeef32b9c950ywan img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U], 580233d2500723e5594f3e7c70896ffeeef32b9c950ywan c_w) == 0); 581233d2500723e5594f3e7c70896ffeeef32b9c950ywan 582233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < c_h; ++i) 583233d2500723e5594f3e7c70896ffeeef32b9c950ywan match &= (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V], 584233d2500723e5594f3e7c70896ffeeef32b9c950ywan img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V], 585233d2500723e5594f3e7c70896ffeeef32b9c950ywan c_w) == 0); 586233d2500723e5594f3e7c70896ffeeef32b9c950ywan 587233d2500723e5594f3e7c70896ffeeef32b9c950ywan return match; 588233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 589233d2500723e5594f3e7c70896ffeeef32b9c950ywan 590233d2500723e5594f3e7c70896ffeeef32b9c950ywan 591233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) 592233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define MAX(x,y) ((x)>(y)?(x):(y)) 593233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER && !CONFIG_VP9_ENCODER 594233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map) 595233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif !CONFIG_VP8_ENCODER && CONFIG_VP9_ENCODER 596233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ARG_CTRL_CNT_MAX NELEMENTS(vp9_arg_ctrl_map) 597233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else 598233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ARG_CTRL_CNT_MAX MAX(NELEMENTS(vp8_arg_ctrl_map), \ 599233d2500723e5594f3e7c70896ffeeef32b9c950ywan NELEMENTS(vp9_arg_ctrl_map)) 600233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 601233d2500723e5594f3e7c70896ffeeef32b9c950ywan 602233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Per-stream configuration */ 603233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct stream_config { 604233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vpx_codec_enc_cfg cfg; 605233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *out_fn; 606233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *stats_fn; 607233d2500723e5594f3e7c70896ffeeef32b9c950ywan stereo_format_t stereo_fmt; 608233d2500723e5594f3e7c70896ffeeef32b9c950ywan int arg_ctrls[ARG_CTRL_CNT_MAX][2]; 609233d2500723e5594f3e7c70896ffeeef32b9c950ywan int arg_ctrl_cnt; 610233d2500723e5594f3e7c70896ffeeef32b9c950ywan int write_webm; 611233d2500723e5594f3e7c70896ffeeef32b9c950ywan int have_kf_max_dist; 612233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 613233d2500723e5594f3e7c70896ffeeef32b9c950ywan 614233d2500723e5594f3e7c70896ffeeef32b9c950ywan 615233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct stream_state { 616233d2500723e5594f3e7c70896ffeeef32b9c950ywan int index; 617233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct stream_state *next; 618233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct stream_config config; 619233d2500723e5594f3e7c70896ffeeef32b9c950ywan FILE *file; 620233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct rate_hist *rate_hist; 621233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct EbmlGlobal ebml; 622233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint32_t hash; 623233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64_t psnr_sse_total; 624233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64_t psnr_samples_total; 625233d2500723e5594f3e7c70896ffeeef32b9c950ywan double psnr_totals[4]; 626233d2500723e5594f3e7c70896ffeeef32b9c950ywan int psnr_count; 627233d2500723e5594f3e7c70896ffeeef32b9c950ywan int counts[64]; 628233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_ctx_t encoder; 629233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int frames_out; 630233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64_t cx_time; 631233d2500723e5594f3e7c70896ffeeef32b9c950ywan size_t nbytes; 632233d2500723e5594f3e7c70896ffeeef32b9c950ywan stats_io_t stats; 633233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vpx_image *img; 634233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_ctx_t decoder; 635233d2500723e5594f3e7c70896ffeeef32b9c950ywan int mismatch_seen; 636233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 637233d2500723e5594f3e7c70896ffeeef32b9c950ywan 638233d2500723e5594f3e7c70896ffeeef32b9c950ywan 639233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid validate_positive_rational(const char *msg, 640233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vpx_rational *rat) { 641233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (rat->den < 0) { 642233d2500723e5594f3e7c70896ffeeef32b9c950ywan rat->num *= -1; 643233d2500723e5594f3e7c70896ffeeef32b9c950ywan rat->den *= -1; 644233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 645233d2500723e5594f3e7c70896ffeeef32b9c950ywan 646233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (rat->num < 0) 647233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Error: %s must be positive\n", msg); 648233d2500723e5594f3e7c70896ffeeef32b9c950ywan 649233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!rat->den) 650233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Error: %s has zero denominator\n", msg); 651233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 652233d2500723e5594f3e7c70896ffeeef32b9c950ywan 653233d2500723e5594f3e7c70896ffeeef32b9c950ywan 654233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void parse_global_config(struct VpxEncoderConfig *global, char **argv) { 655233d2500723e5594f3e7c70896ffeeef32b9c950ywan char **argi, **argj; 656233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct arg arg; 657233d2500723e5594f3e7c70896ffeeef32b9c950ywan 658233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Initialize default parameters */ 659233d2500723e5594f3e7c70896ffeeef32b9c950ywan memset(global, 0, sizeof(*global)); 660233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->codec = get_vpx_encoder_by_index(0); 661233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->passes = 0; 662233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->use_i420 = 1; 663233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Assign default deadline to good quality */ 664233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->deadline = VPX_DL_GOOD_QUALITY; 665233d2500723e5594f3e7c70896ffeeef32b9c950ywan 666233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { 667233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg.argv_step = 1; 668233d2500723e5594f3e7c70896ffeeef32b9c950ywan 669233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg_match(&arg, &codecarg, argi)) { 670233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->codec = get_vpx_encoder_by_name(arg.val); 671233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!global->codec) 672233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Error: Unrecognized argument (%s) to --codec\n", arg.val); 673233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &passes, argi)) { 674233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->passes = arg_parse_uint(&arg); 675233d2500723e5594f3e7c70896ffeeef32b9c950ywan 676233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->passes < 1 || global->passes > 2) 677233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Error: Invalid number of passes (%d)\n", global->passes); 678233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &pass_arg, argi)) { 679233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->pass = arg_parse_uint(&arg); 680233d2500723e5594f3e7c70896ffeeef32b9c950ywan 681233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->pass < 1 || global->pass > 2) 682233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Error: Invalid pass selected (%d)\n", 683233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->pass); 684233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &usage, argi)) 685233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->usage = arg_parse_uint(&arg); 686233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &deadline, argi)) 687233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->deadline = arg_parse_uint(&arg); 688233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &best_dl, argi)) 689233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->deadline = VPX_DL_BEST_QUALITY; 690233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &good_dl, argi)) 691233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->deadline = VPX_DL_GOOD_QUALITY; 692233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &rt_dl, argi)) 693233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->deadline = VPX_DL_REALTIME; 694233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &use_yv12, argi)) 695233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->use_i420 = 0; 696233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &use_i420, argi)) 697233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->use_i420 = 1; 698233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &quietarg, argi)) 699233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->quiet = 1; 700233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &verbosearg, argi)) 701233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->verbose = 1; 702233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &limit, argi)) 703233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->limit = arg_parse_uint(&arg); 704233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &skip, argi)) 705233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->skip_frames = arg_parse_uint(&arg); 706233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &psnrarg, argi)) 707233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->show_psnr = 1; 708233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &recontest, argi)) 709233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->test_decode = arg_parse_enum_or_int(&arg); 710233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &framerate, argi)) { 711233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->framerate = arg_parse_rational(&arg); 712233d2500723e5594f3e7c70896ffeeef32b9c950ywan validate_positive_rational(arg.name, &global->framerate); 713233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->have_framerate = 1; 714233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &out_part, argi)) 715233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->out_part = 1; 716233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &debugmode, argi)) 717233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->debug = 1; 718233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &q_hist_n, argi)) 719233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->show_q_hist_buckets = arg_parse_uint(&arg); 720233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &rate_hist_n, argi)) 721233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->show_rate_hist_buckets = arg_parse_uint(&arg); 722233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &disable_warnings, argi)) 723233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->disable_warnings = 1; 724233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &disable_warning_prompt, argi)) 725233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->disable_warning_prompt = 1; 726233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (arg_match(&arg, &experimental_bitstream, argi)) 727233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->experimental_bitstream = 1; 728233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 729233d2500723e5594f3e7c70896ffeeef32b9c950ywan argj++; 730233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 731233d2500723e5594f3e7c70896ffeeef32b9c950ywan 732233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->pass) { 733233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* DWIM: Assume the user meant passes=2 if pass=2 is specified */ 734233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->pass > global->passes) { 735233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn("Assuming --pass=%d implies --passes=%d\n", 736233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->pass, global->pass); 737233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->passes = global->pass; 738233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 739233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 740233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Validate global config */ 741233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->passes == 0) { 742233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_ENCODER 743233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Make default VP9 passes = 2 until there is a better quality 1-pass 744233d2500723e5594f3e7c70896ffeeef32b9c950ywan // encoder 745233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->passes = (strcmp(global->codec->name, "vp9") == 0 && 746233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->deadline != VPX_DL_REALTIME) ? 2 : 1; 747233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else 748233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->passes = 1; 749233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 750233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 751233d2500723e5594f3e7c70896ffeeef32b9c950ywan 752233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->deadline == VPX_DL_REALTIME && 753233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->passes > 1) { 754233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn("Enforcing one-pass encoding in realtime mode\n"); 755233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->passes = 1; 756233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 757233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 758233d2500723e5594f3e7c70896ffeeef32b9c950ywan 759233d2500723e5594f3e7c70896ffeeef32b9c950ywan 760233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid open_input_file(struct VpxInputContext *input) { 761233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Parse certain options from the input file, if possible */ 762233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->file = strcmp(input->filename, "-") 763233d2500723e5594f3e7c70896ffeeef32b9c950ywan ? fopen(input->filename, "rb") : set_binary_mode(stdin); 764233d2500723e5594f3e7c70896ffeeef32b9c950ywan 765233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!input->file) 766233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Failed to open input file"); 767233d2500723e5594f3e7c70896ffeeef32b9c950ywan 768233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!fseeko(input->file, 0, SEEK_END)) { 769233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Input file is seekable. Figure out how long it is, so we can get 770233d2500723e5594f3e7c70896ffeeef32b9c950ywan * progress info. 771233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 772233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->length = ftello(input->file); 773233d2500723e5594f3e7c70896ffeeef32b9c950ywan rewind(input->file); 774233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 775233d2500723e5594f3e7c70896ffeeef32b9c950ywan 776233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* For RAW input sources, these bytes will applied on the first frame 777233d2500723e5594f3e7c70896ffeeef32b9c950ywan * in read_frame(). 778233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 779233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->detect.buf_read = fread(input->detect.buf, 1, 4, input->file); 780233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->detect.position = 0; 781233d2500723e5594f3e7c70896ffeeef32b9c950ywan 782233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (input->detect.buf_read == 4 783233d2500723e5594f3e7c70896ffeeef32b9c950ywan && file_is_y4m(input->detect.buf)) { 784233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4, 785233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->only_i420) >= 0) { 786233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->file_type = FILE_TYPE_Y4M; 787233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->width = input->y4m.pic_w; 788233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->height = input->y4m.pic_h; 789233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->framerate.numerator = input->y4m.fps_n; 790233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->framerate.denominator = input->y4m.fps_d; 791233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->use_i420 = 0; 792233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else 793233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Unsupported Y4M stream."); 794233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (input->detect.buf_read == 4 && fourcc_is_ivf(input->detect.buf)) { 795233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("IVF is not supported as input."); 796233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 797233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->file_type = FILE_TYPE_RAW; 798233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 799233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 800233d2500723e5594f3e7c70896ffeeef32b9c950ywan 801233d2500723e5594f3e7c70896ffeeef32b9c950ywan 802233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void close_input_file(struct VpxInputContext *input) { 803233d2500723e5594f3e7c70896ffeeef32b9c950ywan fclose(input->file); 804233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (input->file_type == FILE_TYPE_Y4M) 805233d2500723e5594f3e7c70896ffeeef32b9c950ywan y4m_input_close(&input->y4m); 806233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 807233d2500723e5594f3e7c70896ffeeef32b9c950ywan 808233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct stream_state *new_stream(struct VpxEncoderConfig *global, 809233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct stream_state *prev) { 810233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct stream_state *stream; 811233d2500723e5594f3e7c70896ffeeef32b9c950ywan 812233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream = calloc(1, sizeof(*stream)); 813233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream) 814233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Failed to allocate new stream."); 815233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (prev) { 816233d2500723e5594f3e7c70896ffeeef32b9c950ywan memcpy(stream, prev, sizeof(*stream)); 817233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->index++; 818233d2500723e5594f3e7c70896ffeeef32b9c950ywan prev->next = stream; 819233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 820233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_err_t res; 821233d2500723e5594f3e7c70896ffeeef32b9c950ywan 822233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Populate encoder configuration */ 823233d2500723e5594f3e7c70896ffeeef32b9c950ywan res = vpx_codec_enc_config_default(global->codec->interface(), 824233d2500723e5594f3e7c70896ffeeef32b9c950ywan &stream->config.cfg, 825233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->usage); 826233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (res) 827233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Failed to get config: %s\n", vpx_codec_err_to_string(res)); 828233d2500723e5594f3e7c70896ffeeef32b9c950ywan 829233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Change the default timebase to a high enough value so that the 830233d2500723e5594f3e7c70896ffeeef32b9c950ywan * encoder will always create strictly increasing timestamps. 831233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 832233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.g_timebase.den = 1000; 833233d2500723e5594f3e7c70896ffeeef32b9c950ywan 834233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Never use the library's default resolution, require it be parsed 835233d2500723e5594f3e7c70896ffeeef32b9c950ywan * from the file or set on the command line. 836233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 837233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.g_w = 0; 838233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.g_h = 0; 839233d2500723e5594f3e7c70896ffeeef32b9c950ywan 840233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Initialize remaining stream parameters */ 841233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.stereo_fmt = STEREO_FORMAT_MONO; 842233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.write_webm = 1; 843233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO 844233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->ebml.last_pts_ms = -1; 845233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 846233d2500723e5594f3e7c70896ffeeef32b9c950ywan 847233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Allows removal of the application version from the EBML tags */ 848233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->ebml.debug = global->debug; 849233d2500723e5594f3e7c70896ffeeef32b9c950ywan 850233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Default lag_in_frames is 0 in realtime mode */ 851233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->deadline == VPX_DL_REALTIME) 852233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.g_lag_in_frames = 0; 853233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 854233d2500723e5594f3e7c70896ffeeef32b9c950ywan 855233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Output files must be specified for each stream */ 856233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.out_fn = NULL; 857233d2500723e5594f3e7c70896ffeeef32b9c950ywan 858233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->next = NULL; 859233d2500723e5594f3e7c70896ffeeef32b9c950ywan return stream; 860233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 861233d2500723e5594f3e7c70896ffeeef32b9c950ywan 862233d2500723e5594f3e7c70896ffeeef32b9c950ywan 863233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int parse_stream_params(struct VpxEncoderConfig *global, 864233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct stream_state *stream, 865233d2500723e5594f3e7c70896ffeeef32b9c950ywan char **argv) { 866233d2500723e5594f3e7c70896ffeeef32b9c950ywan char **argi, **argj; 867233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct arg arg; 868233d2500723e5594f3e7c70896ffeeef32b9c950ywan static const arg_def_t **ctrl_args = no_args; 869233d2500723e5594f3e7c70896ffeeef32b9c950ywan static const int *ctrl_args_map = NULL; 870233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct stream_config *config = &stream->config; 871233d2500723e5594f3e7c70896ffeeef32b9c950ywan int eos_mark_found = 0; 872233d2500723e5594f3e7c70896ffeeef32b9c950ywan 873233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Handle codec specific options 874233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (0) { 875233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER 876233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (strcmp(global->codec->name, "vp8") == 0) { 877233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctrl_args = vp8_args; 878233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctrl_args_map = vp8_arg_ctrl_map; 879233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 880233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_ENCODER 881233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (strcmp(global->codec->name, "vp9") == 0) { 882233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctrl_args = vp9_args; 883233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctrl_args_map = vp9_arg_ctrl_map; 884233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 885233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 886233d2500723e5594f3e7c70896ffeeef32b9c950ywan 887233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { 888233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg.argv_step = 1; 889233d2500723e5594f3e7c70896ffeeef32b9c950ywan 890233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Once we've found an end-of-stream marker (--) we want to continue 891233d2500723e5594f3e7c70896ffeeef32b9c950ywan * shifting arguments but not consuming them. 892233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 893233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (eos_mark_found) { 894233d2500723e5594f3e7c70896ffeeef32b9c950ywan argj++; 895233d2500723e5594f3e7c70896ffeeef32b9c950ywan continue; 896233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (!strcmp(*argj, "--")) { 897233d2500723e5594f3e7c70896ffeeef32b9c950ywan eos_mark_found = 1; 898233d2500723e5594f3e7c70896ffeeef32b9c950ywan continue; 899233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 900233d2500723e5594f3e7c70896ffeeef32b9c950ywan 901233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (0) { 902233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &outputfile, argi)) { 903233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->out_fn = arg.val; 904233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &fpf_name, argi)) { 905233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->stats_fn = arg.val; 906233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &use_ivf, argi)) { 907233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->write_webm = 0; 908233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &threads, argi)) { 909233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.g_threads = arg_parse_uint(&arg); 910233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &profile, argi)) { 911233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.g_profile = arg_parse_uint(&arg); 912233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &width, argi)) { 913233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.g_w = arg_parse_uint(&arg); 914233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &height, argi)) { 915233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.g_h = arg_parse_uint(&arg); 916233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &stereo_mode, argi)) { 917233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->stereo_fmt = arg_parse_enum_or_int(&arg); 918233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &timebase, argi)) { 919233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.g_timebase = arg_parse_rational(&arg); 920233d2500723e5594f3e7c70896ffeeef32b9c950ywan validate_positive_rational(arg.name, &config->cfg.g_timebase); 921233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &error_resilient, argi)) { 922233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.g_error_resilient = arg_parse_uint(&arg); 923233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &lag_in_frames, argi)) { 924233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.g_lag_in_frames = arg_parse_uint(&arg); 925233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->deadline == VPX_DL_REALTIME && 926233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.g_lag_in_frames != 0) { 927233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn("non-zero %s option ignored in realtime mode.\n", arg.name); 928233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.g_lag_in_frames = 0; 929233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 930233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &dropframe_thresh, argi)) { 931233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg); 932233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &resize_allowed, argi)) { 933233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_resize_allowed = arg_parse_uint(&arg); 934233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &resize_up_thresh, argi)) { 935233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg); 936233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &resize_down_thresh, argi)) { 937233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_resize_down_thresh = arg_parse_uint(&arg); 938233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &end_usage, argi)) { 939233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg); 940233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &target_bitrate, argi)) { 941233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_target_bitrate = arg_parse_uint(&arg); 942233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &min_quantizer, argi)) { 943233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_min_quantizer = arg_parse_uint(&arg); 944233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &max_quantizer, argi)) { 945233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_max_quantizer = arg_parse_uint(&arg); 946233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &undershoot_pct, argi)) { 947233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_undershoot_pct = arg_parse_uint(&arg); 948233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &overshoot_pct, argi)) { 949233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_overshoot_pct = arg_parse_uint(&arg); 950233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &buf_sz, argi)) { 951233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_buf_sz = arg_parse_uint(&arg); 952233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &buf_initial_sz, argi)) { 953233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_buf_initial_sz = arg_parse_uint(&arg); 954233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &buf_optimal_sz, argi)) { 955233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_buf_optimal_sz = arg_parse_uint(&arg); 956233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &bias_pct, argi)) { 957233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg); 958233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->passes < 2) 959233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn("option %s ignored in one-pass mode.\n", arg.name); 960233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &minsection_pct, argi)) { 961233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg); 962233d2500723e5594f3e7c70896ffeeef32b9c950ywan 963233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->passes < 2) 964233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn("option %s ignored in one-pass mode.\n", arg.name); 965233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &maxsection_pct, argi)) { 966233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg); 967233d2500723e5594f3e7c70896ffeeef32b9c950ywan 968233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->passes < 2) 969233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn("option %s ignored in one-pass mode.\n", arg.name); 970233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &kf_min_dist, argi)) { 971233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.kf_min_dist = arg_parse_uint(&arg); 972233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &kf_max_dist, argi)) { 973233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.kf_max_dist = arg_parse_uint(&arg); 974233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->have_kf_max_dist = 1; 975233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (arg_match(&arg, &kf_disabled, argi)) { 976233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->cfg.kf_mode = VPX_KF_DISABLED; 977233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 978233d2500723e5594f3e7c70896ffeeef32b9c950ywan int i, match = 0; 979233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; ctrl_args[i]; i++) { 980233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg_match(&arg, ctrl_args[i], argi)) { 981233d2500723e5594f3e7c70896ffeeef32b9c950ywan int j; 982233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = 1; 983233d2500723e5594f3e7c70896ffeeef32b9c950ywan 984233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Point either to the next free element or the first 985233d2500723e5594f3e7c70896ffeeef32b9c950ywan * instance of this control. 986233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 987233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (j = 0; j < config->arg_ctrl_cnt; j++) 988233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (config->arg_ctrls[j][0] == ctrl_args_map[i]) 989233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 990233d2500723e5594f3e7c70896ffeeef32b9c950ywan 991233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Update/insert */ 992233d2500723e5594f3e7c70896ffeeef32b9c950ywan assert(j < ARG_CTRL_CNT_MAX); 993233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (j < ARG_CTRL_CNT_MAX) { 994233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->arg_ctrls[j][0] = ctrl_args_map[i]; 995233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->arg_ctrls[j][1] = arg_parse_enum_or_int(&arg); 996233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (j == config->arg_ctrl_cnt) 997233d2500723e5594f3e7c70896ffeeef32b9c950ywan config->arg_ctrl_cnt++; 998233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 999233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1000233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1001233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1002233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!match) 1003233d2500723e5594f3e7c70896ffeeef32b9c950ywan argj++; 1004233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1005233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1006233d2500723e5594f3e7c70896ffeeef32b9c950ywan return eos_mark_found; 1007233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1008233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1009233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1010233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define FOREACH_STREAM(func) \ 1011233d2500723e5594f3e7c70896ffeeef32b9c950ywan do { \ 1012233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct stream_state *stream; \ 1013233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (stream = streams; stream; stream = stream->next) { \ 1014233d2500723e5594f3e7c70896ffeeef32b9c950ywan func; \ 1015233d2500723e5594f3e7c70896ffeeef32b9c950ywan } \ 1016233d2500723e5594f3e7c70896ffeeef32b9c950ywan } while (0) 1017233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1018233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1019233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void validate_stream_config(const struct stream_state *stream, 1020233d2500723e5594f3e7c70896ffeeef32b9c950ywan const struct VpxEncoderConfig *global) { 1021233d2500723e5594f3e7c70896ffeeef32b9c950ywan const struct stream_state *streami; 1022233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1023233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->config.cfg.g_w || !stream->config.cfg.g_h) 1024233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Stream %d: Specify stream dimensions with --width (-w) " 1025233d2500723e5594f3e7c70896ffeeef32b9c950ywan " and --height (-h)", stream->index); 1026233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1027233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->config.cfg.g_profile != 0 && !global->experimental_bitstream) { 1028233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Stream %d: profile %d is experimental and requires the --%s flag", 1029233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->index, stream->config.cfg.g_profile, 1030233d2500723e5594f3e7c70896ffeeef32b9c950ywan experimental_bitstream.long_name); 1031233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1032233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1033233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (streami = stream; streami; streami = streami->next) { 1034233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* All streams require output files */ 1035233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!streami->config.out_fn) 1036233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Stream %d: Output file is required (specify with -o)", 1037233d2500723e5594f3e7c70896ffeeef32b9c950ywan streami->index); 1038233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1039233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Check for two streams outputting to the same file */ 1040233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (streami != stream) { 1041233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *a = stream->config.out_fn; 1042233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *b = streami->config.out_fn; 1043233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!strcmp(a, b) && strcmp(a, "/dev/null") && strcmp(a, ":nul")) 1044233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Stream %d: duplicate output file (from stream %d)", 1045233d2500723e5594f3e7c70896ffeeef32b9c950ywan streami->index, stream->index); 1046233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1047233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1048233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Check for two streams sharing a stats file. */ 1049233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (streami != stream) { 1050233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *a = stream->config.stats_fn; 1051233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *b = streami->config.stats_fn; 1052233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (a && b && !strcmp(a, b)) 1053233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Stream %d: duplicate stats file (from stream %d)", 1054233d2500723e5594f3e7c70896ffeeef32b9c950ywan streami->index, stream->index); 1055233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1056233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1057233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1058233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1059233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1060233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void set_stream_dimensions(struct stream_state *stream, 1061233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int w, 1062233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int h) { 1063233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->config.cfg.g_w) { 1064233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->config.cfg.g_h) 1065233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.g_w = w; 1066233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 1067233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.g_w = w * stream->config.cfg.g_h / h; 1068233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1069233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->config.cfg.g_h) { 1070233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.g_h = h * stream->config.cfg.g_w / w; 1071233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1072233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1073233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1074233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1075233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void set_default_kf_interval(struct stream_state *stream, 1076233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxEncoderConfig *global) { 1077233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Use a max keyframe interval of 5 seconds, if none was 1078233d2500723e5594f3e7c70896ffeeef32b9c950ywan * specified on the command line. 1079233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 1080233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->config.have_kf_max_dist) { 1081233d2500723e5594f3e7c70896ffeeef32b9c950ywan double framerate = (double)global->framerate.num / global->framerate.den; 1082233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (framerate > 0.0) 1083233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.kf_max_dist = (unsigned int)(5.0 * framerate); 1084233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1085233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1086233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1087233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1088233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void show_stream_config(struct stream_state *stream, 1089233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxEncoderConfig *global, 1090233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxInputContext *input) { 1091233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1092233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define SHOW(field) \ 1093233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, " %-28s = %d\n", #field, stream->config.cfg.field) 1094233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1095233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->index == 0) { 1096233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "Codec: %s\n", 1097233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_iface_name(global->codec->interface())); 1098233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "Source file: %s Format: %s\n", input->filename, 1099233d2500723e5594f3e7c70896ffeeef32b9c950ywan input->use_i420 ? "I420" : "YV12"); 1100233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1101233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->next || stream->index) 1102233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\nStream Index: %d\n", stream->index); 1103233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "Destination file: %s\n", stream->config.out_fn); 1104233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "Encoder parameters:\n"); 1105233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1106233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_usage); 1107233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_threads); 1108233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_profile); 1109233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_w); 1110233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_h); 1111233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_timebase.num); 1112233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_timebase.den); 1113233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_error_resilient); 1114233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_pass); 1115233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(g_lag_in_frames); 1116233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_dropframe_thresh); 1117233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_resize_allowed); 1118233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_resize_up_thresh); 1119233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_resize_down_thresh); 1120233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_end_usage); 1121233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_target_bitrate); 1122233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_min_quantizer); 1123233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_max_quantizer); 1124233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_undershoot_pct); 1125233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_overshoot_pct); 1126233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_buf_sz); 1127233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_buf_initial_sz); 1128233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_buf_optimal_sz); 1129233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_2pass_vbr_bias_pct); 1130233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_2pass_vbr_minsection_pct); 1131233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(rc_2pass_vbr_maxsection_pct); 1132233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(kf_mode); 1133233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(kf_min_dist); 1134233d2500723e5594f3e7c70896ffeeef32b9c950ywan SHOW(kf_max_dist); 1135233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1136233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1137233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1138233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void open_output_file(struct stream_state *stream, 1139233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxEncoderConfig *global) { 1140233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *fn = stream->config.out_fn; 1141233d2500723e5594f3e7c70896ffeeef32b9c950ywan const struct vpx_codec_enc_cfg *const cfg = &stream->config.cfg; 1142233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1143233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cfg->g_pass == VPX_RC_FIRST_PASS) 1144233d2500723e5594f3e7c70896ffeeef32b9c950ywan return; 1145233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1146233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout); 1147233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1148233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->file) 1149233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Failed to open output file"); 1150233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1151233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR)) 1152233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("WebM output to pipes not supported."); 1153233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1154233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO 1155233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->config.write_webm) { 1156233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->ebml.stream = stream->file; 1157233d2500723e5594f3e7c70896ffeeef32b9c950ywan write_webm_file_header(&stream->ebml, cfg, 1158233d2500723e5594f3e7c70896ffeeef32b9c950ywan &global->framerate, 1159233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.stereo_fmt, 1160233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->codec->fourcc); 1161233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1162233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 1163233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1164233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->config.write_webm) { 1165233d2500723e5594f3e7c70896ffeeef32b9c950ywan ivf_write_file_header(stream->file, cfg, global->codec->fourcc, 0); 1166233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1167233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1168233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1169233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1170233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void close_output_file(struct stream_state *stream, 1171233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int fourcc) { 1172233d2500723e5594f3e7c70896ffeeef32b9c950ywan const struct vpx_codec_enc_cfg *const cfg = &stream->config.cfg; 1173233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1174233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cfg->g_pass == VPX_RC_FIRST_PASS) 1175233d2500723e5594f3e7c70896ffeeef32b9c950ywan return; 1176233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1177233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO 1178233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->config.write_webm) { 1179233d2500723e5594f3e7c70896ffeeef32b9c950ywan write_webm_file_footer(&stream->ebml, stream->hash); 1180233d2500723e5594f3e7c70896ffeeef32b9c950ywan free(stream->ebml.cue_list); 1181233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->ebml.cue_list = NULL; 1182233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1183233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 1184233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1185233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->config.write_webm) { 1186233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!fseek(stream->file, 0, SEEK_SET)) 1187233d2500723e5594f3e7c70896ffeeef32b9c950ywan ivf_write_file_header(stream->file, &stream->config.cfg, 1188233d2500723e5594f3e7c70896ffeeef32b9c950ywan fourcc, 1189233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->frames_out); 1190233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1191233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1192233d2500723e5594f3e7c70896ffeeef32b9c950ywan fclose(stream->file); 1193233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1194233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1195233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1196233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void setup_pass(struct stream_state *stream, 1197233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxEncoderConfig *global, 1198233d2500723e5594f3e7c70896ffeeef32b9c950ywan int pass) { 1199233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->config.stats_fn) { 1200233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stats_open_file(&stream->stats, stream->config.stats_fn, 1201233d2500723e5594f3e7c70896ffeeef32b9c950ywan pass)) 1202233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Failed to open statistics store"); 1203233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 1204233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stats_open_mem(&stream->stats, pass)) 1205233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Failed to open statistics store"); 1206233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1207233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1208233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.g_pass = global->passes == 2 1209233d2500723e5594f3e7c70896ffeeef32b9c950ywan ? pass ? VPX_RC_LAST_PASS : VPX_RC_FIRST_PASS 1210233d2500723e5594f3e7c70896ffeeef32b9c950ywan : VPX_RC_ONE_PASS; 1211233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (pass) 1212233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats); 1213233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1214233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->cx_time = 0; 1215233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->nbytes = 0; 1216233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->frames_out = 0; 1217233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1218233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1219233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1220233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void initialize_encoder(struct stream_state *stream, 1221233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxEncoderConfig *global) { 1222233d2500723e5594f3e7c70896ffeeef32b9c950ywan int i; 1223233d2500723e5594f3e7c70896ffeeef32b9c950ywan int flags = 0; 1224233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1225233d2500723e5594f3e7c70896ffeeef32b9c950ywan flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0; 1226233d2500723e5594f3e7c70896ffeeef32b9c950ywan flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0; 1227233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1228233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Construct Encoder Context */ 1229233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_enc_init(&stream->encoder, global->codec->interface(), 1230233d2500723e5594f3e7c70896ffeeef32b9c950ywan &stream->config.cfg, flags); 1231233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder"); 1232233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1233233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Note that we bypass the vpx_codec_control wrapper macro because 1234233d2500723e5594f3e7c70896ffeeef32b9c950ywan * we're being clever to store the control IDs in an array. Real 1235233d2500723e5594f3e7c70896ffeeef32b9c950ywan * applications will want to make use of the enumerations directly 1236233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 1237233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < stream->config.arg_ctrl_cnt; i++) { 1238233d2500723e5594f3e7c70896ffeeef32b9c950ywan int ctrl = stream->config.arg_ctrls[i][0]; 1239233d2500723e5594f3e7c70896ffeeef32b9c950ywan int value = stream->config.arg_ctrls[i][1]; 1240233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (vpx_codec_control_(&stream->encoder, ctrl, value)) 1241233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "Error: Tried to set control %d = %d\n", 1242233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctrl, value); 1243233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1244233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctx_exit_on_error(&stream->encoder, "Failed to control codec"); 1245233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1246233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1247233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_DECODERS 1248233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->test_decode != TEST_DECODE_OFF) { 1249233d2500723e5594f3e7c70896ffeeef32b9c950ywan const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name); 1250233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_dec_init(&stream->decoder, decoder->interface(), NULL, 0); 1251233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1252233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 1253233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1254233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1255233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1256233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_frame(struct stream_state *stream, 1257233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxEncoderConfig *global, 1258233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vpx_image *img, 1259233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int frames_in) { 1260233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_pts_t frame_start, next_frame_start; 1261233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vpx_codec_enc_cfg *cfg = &stream->config.cfg; 1262233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vpx_usec_timer timer; 1263233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1264233d2500723e5594f3e7c70896ffeeef32b9c950ywan frame_start = (cfg->g_timebase.den * (int64_t)(frames_in - 1) 1265233d2500723e5594f3e7c70896ffeeef32b9c950ywan * global->framerate.den) 1266233d2500723e5594f3e7c70896ffeeef32b9c950ywan / cfg->g_timebase.num / global->framerate.num; 1267233d2500723e5594f3e7c70896ffeeef32b9c950ywan next_frame_start = (cfg->g_timebase.den * (int64_t)(frames_in) 1268233d2500723e5594f3e7c70896ffeeef32b9c950ywan * global->framerate.den) 1269233d2500723e5594f3e7c70896ffeeef32b9c950ywan / cfg->g_timebase.num / global->framerate.num; 1270233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1271233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Scale if necessary */ 1272233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (img && (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) { 1273233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->img) 1274233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, 1275233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg->g_w, cfg->g_h, 16); 1276233d2500723e5594f3e7c70896ffeeef32b9c950ywan I420Scale(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y], 1277233d2500723e5594f3e7c70896ffeeef32b9c950ywan img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U], 1278233d2500723e5594f3e7c70896ffeeef32b9c950ywan img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V], 1279233d2500723e5594f3e7c70896ffeeef32b9c950ywan img->d_w, img->d_h, 1280233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->img->planes[VPX_PLANE_Y], 1281233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->img->stride[VPX_PLANE_Y], 1282233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->img->planes[VPX_PLANE_U], 1283233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->img->stride[VPX_PLANE_U], 1284233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->img->planes[VPX_PLANE_V], 1285233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->img->stride[VPX_PLANE_V], 1286233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->img->d_w, stream->img->d_h, 1287233d2500723e5594f3e7c70896ffeeef32b9c950ywan kFilterBox); 1288233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1289233d2500723e5594f3e7c70896ffeeef32b9c950ywan img = stream->img; 1290233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1291233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1292233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_usec_timer_start(&timer); 1293233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_encode(&stream->encoder, img, frame_start, 1294233d2500723e5594f3e7c70896ffeeef32b9c950ywan (unsigned long)(next_frame_start - frame_start), 1295233d2500723e5594f3e7c70896ffeeef32b9c950ywan 0, global->deadline); 1296233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_usec_timer_mark(&timer); 1297233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->cx_time += vpx_usec_timer_elapsed(&timer); 1298233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctx_exit_on_error(&stream->encoder, "Stream %d: Failed to encode frame", 1299233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->index); 1300233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1301233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1302233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1303233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void update_quantizer_histogram(struct stream_state *stream) { 1304233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->config.cfg.g_pass != VPX_RC_FIRST_PASS) { 1305233d2500723e5594f3e7c70896ffeeef32b9c950ywan int q; 1306233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1307233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_control(&stream->encoder, VP8E_GET_LAST_QUANTIZER_64, &q); 1308233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctx_exit_on_error(&stream->encoder, "Failed to read quantizer"); 1309233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->counts[q]++; 1310233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1311233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1312233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1313233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1314233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void get_cx_data(struct stream_state *stream, 1315233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxEncoderConfig *global, 1316233d2500723e5594f3e7c70896ffeeef32b9c950ywan int *got_data) { 1317233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_codec_cx_pkt_t *pkt; 1318233d2500723e5594f3e7c70896ffeeef32b9c950ywan const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg; 1319233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_iter_t iter = NULL; 1320233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1321233d2500723e5594f3e7c70896ffeeef32b9c950ywan *got_data = 0; 1322233d2500723e5594f3e7c70896ffeeef32b9c950ywan while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter))) { 1323233d2500723e5594f3e7c70896ffeeef32b9c950ywan static size_t fsize = 0; 1324233d2500723e5594f3e7c70896ffeeef32b9c950ywan static off_t ivf_header_pos = 0; 1325233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1326233d2500723e5594f3e7c70896ffeeef32b9c950ywan switch (pkt->kind) { 1327233d2500723e5594f3e7c70896ffeeef32b9c950ywan case VPX_CODEC_CX_FRAME_PKT: 1328233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) { 1329233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->frames_out++; 1330233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1331233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!global->quiet) 1332233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, " %6luF", (unsigned long)pkt->data.frame.sz); 1333233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1334233d2500723e5594f3e7c70896ffeeef32b9c950ywan update_rate_histogram(stream->rate_hist, cfg, pkt); 1335233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO 1336233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->config.write_webm) { 1337233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Update the hash */ 1338233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->ebml.debug) 1339233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->hash = murmur(pkt->data.frame.buf, 1340233d2500723e5594f3e7c70896ffeeef32b9c950ywan (int)pkt->data.frame.sz, 1341233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->hash); 1342233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1343233d2500723e5594f3e7c70896ffeeef32b9c950ywan write_webm_block(&stream->ebml, cfg, pkt); 1344233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1345233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 1346233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->config.write_webm) { 1347233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (pkt->data.frame.partition_id <= 0) { 1348233d2500723e5594f3e7c70896ffeeef32b9c950ywan ivf_header_pos = ftello(stream->file); 1349233d2500723e5594f3e7c70896ffeeef32b9c950ywan fsize = pkt->data.frame.sz; 1350233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1351233d2500723e5594f3e7c70896ffeeef32b9c950ywan ivf_write_frame_header(stream->file, pkt->data.frame.pts, fsize); 1352233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 1353233d2500723e5594f3e7c70896ffeeef32b9c950ywan fsize += pkt->data.frame.sz; 1354233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1355233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) { 1356233d2500723e5594f3e7c70896ffeeef32b9c950ywan off_t currpos = ftello(stream->file); 1357233d2500723e5594f3e7c70896ffeeef32b9c950ywan fseeko(stream->file, ivf_header_pos, SEEK_SET); 1358233d2500723e5594f3e7c70896ffeeef32b9c950ywan ivf_write_frame_size(stream->file, fsize); 1359233d2500723e5594f3e7c70896ffeeef32b9c950ywan fseeko(stream->file, currpos, SEEK_SET); 1360233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1361233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1362233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1363233d2500723e5594f3e7c70896ffeeef32b9c950ywan (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, 1364233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->file); 1365233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1366233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->nbytes += pkt->data.raw.sz; 1367233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1368233d2500723e5594f3e7c70896ffeeef32b9c950ywan *got_data = 1; 1369233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_DECODERS 1370233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) { 1371233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_decode(&stream->decoder, pkt->data.frame.buf, 1372233d2500723e5594f3e7c70896ffeeef32b9c950ywan (unsigned int)pkt->data.frame.sz, NULL, 0); 1373233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->decoder.err) { 1374233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn_or_exit_on_error(&stream->decoder, 1375233d2500723e5594f3e7c70896ffeeef32b9c950ywan global->test_decode == TEST_DECODE_FATAL, 1376233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Failed to decode frame %d in stream %d", 1377233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->frames_out + 1, stream->index); 1378233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->mismatch_seen = stream->frames_out + 1; 1379233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1380233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1381233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 1382233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 1383233d2500723e5594f3e7c70896ffeeef32b9c950ywan case VPX_CODEC_STATS_PKT: 1384233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->frames_out++; 1385233d2500723e5594f3e7c70896ffeeef32b9c950ywan stats_write(&stream->stats, 1386233d2500723e5594f3e7c70896ffeeef32b9c950ywan pkt->data.twopass_stats.buf, 1387233d2500723e5594f3e7c70896ffeeef32b9c950ywan pkt->data.twopass_stats.sz); 1388233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->nbytes += pkt->data.raw.sz; 1389233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 1390233d2500723e5594f3e7c70896ffeeef32b9c950ywan case VPX_CODEC_PSNR_PKT: 1391233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1392233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global->show_psnr) { 1393233d2500723e5594f3e7c70896ffeeef32b9c950ywan int i; 1394233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1395233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->psnr_sse_total += pkt->data.psnr.sse[0]; 1396233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->psnr_samples_total += pkt->data.psnr.samples[0]; 1397233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < 4; i++) { 1398233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!global->quiet) 1399233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "%.3f ", pkt->data.psnr.psnr[i]); 1400233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->psnr_totals[i] += pkt->data.psnr.psnr[i]; 1401233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1402233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->psnr_count++; 1403233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1404233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1405233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 1406233d2500723e5594f3e7c70896ffeeef32b9c950ywan default: 1407233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 1408233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1409233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1410233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1411233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1412233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1413233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void show_psnr(struct stream_state *stream) { 1414233d2500723e5594f3e7c70896ffeeef32b9c950ywan int i; 1415233d2500723e5594f3e7c70896ffeeef32b9c950ywan double ovpsnr; 1416233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1417233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->psnr_count) 1418233d2500723e5594f3e7c70896ffeeef32b9c950ywan return; 1419233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1420233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "Stream %d PSNR (Overall/Avg/Y/U/V)", stream->index); 1421233d2500723e5594f3e7c70896ffeeef32b9c950ywan ovpsnr = sse_to_psnr((double)stream->psnr_samples_total, 255.0, 1422233d2500723e5594f3e7c70896ffeeef32b9c950ywan (double)stream->psnr_sse_total); 1423233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, " %.3f", ovpsnr); 1424233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1425233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < 4; i++) { 1426233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, " %.3f", stream->psnr_totals[i] / stream->psnr_count); 1427233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1428233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\n"); 1429233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1430233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1431233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1432233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic float usec_to_fps(uint64_t usec, unsigned int frames) { 1433233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0); 1434233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1435233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1436233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1437233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void test_decode(struct stream_state *stream, 1438233d2500723e5594f3e7c70896ffeeef32b9c950ywan enum TestDecodeFatality fatal, 1439233d2500723e5594f3e7c70896ffeeef32b9c950ywan const VpxInterface *codec) { 1440233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_image_t enc_img, dec_img; 1441233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1442233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->mismatch_seen) 1443233d2500723e5594f3e7c70896ffeeef32b9c950ywan return; 1444233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1445233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Get the internal reference frame */ 1446233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (strcmp(codec->name, "vp8") == 0) { 1447233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vpx_ref_frame ref_enc, ref_dec; 1448233d2500723e5594f3e7c70896ffeeef32b9c950ywan int width, height; 1449233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1450233d2500723e5594f3e7c70896ffeeef32b9c950ywan width = (stream->config.cfg.g_w + 15) & ~15; 1451233d2500723e5594f3e7c70896ffeeef32b9c950ywan height = (stream->config.cfg.g_h + 15) & ~15; 1452233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_img_alloc(&ref_enc.img, VPX_IMG_FMT_I420, width, height, 1); 1453233d2500723e5594f3e7c70896ffeeef32b9c950ywan enc_img = ref_enc.img; 1454233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_img_alloc(&ref_dec.img, VPX_IMG_FMT_I420, width, height, 1); 1455233d2500723e5594f3e7c70896ffeeef32b9c950ywan dec_img = ref_dec.img; 1456233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1457233d2500723e5594f3e7c70896ffeeef32b9c950ywan ref_enc.frame_type = VP8_LAST_FRAME; 1458233d2500723e5594f3e7c70896ffeeef32b9c950ywan ref_dec.frame_type = VP8_LAST_FRAME; 1459233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_control(&stream->encoder, VP8_COPY_REFERENCE, &ref_enc); 1460233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_control(&stream->decoder, VP8_COPY_REFERENCE, &ref_dec); 1461233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 1462233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vp9_ref_frame ref; 1463233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1464233d2500723e5594f3e7c70896ffeeef32b9c950ywan ref.idx = 0; 1465233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_control(&stream->encoder, VP9_GET_REFERENCE, &ref); 1466233d2500723e5594f3e7c70896ffeeef32b9c950ywan enc_img = ref.img; 1467233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_control(&stream->decoder, VP9_GET_REFERENCE, &ref); 1468233d2500723e5594f3e7c70896ffeeef32b9c950ywan dec_img = ref.img; 1469233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1470233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctx_exit_on_error(&stream->encoder, "Failed to get encoder reference frame"); 1471233d2500723e5594f3e7c70896ffeeef32b9c950ywan ctx_exit_on_error(&stream->decoder, "Failed to get decoder reference frame"); 1472233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1473233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!compare_img(&enc_img, &dec_img)) { 1474233d2500723e5594f3e7c70896ffeeef32b9c950ywan int y[4], u[4], v[4]; 1475233d2500723e5594f3e7c70896ffeeef32b9c950ywan find_mismatch(&enc_img, &dec_img, y, u, v); 1476233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->decoder.err = 1; 1477233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn_or_exit_on_error(&stream->decoder, fatal == TEST_DECODE_FATAL, 1478233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Stream %d: Encode/decode mismatch on frame %d at" 1479233d2500723e5594f3e7c70896ffeeef32b9c950ywan " Y[%d, %d] {%d/%d}," 1480233d2500723e5594f3e7c70896ffeeef32b9c950ywan " U[%d, %d] {%d/%d}," 1481233d2500723e5594f3e7c70896ffeeef32b9c950ywan " V[%d, %d] {%d/%d}", 1482233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->index, stream->frames_out, 1483233d2500723e5594f3e7c70896ffeeef32b9c950ywan y[0], y[1], y[2], y[3], 1484233d2500723e5594f3e7c70896ffeeef32b9c950ywan u[0], u[1], u[2], u[3], 1485233d2500723e5594f3e7c70896ffeeef32b9c950ywan v[0], v[1], v[2], v[3]); 1486233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->mismatch_seen = stream->frames_out; 1487233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1488233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1489233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_img_free(&enc_img); 1490233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_img_free(&dec_img); 1491233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1492233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1493233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1494233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void print_time(const char *label, int64_t etl) { 1495233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64_t hours; 1496233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64_t mins; 1497233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64_t secs; 1498233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1499233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (etl >= 0) { 1500233d2500723e5594f3e7c70896ffeeef32b9c950ywan hours = etl / 3600; 1501233d2500723e5594f3e7c70896ffeeef32b9c950ywan etl -= hours * 3600; 1502233d2500723e5594f3e7c70896ffeeef32b9c950ywan mins = etl / 60; 1503233d2500723e5594f3e7c70896ffeeef32b9c950ywan etl -= mins * 60; 1504233d2500723e5594f3e7c70896ffeeef32b9c950ywan secs = etl; 1505233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1506233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "[%3s %2"PRId64":%02"PRId64": % 02"PRId64"] ", 1507233d2500723e5594f3e7c70896ffeeef32b9c950ywan label, hours, mins, secs); 1508233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 1509233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "[%3s unknown] ", label); 1510233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1511233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1512233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1513233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1514233d2500723e5594f3e7c70896ffeeef32b9c950ywanint main(int argc, const char **argv_) { 1515233d2500723e5594f3e7c70896ffeeef32b9c950ywan int pass; 1516233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_image_t raw; 1517233d2500723e5594f3e7c70896ffeeef32b9c950ywan int frame_avail, got_data; 1518233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1519233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxInputContext input = {0}; 1520233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct VpxEncoderConfig global; 1521233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct stream_state *streams = NULL; 1522233d2500723e5594f3e7c70896ffeeef32b9c950ywan char **argv, **argi; 1523233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64_t cx_time = 0; 1524233d2500723e5594f3e7c70896ffeeef32b9c950ywan int stream_cnt = 0; 1525233d2500723e5594f3e7c70896ffeeef32b9c950ywan int res = 0; 1526233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1527233d2500723e5594f3e7c70896ffeeef32b9c950ywan exec_name = argv_[0]; 1528233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1529233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (argc < 3) 1530233d2500723e5594f3e7c70896ffeeef32b9c950ywan usage_exit(); 1531233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1532233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Setup default input stream settings */ 1533233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.framerate.numerator = 30; 1534233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.framerate.denominator = 1; 1535233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.use_i420 = 1; 1536233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.only_i420 = 1; 1537233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1538233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* First parse the global configuration values, because we want to apply 1539233d2500723e5594f3e7c70896ffeeef32b9c950ywan * other parameters on top of the default configuration provided by the 1540233d2500723e5594f3e7c70896ffeeef32b9c950ywan * codec. 1541233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 1542233d2500723e5594f3e7c70896ffeeef32b9c950ywan argv = argv_dup(argc - 1, argv_ + 1); 1543233d2500723e5594f3e7c70896ffeeef32b9c950ywan parse_global_config(&global, argv); 1544233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1545233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1546233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 1547233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Now parse each stream's parameters. Using a local scope here 1548233d2500723e5594f3e7c70896ffeeef32b9c950ywan * due to the use of 'stream' as loop variable in FOREACH_STREAM 1549233d2500723e5594f3e7c70896ffeeef32b9c950ywan * loops 1550233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 1551233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct stream_state *stream = NULL; 1552233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1553233d2500723e5594f3e7c70896ffeeef32b9c950ywan do { 1554233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream = new_stream(&global, stream); 1555233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream_cnt++; 1556233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!streams) 1557233d2500723e5594f3e7c70896ffeeef32b9c950ywan streams = stream; 1558233d2500723e5594f3e7c70896ffeeef32b9c950ywan } while (parse_stream_params(&global, stream, argv)); 1559233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1560233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1561233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Check for unrecognized options */ 1562233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (argi = argv; *argi; argi++) 1563233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (argi[0][0] == '-' && argi[0][1]) 1564233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Error: Unrecognized option %s\n", *argi); 1565233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1566233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(check_encoder_config(global.disable_warning_prompt, 1567233d2500723e5594f3e7c70896ffeeef32b9c950ywan &global, &stream->config.cfg);); 1568233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1569233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Handle non-option arguments */ 1570233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.filename = argv[0]; 1571233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1572233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!input.filename) 1573233d2500723e5594f3e7c70896ffeeef32b9c950ywan usage_exit(); 1574233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1575233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Decide if other chroma subsamplings than 4:2:0 are supported */ 1576233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.codec->fourcc == VP9_FOURCC) 1577233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.only_i420 = 0; 1578233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1579233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) { 1580233d2500723e5594f3e7c70896ffeeef32b9c950ywan int frames_in = 0, seen_frames = 0; 1581233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64_t estimated_time_left = -1; 1582233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64_t average_rate = -1; 1583233d2500723e5594f3e7c70896ffeeef32b9c950ywan off_t lagged_count = 0; 1584233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1585233d2500723e5594f3e7c70896ffeeef32b9c950ywan open_input_file(&input); 1586233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1587233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* If the input file doesn't specify its w/h (raw files), try to get 1588233d2500723e5594f3e7c70896ffeeef32b9c950ywan * the data from the first stream's configuration. 1589233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 1590233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!input.width || !input.height) 1591233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM( { 1592233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->config.cfg.g_w && stream->config.cfg.g_h) { 1593233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.width = stream->config.cfg.g_w; 1594233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.height = stream->config.cfg.g_h; 1595233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 1596233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1597233d2500723e5594f3e7c70896ffeeef32b9c950ywan }); 1598233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1599233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Update stream configurations from the input file's parameters */ 1600233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!input.width || !input.height) 1601233d2500723e5594f3e7c70896ffeeef32b9c950ywan fatal("Specify stream dimensions with --width (-w) " 1602233d2500723e5594f3e7c70896ffeeef32b9c950ywan " and --height (-h)"); 1603233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(set_stream_dimensions(stream, input.width, input.height)); 1604233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(validate_stream_config(stream, &global)); 1605233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1606233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Ensure that --passes and --pass are consistent. If --pass is set and 1607233d2500723e5594f3e7c70896ffeeef32b9c950ywan * --passes=2, ensure --fpf was set. 1608233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 1609233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.pass && global.passes == 2) 1610233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM( { 1611233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!stream->config.stats_fn) 1612233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Stream %d: Must specify --fpf when --pass=%d" 1613233d2500723e5594f3e7c70896ffeeef32b9c950ywan " and --passes=2\n", stream->index, global.pass); 1614233d2500723e5594f3e7c70896ffeeef32b9c950ywan }); 1615233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1616233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if !CONFIG_WEBM_IO 1617233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM({ 1618233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->config.write_webm = 0; 1619233d2500723e5594f3e7c70896ffeeef32b9c950ywan warn("vpxenc was compiled without WebM container support." 1620233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Producing IVF output"); 1621233d2500723e5594f3e7c70896ffeeef32b9c950ywan }); 1622233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 1623233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1624233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Use the frame rate from the file only if none was specified 1625233d2500723e5594f3e7c70896ffeeef32b9c950ywan * on the command-line. 1626233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 1627233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!global.have_framerate) { 1628233d2500723e5594f3e7c70896ffeeef32b9c950ywan global.framerate.num = input.framerate.numerator; 1629233d2500723e5594f3e7c70896ffeeef32b9c950ywan global.framerate.den = input.framerate.denominator; 1630233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1631233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1632233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(set_default_kf_interval(stream, &global)); 1633233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1634233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Show configuration */ 1635233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.verbose && pass == 0) 1636233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(show_stream_config(stream, &global, &input)); 1637233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1638233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (pass == (global.pass ? global.pass - 1 : 0)) { 1639233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (input.file_type == FILE_TYPE_Y4M) 1640233d2500723e5594f3e7c70896ffeeef32b9c950ywan /*The Y4M reader does its own allocation. 1641233d2500723e5594f3e7c70896ffeeef32b9c950ywan Just initialize this here to avoid problems if we never read any 1642233d2500723e5594f3e7c70896ffeeef32b9c950ywan frames.*/ 1643233d2500723e5594f3e7c70896ffeeef32b9c950ywan memset(&raw, 0, sizeof(raw)); 1644233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 1645233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_img_alloc(&raw, 1646233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.use_i420 ? VPX_IMG_FMT_I420 1647233d2500723e5594f3e7c70896ffeeef32b9c950ywan : VPX_IMG_FMT_YV12, 1648233d2500723e5594f3e7c70896ffeeef32b9c950ywan input.width, input.height, 32); 1649233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1650233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(stream->rate_hist = 1651233d2500723e5594f3e7c70896ffeeef32b9c950ywan init_rate_histogram(&stream->config.cfg, 1652233d2500723e5594f3e7c70896ffeeef32b9c950ywan &global.framerate)); 1653233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1654233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1655233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(setup_pass(stream, &global, pass)); 1656233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(open_output_file(stream, &global)); 1657233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(initialize_encoder(stream, &global)); 1658233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1659233d2500723e5594f3e7c70896ffeeef32b9c950ywan frame_avail = 1; 1660233d2500723e5594f3e7c70896ffeeef32b9c950ywan got_data = 0; 1661233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1662233d2500723e5594f3e7c70896ffeeef32b9c950ywan while (frame_avail || got_data) { 1663233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vpx_usec_timer timer; 1664233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1665233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!global.limit || frames_in < global.limit) { 1666233d2500723e5594f3e7c70896ffeeef32b9c950ywan frame_avail = read_frame(&input, &raw); 1667233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1668233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (frame_avail) 1669233d2500723e5594f3e7c70896ffeeef32b9c950ywan frames_in++; 1670233d2500723e5594f3e7c70896ffeeef32b9c950ywan seen_frames = frames_in > global.skip_frames ? 1671233d2500723e5594f3e7c70896ffeeef32b9c950ywan frames_in - global.skip_frames : 0; 1672233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1673233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!global.quiet) { 1674233d2500723e5594f3e7c70896ffeeef32b9c950ywan float fps = usec_to_fps(cx_time, seen_frames); 1675233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\rPass %d/%d ", pass + 1, global.passes); 1676233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1677233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream_cnt == 1) 1678233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, 1679233d2500723e5594f3e7c70896ffeeef32b9c950ywan "frame %4d/%-4d %7"PRId64"B ", 1680233d2500723e5594f3e7c70896ffeeef32b9c950ywan frames_in, streams->frames_out, (int64_t)streams->nbytes); 1681233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 1682233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "frame %4d ", frames_in); 1683233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1684233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "%7"PRId64" %s %.2f %s ", 1685233d2500723e5594f3e7c70896ffeeef32b9c950ywan cx_time > 9999999 ? cx_time / 1000 : cx_time, 1686233d2500723e5594f3e7c70896ffeeef32b9c950ywan cx_time > 9999999 ? "ms" : "us", 1687233d2500723e5594f3e7c70896ffeeef32b9c950ywan fps >= 1.0 ? fps : fps * 60, 1688233d2500723e5594f3e7c70896ffeeef32b9c950ywan fps >= 1.0 ? "fps" : "fpm"); 1689233d2500723e5594f3e7c70896ffeeef32b9c950ywan print_time("ETA", estimated_time_left); 1690233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\033[K"); 1691233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1692233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1693233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else 1694233d2500723e5594f3e7c70896ffeeef32b9c950ywan frame_avail = 0; 1695233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1696233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (frames_in > global.skip_frames) { 1697233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_usec_timer_start(&timer); 1698233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(encode_frame(stream, &global, 1699233d2500723e5594f3e7c70896ffeeef32b9c950ywan frame_avail ? &raw : NULL, 1700233d2500723e5594f3e7c70896ffeeef32b9c950ywan frames_in)); 1701233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_usec_timer_mark(&timer); 1702233d2500723e5594f3e7c70896ffeeef32b9c950ywan cx_time += vpx_usec_timer_elapsed(&timer); 1703233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1704233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(update_quantizer_histogram(stream)); 1705233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1706233d2500723e5594f3e7c70896ffeeef32b9c950ywan got_data = 0; 1707233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(get_cx_data(stream, &global, &got_data)); 1708233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1709233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!got_data && input.length && !streams->frames_out) { 1710233d2500723e5594f3e7c70896ffeeef32b9c950ywan lagged_count = global.limit ? seen_frames : ftello(input.file); 1711233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (input.length) { 1712233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64_t remaining; 1713233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64_t rate; 1714233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1715233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.limit) { 1716233d2500723e5594f3e7c70896ffeeef32b9c950ywan off_t frame_in_lagged = (seen_frames - lagged_count) * 1000; 1717233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1718233d2500723e5594f3e7c70896ffeeef32b9c950ywan rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0; 1719233d2500723e5594f3e7c70896ffeeef32b9c950ywan remaining = 1000 * (global.limit - global.skip_frames 1720233d2500723e5594f3e7c70896ffeeef32b9c950ywan - seen_frames + lagged_count); 1721233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 1722233d2500723e5594f3e7c70896ffeeef32b9c950ywan off_t input_pos = ftello(input.file); 1723233d2500723e5594f3e7c70896ffeeef32b9c950ywan off_t input_pos_lagged = input_pos - lagged_count; 1724233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64_t limit = input.length; 1725233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1726233d2500723e5594f3e7c70896ffeeef32b9c950ywan rate = cx_time ? input_pos_lagged * (int64_t)1000000 / cx_time : 0; 1727233d2500723e5594f3e7c70896ffeeef32b9c950ywan remaining = limit - input_pos + lagged_count; 1728233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1729233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1730233d2500723e5594f3e7c70896ffeeef32b9c950ywan average_rate = (average_rate <= 0) 1731233d2500723e5594f3e7c70896ffeeef32b9c950ywan ? rate 1732233d2500723e5594f3e7c70896ffeeef32b9c950ywan : (average_rate * 7 + rate) / 8; 1733233d2500723e5594f3e7c70896ffeeef32b9c950ywan estimated_time_left = average_rate ? remaining / average_rate : -1; 1734233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1735233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1736233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (got_data && global.test_decode != TEST_DECODE_OFF) 1737233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(test_decode(stream, global.test_decode, global.codec)); 1738233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1739233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1740233d2500723e5594f3e7c70896ffeeef32b9c950ywan fflush(stdout); 1741233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1742233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1743233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream_cnt > 1) 1744233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(stderr, "\n"); 1745233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1746233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!global.quiet) 1747233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(fprintf( 1748233d2500723e5594f3e7c70896ffeeef32b9c950ywan stderr, 1749233d2500723e5594f3e7c70896ffeeef32b9c950ywan "\rPass %d/%d frame %4d/%-4d %7"PRId64"B %7lub/f %7"PRId64"b/s" 1750233d2500723e5594f3e7c70896ffeeef32b9c950ywan " %7"PRId64" %s (%.2f fps)\033[K\n", pass + 1, 1751233d2500723e5594f3e7c70896ffeeef32b9c950ywan global.passes, frames_in, stream->frames_out, (int64_t)stream->nbytes, 1752233d2500723e5594f3e7c70896ffeeef32b9c950ywan seen_frames ? (unsigned long)(stream->nbytes * 8 / seen_frames) : 0, 1753233d2500723e5594f3e7c70896ffeeef32b9c950ywan seen_frames ? (int64_t)stream->nbytes * 8 1754233d2500723e5594f3e7c70896ffeeef32b9c950ywan * (int64_t)global.framerate.num / global.framerate.den 1755233d2500723e5594f3e7c70896ffeeef32b9c950ywan / seen_frames 1756233d2500723e5594f3e7c70896ffeeef32b9c950ywan : 0, 1757233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->cx_time > 9999999 ? stream->cx_time / 1000 : stream->cx_time, 1758233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->cx_time > 9999999 ? "ms" : "us", 1759233d2500723e5594f3e7c70896ffeeef32b9c950ywan usec_to_fps(stream->cx_time, seen_frames)); 1760233d2500723e5594f3e7c70896ffeeef32b9c950ywan ); 1761233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1762233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.show_psnr) 1763233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(show_psnr(stream)); 1764233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1765233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(vpx_codec_destroy(&stream->encoder)); 1766233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1767233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.test_decode != TEST_DECODE_OFF) { 1768233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(vpx_codec_destroy(&stream->decoder)); 1769233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1770233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1771233d2500723e5594f3e7c70896ffeeef32b9c950ywan close_input_file(&input); 1772233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1773233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.test_decode == TEST_DECODE_FATAL) { 1774233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(res |= stream->mismatch_seen); 1775233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1776233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(close_output_file(stream, global.codec->fourcc)); 1777233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1778233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(stats_close(&stream->stats, global.passes - 1)); 1779233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1780233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.pass) 1781233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 1782233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1783233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1784233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.show_q_hist_buckets) 1785233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(show_q_histogram(stream->counts, 1786233d2500723e5594f3e7c70896ffeeef32b9c950ywan global.show_q_hist_buckets)); 1787233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1788233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (global.show_rate_hist_buckets) 1789233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(show_rate_histogram(stream->rate_hist, 1790233d2500723e5594f3e7c70896ffeeef32b9c950ywan &stream->config.cfg, 1791233d2500723e5594f3e7c70896ffeeef32b9c950ywan global.show_rate_hist_buckets)); 1792233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM(destroy_rate_histogram(stream->rate_hist)); 1793233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1794233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_INTERNAL_STATS 1795233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* TODO(jkoleszar): This doesn't belong in this executable. Do it for now, 1796233d2500723e5594f3e7c70896ffeeef32b9c950ywan * to match some existing utilities. 1797233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 1798233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!(global.pass == 1 && global.passes == 2)) 1799233d2500723e5594f3e7c70896ffeeef32b9c950ywan FOREACH_STREAM({ 1800233d2500723e5594f3e7c70896ffeeef32b9c950ywan FILE *f = fopen("opsnr.stt", "a"); 1801233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stream->mismatch_seen) { 1802233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(f, "First mismatch occurred in frame %d\n", 1803233d2500723e5594f3e7c70896ffeeef32b9c950ywan stream->mismatch_seen); 1804233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 1805233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(f, "No mismatch detected in recon buffers\n"); 1806233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1807233d2500723e5594f3e7c70896ffeeef32b9c950ywan fclose(f); 1808233d2500723e5594f3e7c70896ffeeef32b9c950ywan }); 1809233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 1810233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1811233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_img_free(&raw); 1812233d2500723e5594f3e7c70896ffeeef32b9c950ywan free(argv); 1813233d2500723e5594f3e7c70896ffeeef32b9c950ywan free(streams); 1814233d2500723e5594f3e7c70896ffeeef32b9c950ywan return res ? EXIT_FAILURE : EXIT_SUCCESS; 1815233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 1816