| Index: source/libvpx/vpxenc.c
|
| ===================================================================
|
| --- source/libvpx/vpxenc.c (revision 240950)
|
| +++ source/libvpx/vpxenc.c (working copy)
|
| @@ -8,32 +8,27 @@
|
| * be found in the AUTHORS file in the root of the source tree.
|
| */
|
|
|
| -#include "vpx_config.h"
|
| +#include "./vpxenc.h"
|
| +#include "./vpx_config.h"
|
|
|
| -#if defined(_WIN32) || defined(__OS2__) || !CONFIG_OS_SUPPORT
|
| -#define USE_POSIX_MMAP 0
|
| -#else
|
| -#define USE_POSIX_MMAP 1
|
| -#endif
|
| -
|
| +#include <assert.h>
|
| +#include <limits.h>
|
| +#include <math.h>
|
| +#include <stdarg.h>
|
| #include <stdio.h>
|
| #include <stdlib.h>
|
| -#include <stdarg.h>
|
| #include <string.h>
|
| -#include <limits.h>
|
| -#include <assert.h>
|
| +
|
| #include "vpx/vpx_encoder.h"
|
| #if CONFIG_DECODERS
|
| #include "vpx/vpx_decoder.h"
|
| #endif
|
| -#if USE_POSIX_MMAP
|
| -#include <sys/types.h>
|
| -#include <sys/stat.h>
|
| -#include <sys/mman.h>
|
| -#include <fcntl.h>
|
| -#include <unistd.h>
|
| -#endif
|
|
|
| +#include "third_party/libyuv/include/libyuv/scale.h"
|
| +#include "./args.h"
|
| +#include "./ivfdec.h"
|
| +#include "./ivfenc.h"
|
| +
|
| #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
|
| #include "vpx/vp8cx.h"
|
| #endif
|
| @@ -41,38 +36,14 @@
|
| #include "vpx/vp8dx.h"
|
| #endif
|
|
|
| +#include "./tools_common.h"
|
| #include "vpx_ports/mem_ops.h"
|
| #include "vpx_ports/vpx_timer.h"
|
| -#include "tools_common.h"
|
| -#include "y4minput.h"
|
| -#include "third_party/libmkv/EbmlWriter.h"
|
| -#include "third_party/libmkv/EbmlIDs.h"
|
| -#include "third_party/libyuv/include/libyuv/scale.h"
|
| +#include "./vpxstats.h"
|
| +#include "./warnings.h"
|
| +#include "./webmenc.h"
|
| +#include "./y4minput.h"
|
|
|
| -/* Need special handling of these functions on Windows */
|
| -#if defined(_MSC_VER)
|
| -/* MSVS doesn't define off_t, and uses _f{seek,tell}i64 */
|
| -typedef __int64 off_t;
|
| -#define fseeko _fseeki64
|
| -#define ftello _ftelli64
|
| -#elif defined(_WIN32)
|
| -/* MinGW defines off_t as long
|
| - and uses f{seek,tell}o64/off64_t for large files */
|
| -#define fseeko fseeko64
|
| -#define ftello ftello64
|
| -#define off_t off64_t
|
| -#endif
|
| -
|
| -#define LITERALU64(hi,lo) ((((uint64_t)hi)<<32)|lo)
|
| -
|
| -/* We should use 32-bit file operations in WebM file format
|
| - * when building ARM executable file (.axf) with RVCT */
|
| -#if !CONFIG_OS_SUPPORT
|
| -typedef long off_t;
|
| -#define fseeko fseek
|
| -#define ftello ftell
|
| -#endif
|
| -
|
| /* Swallow warnings about unused results of fread/fwrite */
|
| static size_t wrap_fread(void *ptr, size_t size, size_t nmemb,
|
| FILE *stream) {
|
| @@ -89,8 +60,6 @@
|
|
|
| static const char *exec_name;
|
|
|
| -#define VP8_FOURCC (0x30385056)
|
| -#define VP9_FOURCC (0x30395056)
|
| static const struct codec_item {
|
| char const *name;
|
| const vpx_codec_iface_t *(*iface)(void);
|
| @@ -109,37 +78,6 @@
|
| #endif
|
| };
|
|
|
| -static void usage_exit();
|
| -
|
| -#define LOG_ERROR(label) do \
|
| - {\
|
| - const char *l=label;\
|
| - va_list ap;\
|
| - va_start(ap, fmt);\
|
| - if(l)\
|
| - fprintf(stderr, "%s: ", l);\
|
| - vfprintf(stderr, fmt, ap);\
|
| - fprintf(stderr, "\n");\
|
| - va_end(ap);\
|
| - } while(0)
|
| -
|
| -void die(const char *fmt, ...) {
|
| - LOG_ERROR(NULL);
|
| - usage_exit();
|
| -}
|
| -
|
| -
|
| -void fatal(const char *fmt, ...) {
|
| - LOG_ERROR("Fatal");
|
| - exit(EXIT_FAILURE);
|
| -}
|
| -
|
| -
|
| -void warn(const char *fmt, ...) {
|
| - LOG_ERROR("Warning");
|
| -}
|
| -
|
| -
|
| static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
|
| const char *s, va_list ap) {
|
| if (ctx->err) {
|
| @@ -173,700 +111,29 @@
|
| va_end(ap);
|
| }
|
|
|
| -/* This structure is used to abstract the different ways of handling
|
| - * first pass statistics.
|
| - */
|
| -typedef struct {
|
| - vpx_fixed_buf_t buf;
|
| - int pass;
|
| - FILE *file;
|
| - char *buf_ptr;
|
| - size_t buf_alloc_sz;
|
| -} stats_io_t;
|
| -
|
| -int stats_open_file(stats_io_t *stats, const char *fpf, int pass) {
|
| - int res;
|
| -
|
| - stats->pass = pass;
|
| -
|
| - if (pass == 0) {
|
| - stats->file = fopen(fpf, "wb");
|
| - stats->buf.sz = 0;
|
| - stats->buf.buf = NULL,
|
| - res = (stats->file != NULL);
|
| - } else {
|
| -#if 0
|
| -#elif USE_POSIX_MMAP
|
| - struct stat stat_buf;
|
| - int fd;
|
| -
|
| - fd = open(fpf, O_RDONLY);
|
| - stats->file = fdopen(fd, "rb");
|
| - fstat(fd, &stat_buf);
|
| - stats->buf.sz = stat_buf.st_size;
|
| - stats->buf.buf = mmap(NULL, stats->buf.sz, PROT_READ, MAP_PRIVATE,
|
| - fd, 0);
|
| - res = (stats->buf.buf != NULL);
|
| -#else
|
| - size_t nbytes;
|
| -
|
| - stats->file = fopen(fpf, "rb");
|
| -
|
| - if (fseek(stats->file, 0, SEEK_END))
|
| - fatal("First-pass stats file must be seekable!");
|
| -
|
| - stats->buf.sz = stats->buf_alloc_sz = ftell(stats->file);
|
| - rewind(stats->file);
|
| -
|
| - stats->buf.buf = malloc(stats->buf_alloc_sz);
|
| -
|
| - if (!stats->buf.buf)
|
| - fatal("Failed to allocate first-pass stats buffer (%lu bytes)",
|
| - (unsigned long)stats->buf_alloc_sz);
|
| -
|
| - nbytes = fread(stats->buf.buf, 1, stats->buf.sz, stats->file);
|
| - res = (nbytes == stats->buf.sz);
|
| -#endif
|
| - }
|
| -
|
| - return res;
|
| -}
|
| -
|
| -int stats_open_mem(stats_io_t *stats, int pass) {
|
| - int res;
|
| - stats->pass = pass;
|
| -
|
| - if (!pass) {
|
| - stats->buf.sz = 0;
|
| - stats->buf_alloc_sz = 64 * 1024;
|
| - stats->buf.buf = malloc(stats->buf_alloc_sz);
|
| - }
|
| -
|
| - stats->buf_ptr = stats->buf.buf;
|
| - res = (stats->buf.buf != NULL);
|
| - return res;
|
| -}
|
| -
|
| -
|
| -void stats_close(stats_io_t *stats, int last_pass) {
|
| - if (stats->file) {
|
| - if (stats->pass == last_pass) {
|
| -#if 0
|
| -#elif USE_POSIX_MMAP
|
| - munmap(stats->buf.buf, stats->buf.sz);
|
| -#else
|
| - free(stats->buf.buf);
|
| -#endif
|
| - }
|
| -
|
| - fclose(stats->file);
|
| - stats->file = NULL;
|
| - } else {
|
| - if (stats->pass == last_pass)
|
| - free(stats->buf.buf);
|
| - }
|
| -}
|
| -
|
| -void stats_write(stats_io_t *stats, const void *pkt, size_t len) {
|
| - if (stats->file) {
|
| - (void) fwrite(pkt, 1, len, stats->file);
|
| - } else {
|
| - if (stats->buf.sz + len > stats->buf_alloc_sz) {
|
| - size_t new_sz = stats->buf_alloc_sz + 64 * 1024;
|
| - char *new_ptr = realloc(stats->buf.buf, new_sz);
|
| -
|
| - if (new_ptr) {
|
| - stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)stats->buf.buf);
|
| - stats->buf.buf = new_ptr;
|
| - stats->buf_alloc_sz = new_sz;
|
| - } else
|
| - fatal("Failed to realloc firstpass stats buffer.");
|
| - }
|
| -
|
| - memcpy(stats->buf_ptr, pkt, len);
|
| - stats->buf.sz += len;
|
| - stats->buf_ptr += len;
|
| - }
|
| -}
|
| -
|
| -vpx_fixed_buf_t stats_get(stats_io_t *stats) {
|
| - return stats->buf;
|
| -}
|
| -
|
| -/* Stereo 3D packed frame format */
|
| -typedef enum stereo_format {
|
| - STEREO_FORMAT_MONO = 0,
|
| - STEREO_FORMAT_LEFT_RIGHT = 1,
|
| - STEREO_FORMAT_BOTTOM_TOP = 2,
|
| - STEREO_FORMAT_TOP_BOTTOM = 3,
|
| - STEREO_FORMAT_RIGHT_LEFT = 11
|
| -} stereo_format_t;
|
| -
|
| -enum video_file_type {
|
| - FILE_TYPE_RAW,
|
| - FILE_TYPE_IVF,
|
| - FILE_TYPE_Y4M
|
| -};
|
| -
|
| -struct detect_buffer {
|
| - char buf[4];
|
| - size_t buf_read;
|
| - size_t position;
|
| -};
|
| -
|
| -
|
| -struct input_state {
|
| - char *fn;
|
| - FILE *file;
|
| - off_t length;
|
| - y4m_input y4m;
|
| - struct detect_buffer detect;
|
| - enum video_file_type file_type;
|
| - unsigned int w;
|
| - unsigned int h;
|
| - struct vpx_rational framerate;
|
| - int use_i420;
|
| - int only_i420;
|
| -};
|
| -
|
| -
|
| -#define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
|
| -static int read_frame(struct input_state *input, vpx_image_t *img) {
|
| - FILE *f = input->file;
|
| - enum video_file_type file_type = input->file_type;
|
| - y4m_input *y4m = &input->y4m;
|
| - struct detect_buffer *detect = &input->detect;
|
| - int plane = 0;
|
| +int read_frame(struct VpxInputContext *input_ctx, vpx_image_t *img) {
|
| + FILE *f = input_ctx->file;
|
| + y4m_input *y4m = &input_ctx->y4m;
|
| int shortread = 0;
|
|
|
| - if (file_type == FILE_TYPE_Y4M) {
|
| + if (input_ctx->file_type == FILE_TYPE_Y4M) {
|
| if (y4m_input_fetch_frame(y4m, f, img) < 1)
|
| return 0;
|
| } else {
|
| - if (file_type == FILE_TYPE_IVF) {
|
| - char junk[IVF_FRAME_HDR_SZ];
|
| -
|
| - /* Skip the frame header. We know how big the frame should be. See
|
| - * write_ivf_frame_header() for documentation on the frame header
|
| - * layout.
|
| - */
|
| - (void) fread(junk, 1, IVF_FRAME_HDR_SZ, f);
|
| - }
|
| -
|
| - for (plane = 0; plane < 3; plane++) {
|
| - unsigned char *ptr;
|
| - int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
|
| - int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
|
| - int r;
|
| -
|
| - /* Determine the correct plane based on the image format. The for-loop
|
| - * always counts in Y,U,V order, but this may not match the order of
|
| - * the data on disk.
|
| - */
|
| - switch (plane) {
|
| - case 1:
|
| - ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_V : VPX_PLANE_U];
|
| - break;
|
| - case 2:
|
| - ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_U : VPX_PLANE_V];
|
| - break;
|
| - default:
|
| - ptr = img->planes[plane];
|
| - }
|
| -
|
| - for (r = 0; r < h; r++) {
|
| - size_t needed = w;
|
| - size_t buf_position = 0;
|
| - const size_t left = detect->buf_read - detect->position;
|
| - if (left > 0) {
|
| - const size_t more = (left < needed) ? left : needed;
|
| - memcpy(ptr, detect->buf + detect->position, more);
|
| - buf_position = more;
|
| - needed -= more;
|
| - detect->position += more;
|
| - }
|
| - if (needed > 0) {
|
| - shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
|
| - }
|
| -
|
| - ptr += img->stride[plane];
|
| - }
|
| - }
|
| + shortread = read_yuv_frame(input_ctx, img);
|
| }
|
|
|
| return !shortread;
|
| }
|
|
|
| -
|
| -unsigned int file_is_y4m(FILE *infile,
|
| - y4m_input *y4m,
|
| - char detect[4]) {
|
| +int file_is_y4m(FILE *infile, y4m_input *y4m, const char detect[4]) {
|
| if (memcmp(detect, "YUV4", 4) == 0) {
|
| return 1;
|
| }
|
| return 0;
|
| }
|
|
|
| -#define IVF_FILE_HDR_SZ (32)
|
| -unsigned int file_is_ivf(struct input_state *input,
|
| - unsigned int *fourcc) {
|
| - char raw_hdr[IVF_FILE_HDR_SZ];
|
| - int is_ivf = 0;
|
| - FILE *infile = input->file;
|
| - unsigned int *width = &input->w;
|
| - unsigned int *height = &input->h;
|
| - struct detect_buffer *detect = &input->detect;
|
|
|
| - if (memcmp(detect->buf, "DKIF", 4) != 0)
|
| - return 0;
|
| -
|
| - /* See write_ivf_file_header() for more documentation on the file header
|
| - * layout.
|
| - */
|
| - if (fread(raw_hdr + 4, 1, IVF_FILE_HDR_SZ - 4, infile)
|
| - == IVF_FILE_HDR_SZ - 4) {
|
| - {
|
| - is_ivf = 1;
|
| -
|
| - if (mem_get_le16(raw_hdr + 4) != 0)
|
| - warn("Unrecognized IVF version! This file may not decode "
|
| - "properly.");
|
| -
|
| - *fourcc = mem_get_le32(raw_hdr + 8);
|
| - }
|
| - }
|
| -
|
| - if (is_ivf) {
|
| - *width = mem_get_le16(raw_hdr + 12);
|
| - *height = mem_get_le16(raw_hdr + 14);
|
| - detect->position = 4;
|
| - }
|
| -
|
| - return is_ivf;
|
| -}
|
| -
|
| -
|
| -static void write_ivf_file_header(FILE *outfile,
|
| - const vpx_codec_enc_cfg_t *cfg,
|
| - unsigned int fourcc,
|
| - int frame_cnt) {
|
| - char header[32];
|
| -
|
| - if (cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
|
| - return;
|
| -
|
| - header[0] = 'D';
|
| - header[1] = 'K';
|
| - header[2] = 'I';
|
| - header[3] = 'F';
|
| - mem_put_le16(header + 4, 0); /* version */
|
| - mem_put_le16(header + 6, 32); /* headersize */
|
| - mem_put_le32(header + 8, fourcc); /* headersize */
|
| - mem_put_le16(header + 12, cfg->g_w); /* width */
|
| - mem_put_le16(header + 14, cfg->g_h); /* height */
|
| - mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
|
| - mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
|
| - mem_put_le32(header + 24, frame_cnt); /* length */
|
| - mem_put_le32(header + 28, 0); /* unused */
|
| -
|
| - (void) fwrite(header, 1, 32, outfile);
|
| -}
|
| -
|
| -
|
| -static void write_ivf_frame_header(FILE *outfile,
|
| - const vpx_codec_cx_pkt_t *pkt) {
|
| - char header[12];
|
| - vpx_codec_pts_t pts;
|
| -
|
| - if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
|
| - return;
|
| -
|
| - pts = pkt->data.frame.pts;
|
| - mem_put_le32(header, (int)pkt->data.frame.sz);
|
| - mem_put_le32(header + 4, pts & 0xFFFFFFFF);
|
| - mem_put_le32(header + 8, pts >> 32);
|
| -
|
| - (void) fwrite(header, 1, 12, outfile);
|
| -}
|
| -
|
| -static void write_ivf_frame_size(FILE *outfile, size_t size) {
|
| - char header[4];
|
| - mem_put_le32(header, (int)size);
|
| - (void) fwrite(header, 1, 4, outfile);
|
| -}
|
| -
|
| -
|
| -typedef off_t EbmlLoc;
|
| -
|
| -
|
| -struct cue_entry {
|
| - unsigned int time;
|
| - uint64_t loc;
|
| -};
|
| -
|
| -
|
| -struct EbmlGlobal {
|
| - int debug;
|
| -
|
| - FILE *stream;
|
| - int64_t last_pts_ms;
|
| - vpx_rational_t framerate;
|
| -
|
| - /* These pointers are to the start of an element */
|
| - off_t position_reference;
|
| - off_t seek_info_pos;
|
| - off_t segment_info_pos;
|
| - off_t track_pos;
|
| - off_t cue_pos;
|
| - off_t cluster_pos;
|
| -
|
| - /* This pointer is to a specific element to be serialized */
|
| - off_t track_id_pos;
|
| -
|
| - /* These pointers are to the size field of the element */
|
| - EbmlLoc startSegment;
|
| - EbmlLoc startCluster;
|
| -
|
| - uint32_t cluster_timecode;
|
| - int cluster_open;
|
| -
|
| - struct cue_entry *cue_list;
|
| - unsigned int cues;
|
| -
|
| -};
|
| -
|
| -
|
| -void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len) {
|
| - (void) fwrite(buffer_in, 1, len, glob->stream);
|
| -}
|
| -
|
| -#define WRITE_BUFFER(s) \
|
| - for(i = len-1; i>=0; i--)\
|
| - { \
|
| - x = (char)(*(const s *)buffer_in >> (i * CHAR_BIT)); \
|
| - Ebml_Write(glob, &x, 1); \
|
| - }
|
| -void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, int buffer_size, unsigned long len) {
|
| - char x;
|
| - int i;
|
| -
|
| - /* buffer_size:
|
| - * 1 - int8_t;
|
| - * 2 - int16_t;
|
| - * 3 - int32_t;
|
| - * 4 - int64_t;
|
| - */
|
| - switch (buffer_size) {
|
| - case 1:
|
| - WRITE_BUFFER(int8_t)
|
| - break;
|
| - case 2:
|
| - WRITE_BUFFER(int16_t)
|
| - break;
|
| - case 4:
|
| - WRITE_BUFFER(int32_t)
|
| - break;
|
| - case 8:
|
| - WRITE_BUFFER(int64_t)
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| -}
|
| -#undef WRITE_BUFFER
|
| -
|
| -/* Need a fixed size serializer for the track ID. libmkv provides a 64 bit
|
| - * one, but not a 32 bit one.
|
| - */
|
| -static void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) {
|
| - unsigned char sizeSerialized = 4 | 0x80;
|
| - Ebml_WriteID(glob, class_id);
|
| - Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
|
| - Ebml_Serialize(glob, &ui, sizeof(ui), 4);
|
| -}
|
| -
|
| -
|
| -static void
|
| -Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc,
|
| - unsigned long class_id) {
|
| - /* todo this is always taking 8 bytes, this may need later optimization */
|
| - /* this is a key that says length unknown */
|
| - uint64_t unknownLen = LITERALU64(0x01FFFFFF, 0xFFFFFFFF);
|
| -
|
| - Ebml_WriteID(glob, class_id);
|
| - *ebmlLoc = ftello(glob->stream);
|
| - Ebml_Serialize(glob, &unknownLen, sizeof(unknownLen), 8);
|
| -}
|
| -
|
| -static void
|
| -Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc) {
|
| - off_t pos;
|
| - uint64_t size;
|
| -
|
| - /* Save the current stream pointer */
|
| - pos = ftello(glob->stream);
|
| -
|
| - /* Calculate the size of this element */
|
| - size = pos - *ebmlLoc - 8;
|
| - size |= LITERALU64(0x01000000, 0x00000000);
|
| -
|
| - /* Seek back to the beginning of the element and write the new size */
|
| - fseeko(glob->stream, *ebmlLoc, SEEK_SET);
|
| - Ebml_Serialize(glob, &size, sizeof(size), 8);
|
| -
|
| - /* Reset the stream pointer */
|
| - fseeko(glob->stream, pos, SEEK_SET);
|
| -}
|
| -
|
| -
|
| -static void
|
| -write_webm_seek_element(EbmlGlobal *ebml, unsigned long id, off_t pos) {
|
| - uint64_t offset = pos - ebml->position_reference;
|
| - EbmlLoc start;
|
| - Ebml_StartSubElement(ebml, &start, Seek);
|
| - Ebml_SerializeBinary(ebml, SeekID, id);
|
| - Ebml_SerializeUnsigned64(ebml, SeekPosition, offset);
|
| - Ebml_EndSubElement(ebml, &start);
|
| -}
|
| -
|
| -
|
| -static void
|
| -write_webm_seek_info(EbmlGlobal *ebml) {
|
| -
|
| - off_t pos;
|
| -
|
| - /* Save the current stream pointer */
|
| - pos = ftello(ebml->stream);
|
| -
|
| - if (ebml->seek_info_pos)
|
| - fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET);
|
| - else
|
| - ebml->seek_info_pos = pos;
|
| -
|
| - {
|
| - EbmlLoc start;
|
| -
|
| - Ebml_StartSubElement(ebml, &start, SeekHead);
|
| - write_webm_seek_element(ebml, Tracks, ebml->track_pos);
|
| - write_webm_seek_element(ebml, Cues, ebml->cue_pos);
|
| - write_webm_seek_element(ebml, Info, ebml->segment_info_pos);
|
| - Ebml_EndSubElement(ebml, &start);
|
| - }
|
| - {
|
| - /* segment info */
|
| - EbmlLoc startInfo;
|
| - uint64_t frame_time;
|
| - char version_string[64];
|
| -
|
| - /* Assemble version string */
|
| - if (ebml->debug)
|
| - strcpy(version_string, "vpxenc");
|
| - else {
|
| - strcpy(version_string, "vpxenc ");
|
| - strncat(version_string,
|
| - vpx_codec_version_str(),
|
| - sizeof(version_string) - 1 - strlen(version_string));
|
| - }
|
| -
|
| - frame_time = (uint64_t)1000 * ebml->framerate.den
|
| - / ebml->framerate.num;
|
| - ebml->segment_info_pos = ftello(ebml->stream);
|
| - Ebml_StartSubElement(ebml, &startInfo, Info);
|
| - Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
|
| - Ebml_SerializeFloat(ebml, Segment_Duration,
|
| - (double)(ebml->last_pts_ms + frame_time));
|
| - Ebml_SerializeString(ebml, 0x4D80, version_string);
|
| - Ebml_SerializeString(ebml, 0x5741, version_string);
|
| - Ebml_EndSubElement(ebml, &startInfo);
|
| - }
|
| -}
|
| -
|
| -
|
| -static void
|
| -write_webm_file_header(EbmlGlobal *glob,
|
| - const vpx_codec_enc_cfg_t *cfg,
|
| - const struct vpx_rational *fps,
|
| - stereo_format_t stereo_fmt,
|
| - unsigned int fourcc) {
|
| - {
|
| - EbmlLoc start;
|
| - Ebml_StartSubElement(glob, &start, EBML);
|
| - Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
|
| - Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1);
|
| - Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4);
|
| - Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8);
|
| - Ebml_SerializeString(glob, DocType, "webm");
|
| - Ebml_SerializeUnsigned(glob, DocTypeVersion, 2);
|
| - Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2);
|
| - Ebml_EndSubElement(glob, &start);
|
| - }
|
| - {
|
| - Ebml_StartSubElement(glob, &glob->startSegment, Segment);
|
| - glob->position_reference = ftello(glob->stream);
|
| - glob->framerate = *fps;
|
| - write_webm_seek_info(glob);
|
| -
|
| - {
|
| - EbmlLoc trackStart;
|
| - glob->track_pos = ftello(glob->stream);
|
| - Ebml_StartSubElement(glob, &trackStart, Tracks);
|
| - {
|
| - unsigned int trackNumber = 1;
|
| - uint64_t trackID = 0;
|
| -
|
| - EbmlLoc start;
|
| - Ebml_StartSubElement(glob, &start, TrackEntry);
|
| - Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
|
| - glob->track_id_pos = ftello(glob->stream);
|
| - Ebml_SerializeUnsigned32(glob, TrackUID, trackID);
|
| - Ebml_SerializeUnsigned(glob, TrackType, 1);
|
| - Ebml_SerializeString(glob, CodecID,
|
| - fourcc == VP8_FOURCC ? "V_VP8" : "V_VP9");
|
| - {
|
| - unsigned int pixelWidth = cfg->g_w;
|
| - unsigned int pixelHeight = cfg->g_h;
|
| -
|
| - EbmlLoc videoStart;
|
| - Ebml_StartSubElement(glob, &videoStart, Video);
|
| - Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
|
| - Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
|
| - Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt);
|
| - Ebml_EndSubElement(glob, &videoStart);
|
| - }
|
| - Ebml_EndSubElement(glob, &start); /* Track Entry */
|
| - }
|
| - Ebml_EndSubElement(glob, &trackStart);
|
| - }
|
| - /* segment element is open */
|
| - }
|
| -}
|
| -
|
| -
|
| -static void
|
| -write_webm_block(EbmlGlobal *glob,
|
| - const vpx_codec_enc_cfg_t *cfg,
|
| - const vpx_codec_cx_pkt_t *pkt) {
|
| - unsigned long block_length;
|
| - unsigned char track_number;
|
| - unsigned short block_timecode = 0;
|
| - unsigned char flags;
|
| - int64_t pts_ms;
|
| - int start_cluster = 0, is_keyframe;
|
| -
|
| - /* Calculate the PTS of this frame in milliseconds */
|
| - pts_ms = pkt->data.frame.pts * 1000
|
| - * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
|
| - if (pts_ms <= glob->last_pts_ms)
|
| - pts_ms = glob->last_pts_ms + 1;
|
| - glob->last_pts_ms = pts_ms;
|
| -
|
| - /* Calculate the relative time of this block */
|
| - if (pts_ms - glob->cluster_timecode > SHRT_MAX)
|
| - start_cluster = 1;
|
| - else
|
| - block_timecode = (unsigned short)pts_ms - glob->cluster_timecode;
|
| -
|
| - is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
|
| - if (start_cluster || is_keyframe) {
|
| - if (glob->cluster_open)
|
| - Ebml_EndSubElement(glob, &glob->startCluster);
|
| -
|
| - /* Open the new cluster */
|
| - block_timecode = 0;
|
| - glob->cluster_open = 1;
|
| - glob->cluster_timecode = (uint32_t)pts_ms;
|
| - glob->cluster_pos = ftello(glob->stream);
|
| - Ebml_StartSubElement(glob, &glob->startCluster, Cluster); /* cluster */
|
| - Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode);
|
| -
|
| - /* Save a cue point if this is a keyframe. */
|
| - if (is_keyframe) {
|
| - struct cue_entry *cue, *new_cue_list;
|
| -
|
| - new_cue_list = realloc(glob->cue_list,
|
| - (glob->cues + 1) * sizeof(struct cue_entry));
|
| - if (new_cue_list)
|
| - glob->cue_list = new_cue_list;
|
| - else
|
| - fatal("Failed to realloc cue list.");
|
| -
|
| - cue = &glob->cue_list[glob->cues];
|
| - cue->time = glob->cluster_timecode;
|
| - cue->loc = glob->cluster_pos;
|
| - glob->cues++;
|
| - }
|
| - }
|
| -
|
| - /* Write the Simple Block */
|
| - Ebml_WriteID(glob, SimpleBlock);
|
| -
|
| - block_length = (unsigned long)pkt->data.frame.sz + 4;
|
| - block_length |= 0x10000000;
|
| - Ebml_Serialize(glob, &block_length, sizeof(block_length), 4);
|
| -
|
| - track_number = 1;
|
| - track_number |= 0x80;
|
| - Ebml_Write(glob, &track_number, 1);
|
| -
|
| - Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2);
|
| -
|
| - flags = 0;
|
| - if (is_keyframe)
|
| - flags |= 0x80;
|
| - if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE)
|
| - flags |= 0x08;
|
| - Ebml_Write(glob, &flags, 1);
|
| -
|
| - Ebml_Write(glob, pkt->data.frame.buf, (unsigned long)pkt->data.frame.sz);
|
| -}
|
| -
|
| -
|
| -static void
|
| -write_webm_file_footer(EbmlGlobal *glob, long hash) {
|
| -
|
| - if (glob->cluster_open)
|
| - Ebml_EndSubElement(glob, &glob->startCluster);
|
| -
|
| - {
|
| - EbmlLoc start;
|
| - unsigned int i;
|
| -
|
| - glob->cue_pos = ftello(glob->stream);
|
| - Ebml_StartSubElement(glob, &start, Cues);
|
| - for (i = 0; i < glob->cues; i++) {
|
| - struct cue_entry *cue = &glob->cue_list[i];
|
| - EbmlLoc start;
|
| -
|
| - Ebml_StartSubElement(glob, &start, CuePoint);
|
| - {
|
| - EbmlLoc start;
|
| -
|
| - Ebml_SerializeUnsigned(glob, CueTime, cue->time);
|
| -
|
| - Ebml_StartSubElement(glob, &start, CueTrackPositions);
|
| - Ebml_SerializeUnsigned(glob, CueTrack, 1);
|
| - Ebml_SerializeUnsigned64(glob, CueClusterPosition,
|
| - cue->loc - glob->position_reference);
|
| - Ebml_EndSubElement(glob, &start);
|
| - }
|
| - Ebml_EndSubElement(glob, &start);
|
| - }
|
| - Ebml_EndSubElement(glob, &start);
|
| - }
|
| -
|
| - Ebml_EndSubElement(glob, &glob->startSegment);
|
| -
|
| - /* Patch up the seek info block */
|
| - write_webm_seek_info(glob);
|
| -
|
| - /* Patch up the track id */
|
| - fseeko(glob->stream, glob->track_id_pos, SEEK_SET);
|
| - Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash);
|
| -
|
| - fseeko(glob->stream, 0, SEEK_END);
|
| -}
|
| -
|
| -
|
| /* Murmur hash derived from public domain reference implementation at
|
| * http:// sites.google.com/site/murmurhash/
|
| */
|
| @@ -914,24 +181,7 @@
|
| return h;
|
| }
|
|
|
| -#include "math.h"
|
| -#define MAX_PSNR 100
|
| -static double vp8_mse2psnr(double Samples, double Peak, double Mse) {
|
| - double psnr;
|
|
|
| - if ((double)Mse > 0.0)
|
| - psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
|
| - else
|
| - psnr = MAX_PSNR; /* Limit to prevent / 0 */
|
| -
|
| - if (psnr > MAX_PSNR)
|
| - psnr = MAX_PSNR;
|
| -
|
| - return psnr;
|
| -}
|
| -
|
| -
|
| -#include "args.h"
|
| static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
|
| "Debug mode (makes output deterministic)");
|
| static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
|
| @@ -966,11 +216,7 @@
|
| "Show encoder parameters");
|
| static const arg_def_t psnrarg = ARG_DEF(NULL, "psnr", 0,
|
| "Show PSNR in status line");
|
| -enum TestDecodeFatality {
|
| - TEST_DECODE_OFF,
|
| - TEST_DECODE_FATAL,
|
| - TEST_DECODE_WARN,
|
| -};
|
| +
|
| static const struct arg_enum_list test_decode_enum[] = {
|
| {"off", TEST_DECODE_OFF},
|
| {"fatal", TEST_DECODE_FATAL},
|
| @@ -990,11 +236,19 @@
|
| "Show quantizer histogram (n-buckets)");
|
| static const arg_def_t rate_hist_n = ARG_DEF(NULL, "rate-hist", 1,
|
| "Show rate histogram (n-buckets)");
|
| +static const arg_def_t disable_warnings =
|
| + ARG_DEF(NULL, "disable-warnings", 0,
|
| + "Disable warnings about potentially incorrect encode settings.");
|
| +static const arg_def_t disable_warning_prompt =
|
| + ARG_DEF("y", "disable-warning-prompt", 0,
|
| + "Display warnings, but do not prompt user to continue.");
|
| +
|
| static const arg_def_t *main_args[] = {
|
| &debugmode,
|
| &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &skip,
|
| &deadline, &best_dl, &good_dl, &rt_dl,
|
| - &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, &rate_hist_n,
|
| + &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n,
|
| + &rate_hist_n, &disable_warnings, &disable_warning_prompt,
|
| NULL
|
| };
|
|
|
| @@ -1132,6 +386,9 @@
|
| #if CONFIG_VP9_ENCODER
|
| static const arg_def_t frame_parallel_decoding = ARG_DEF(
|
| NULL, "frame-parallel", 1, "Enable frame parallel decodability features");
|
| +static const arg_def_t aq_mode = ARG_DEF(
|
| + NULL, "aq-mode", 1,
|
| + "Adaptive q mode (0: off (by default), 1: variance 2: complexity)");
|
| #endif
|
|
|
| #if CONFIG_VP8_ENCODER
|
| @@ -1156,7 +413,7 @@
|
| &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
|
| &tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type,
|
| &tune_ssim, &cq_level, &max_intra_rate_pct, &lossless,
|
| - &frame_parallel_decoding,
|
| + &frame_parallel_decoding, &aq_mode,
|
| NULL
|
| };
|
| static const int vp9_arg_ctrl_map[] = {
|
| @@ -1165,14 +422,14 @@
|
| VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS,
|
| VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
|
| VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
|
| - VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING,
|
| + VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE,
|
| 0
|
| };
|
| #endif
|
|
|
| static const arg_def_t *no_args[] = { NULL };
|
|
|
| -static void usage_exit() {
|
| +void usage_exit() {
|
| int i;
|
|
|
| fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n",
|
| @@ -1385,9 +642,9 @@
|
| };
|
|
|
|
|
| -static void init_rate_histogram(struct rate_hist *hist,
|
| +static void init_rate_histogram(struct rate_hist *hist,
|
| const vpx_codec_enc_cfg_t *cfg,
|
| - const vpx_rational_t *fps) {
|
| + const vpx_rational_t *fps) {
|
| int i;
|
|
|
| /* Determine the number of samples in the buffer. Use the file's framerate
|
| @@ -1605,29 +862,6 @@
|
| NELEMENTS(vp9_arg_ctrl_map))
|
| #endif
|
|
|
| -/* Configuration elements common to all streams */
|
| -struct global_config {
|
| - const struct codec_item *codec;
|
| - int passes;
|
| - int pass;
|
| - int usage;
|
| - int deadline;
|
| - int use_i420;
|
| - int quiet;
|
| - int verbose;
|
| - int limit;
|
| - int skip_frames;
|
| - int show_psnr;
|
| - enum TestDecodeFatality test_decode;
|
| - int have_framerate;
|
| - struct vpx_rational framerate;
|
| - int out_part;
|
| - int debug;
|
| - int show_q_hist_buckets;
|
| - int show_rate_hist_buckets;
|
| -};
|
| -
|
| -
|
| /* Per-stream configuration */
|
| struct stream_config {
|
| struct vpx_codec_enc_cfg cfg;
|
| @@ -1647,7 +881,7 @@
|
| struct stream_config config;
|
| FILE *file;
|
| struct rate_hist rate_hist;
|
| - EbmlGlobal ebml;
|
| + struct EbmlGlobal ebml;
|
| uint32_t hash;
|
| uint64_t psnr_sse_total;
|
| uint64_t psnr_samples_total;
|
| @@ -1680,7 +914,7 @@
|
| }
|
|
|
|
|
| -static void parse_global_config(struct global_config *global, char **argv) {
|
| +static void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
|
| char **argi, **argj;
|
| struct arg arg;
|
|
|
| @@ -1757,6 +991,10 @@
|
| global->show_q_hist_buckets = arg_parse_uint(&arg);
|
| else if (arg_match(&arg, &rate_hist_n, argi))
|
| global->show_rate_hist_buckets = arg_parse_uint(&arg);
|
| + else if (arg_match(&arg, &disable_warnings, argi))
|
| + global->disable_warnings = 1;
|
| + else if (arg_match(&arg, &disable_warning_prompt, argi))
|
| + global->disable_warning_prompt = 1;
|
| else
|
| argj++;
|
| }
|
| @@ -1783,12 +1021,10 @@
|
| }
|
|
|
|
|
| -void open_input_file(struct input_state *input) {
|
| - unsigned int fourcc;
|
| -
|
| +void open_input_file(struct VpxInputContext *input) {
|
| /* Parse certain options from the input file, if possible */
|
| - input->file = strcmp(input->fn, "-") ? fopen(input->fn, "rb")
|
| - : set_binary_mode(stdin);
|
| + input->file = strcmp(input->filename, "-")
|
| + ? fopen(input->filename, "rb") : set_binary_mode(stdin);
|
|
|
| if (!input->file)
|
| fatal("Failed to open input file");
|
| @@ -1812,39 +1048,29 @@
|
| if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4,
|
| input->only_i420) >= 0) {
|
| input->file_type = FILE_TYPE_Y4M;
|
| - input->w = input->y4m.pic_w;
|
| - input->h = input->y4m.pic_h;
|
| - input->framerate.num = input->y4m.fps_n;
|
| - input->framerate.den = input->y4m.fps_d;
|
| + input->width = input->y4m.pic_w;
|
| + input->height = input->y4m.pic_h;
|
| + input->framerate.numerator = input->y4m.fps_n;
|
| + input->framerate.denominator = input->y4m.fps_d;
|
| input->use_i420 = 0;
|
| } else
|
| fatal("Unsupported Y4M stream.");
|
| - } else if (input->detect.buf_read == 4 && file_is_ivf(input, &fourcc)) {
|
| - input->file_type = FILE_TYPE_IVF;
|
| - switch (fourcc) {
|
| - case 0x32315659:
|
| - input->use_i420 = 0;
|
| - break;
|
| - case 0x30323449:
|
| - input->use_i420 = 1;
|
| - break;
|
| - default:
|
| - fatal("Unsupported fourcc (%08x) in IVF", fourcc);
|
| - }
|
| + } else if (input->detect.buf_read == 4 && file_is_ivf(input)) {
|
| + fatal("IVF is not supported as input.");
|
| } else {
|
| input->file_type = FILE_TYPE_RAW;
|
| }
|
| }
|
|
|
|
|
| -static void close_input_file(struct input_state *input) {
|
| +static void close_input_file(struct VpxInputContext *input) {
|
| fclose(input->file);
|
| if (input->file_type == FILE_TYPE_Y4M)
|
| y4m_input_close(&input->y4m);
|
| }
|
|
|
| -static struct stream_state *new_stream(struct global_config *global,
|
| - struct stream_state *prev) {
|
| +static struct stream_state *new_stream(struct VpxEncoderConfig *global,
|
| + struct stream_state *prev) {
|
| struct stream_state *stream;
|
|
|
| stream = calloc(1, sizeof(*stream));
|
| @@ -1892,7 +1118,7 @@
|
| }
|
|
|
|
|
| -static int parse_stream_params(struct global_config *global,
|
| +static int parse_stream_params(struct VpxEncoderConfig *global,
|
| struct stream_state *stream,
|
| char **argv) {
|
| char **argi, **argj;
|
| @@ -2038,14 +1264,13 @@
|
| }
|
|
|
|
|
| -#define FOREACH_STREAM(func)\
|
| - do\
|
| - {\
|
| - struct stream_state *stream;\
|
| - \
|
| - for(stream = streams; stream; stream = stream->next)\
|
| - func;\
|
| - }while(0)
|
| +#define FOREACH_STREAM(func) \
|
| + do { \
|
| + struct stream_state *stream; \
|
| + for (stream = streams; stream; stream = stream->next) { \
|
| + func; \
|
| + } \
|
| + } while (0)
|
|
|
|
|
| static void validate_stream_config(struct stream_state *stream) {
|
| @@ -2097,8 +1322,8 @@
|
| }
|
|
|
|
|
| -static void set_default_kf_interval(struct stream_state *stream,
|
| - struct global_config *global) {
|
| +static void set_default_kf_interval(struct stream_state *stream,
|
| + struct VpxEncoderConfig *global) {
|
| /* Use a max keyframe interval of 5 seconds, if none was
|
| * specified on the command line.
|
| */
|
| @@ -2110,9 +1335,9 @@
|
| }
|
|
|
|
|
| -static void show_stream_config(struct stream_state *stream,
|
| - struct global_config *global,
|
| - struct input_state *input) {
|
| +static void show_stream_config(struct stream_state *stream,
|
| + struct VpxEncoderConfig *global,
|
| + struct VpxInputContext *input) {
|
|
|
| #define SHOW(field) \
|
| fprintf(stderr, " %-28s = %d\n", #field, stream->config.cfg.field)
|
| @@ -2120,7 +1345,7 @@
|
| if (stream->index == 0) {
|
| fprintf(stderr, "Codec: %s\n",
|
| vpx_codec_iface_name(global->codec->iface()));
|
| - fprintf(stderr, "Source file: %s Format: %s\n", input->fn,
|
| + fprintf(stderr, "Source file: %s Format: %s\n", input->filename,
|
| input->use_i420 ? "I420" : "YV12");
|
| }
|
| if (stream->next || stream->index)
|
| @@ -2161,7 +1386,7 @@
|
|
|
|
|
| static void open_output_file(struct stream_state *stream,
|
| - struct global_config *global) {
|
| + struct VpxEncoderConfig *global) {
|
| const char *fn = stream->config.out_fn;
|
|
|
| stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout);
|
| @@ -2179,7 +1404,7 @@
|
| stream->config.stereo_fmt,
|
| global->codec->fourcc);
|
| } else
|
| - write_ivf_file_header(stream->file, &stream->config.cfg,
|
| + ivf_write_file_header(stream->file, &stream->config.cfg,
|
| global->codec->fourcc, 0);
|
| }
|
|
|
| @@ -2192,7 +1417,7 @@
|
| stream->ebml.cue_list = NULL;
|
| } else {
|
| if (!fseek(stream->file, 0, SEEK_SET))
|
| - write_ivf_file_header(stream->file, &stream->config.cfg,
|
| + ivf_write_file_header(stream->file, &stream->config.cfg,
|
| fourcc,
|
| stream->frames_out);
|
| }
|
| @@ -2201,9 +1426,9 @@
|
| }
|
|
|
|
|
| -static void setup_pass(struct stream_state *stream,
|
| - struct global_config *global,
|
| - int pass) {
|
| +static void setup_pass(struct stream_state *stream,
|
| + struct VpxEncoderConfig *global,
|
| + int pass) {
|
| if (stream->config.stats_fn) {
|
| if (!stats_open_file(&stream->stats, stream->config.stats_fn,
|
| pass))
|
| @@ -2225,8 +1450,8 @@
|
| }
|
|
|
|
|
| -static void initialize_encoder(struct stream_state *stream,
|
| - struct global_config *global) {
|
| +static void initialize_encoder(struct stream_state *stream,
|
| + struct VpxEncoderConfig *global) {
|
| int i;
|
| int flags = 0;
|
|
|
| @@ -2260,10 +1485,10 @@
|
| }
|
|
|
|
|
| -static void encode_frame(struct stream_state *stream,
|
| - struct global_config *global,
|
| - struct vpx_image *img,
|
| - unsigned int frames_in) {
|
| +static void encode_frame(struct stream_state *stream,
|
| + struct VpxEncoderConfig *global,
|
| + struct vpx_image *img,
|
| + unsigned int frames_in) {
|
| vpx_codec_pts_t frame_start, next_frame_start;
|
| struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
|
| struct vpx_usec_timer timer;
|
| @@ -2318,9 +1543,9 @@
|
| }
|
|
|
|
|
| -static void get_cx_data(struct stream_state *stream,
|
| - struct global_config *global,
|
| - int *got_data) {
|
| +static void get_cx_data(struct stream_state *stream,
|
| + struct VpxEncoderConfig *global,
|
| + int *got_data) {
|
| const vpx_codec_cx_pkt_t *pkt;
|
| const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
|
| vpx_codec_iter_t iter = NULL;
|
| @@ -2352,14 +1577,14 @@
|
| ivf_header_pos = ftello(stream->file);
|
| fsize = pkt->data.frame.sz;
|
|
|
| - write_ivf_frame_header(stream->file, pkt);
|
| + ivf_write_frame_header(stream->file, pkt);
|
| } else {
|
| fsize += pkt->data.frame.sz;
|
|
|
| if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
|
| off_t currpos = ftello(stream->file);
|
| fseeko(stream->file, ivf_header_pos, SEEK_SET);
|
| - write_ivf_frame_size(stream->file, fsize);
|
| + ivf_write_frame_size(stream->file, fsize);
|
| fseeko(stream->file, currpos, SEEK_SET);
|
| }
|
| }
|
| @@ -2512,18 +1737,19 @@
|
| }
|
| }
|
|
|
| +
|
| int main(int argc, const char **argv_) {
|
| - int pass;
|
| - vpx_image_t raw;
|
| - int frame_avail, got_data;
|
| + int pass;
|
| + vpx_image_t raw;
|
| + int frame_avail, got_data;
|
|
|
| - struct input_state input = {0};
|
| - struct global_config global;
|
| - struct stream_state *streams = NULL;
|
| - char **argv, **argi;
|
| - uint64_t cx_time = 0;
|
| - int stream_cnt = 0;
|
| - int res = 0;
|
| + struct VpxInputContext input = {0};
|
| + struct VpxEncoderConfig global;
|
| + struct stream_state *streams = NULL;
|
| + char **argv, **argi;
|
| + uint64_t cx_time = 0;
|
| + int stream_cnt = 0;
|
| + int res = 0;
|
|
|
| exec_name = argv_[0];
|
|
|
| @@ -2531,8 +1757,8 @@
|
| usage_exit();
|
|
|
| /* Setup default input stream settings */
|
| - input.framerate.num = 30;
|
| - input.framerate.den = 1;
|
| + input.framerate.numerator = 30;
|
| + input.framerate.denominator = 1;
|
| input.use_i420 = 1;
|
| input.only_i420 = 1;
|
|
|
| @@ -2543,6 +1769,7 @@
|
| argv = argv_dup(argc - 1, argv_ + 1);
|
| parse_global_config(&global, argv);
|
|
|
| +
|
| {
|
| /* Now parse each stream's parameters. Using a local scope here
|
| * due to the use of 'stream' as loop variable in FOREACH_STREAM
|
| @@ -2563,10 +1790,13 @@
|
| if (argi[0][0] == '-' && argi[0][1])
|
| die("Error: Unrecognized option %s\n", *argi);
|
|
|
| + FOREACH_STREAM(check_encoder_config(global.disable_warning_prompt,
|
| + &global, &stream->config.cfg););
|
| +
|
| /* Handle non-option arguments */
|
| - input.fn = argv[0];
|
| + input.filename = argv[0];
|
|
|
| - if (!input.fn)
|
| + if (!input.filename)
|
| usage_exit();
|
|
|
| #if CONFIG_NON420
|
| @@ -2586,20 +1816,20 @@
|
| /* If the input file doesn't specify its w/h (raw files), try to get
|
| * the data from the first stream's configuration.
|
| */
|
| - if (!input.w || !input.h)
|
| + if (!input.width || !input.height)
|
| FOREACH_STREAM( {
|
| if (stream->config.cfg.g_w && stream->config.cfg.g_h) {
|
| - input.w = stream->config.cfg.g_w;
|
| - input.h = stream->config.cfg.g_h;
|
| + input.width = stream->config.cfg.g_w;
|
| + input.height = stream->config.cfg.g_h;
|
| break;
|
| }
|
| });
|
|
|
| /* Update stream configurations from the input file's parameters */
|
| - if (!input.w || !input.h)
|
| + if (!input.width || !input.height)
|
| fatal("Specify stream dimensions with --width (-w) "
|
| " and --height (-h)");
|
| - FOREACH_STREAM(set_stream_dimensions(stream, input.w, input.h));
|
| + FOREACH_STREAM(set_stream_dimensions(stream, input.width, input.height));
|
| FOREACH_STREAM(validate_stream_config(stream));
|
|
|
| /* Ensure that --passes and --pass are consistent. If --pass is set and
|
| @@ -2615,8 +1845,10 @@
|
| /* Use the frame rate from the file only if none was specified
|
| * on the command-line.
|
| */
|
| - if (!global.have_framerate)
|
| - global.framerate = input.framerate;
|
| + if (!global.have_framerate) {
|
| + global.framerate.num = input.framerate.numerator;
|
| + global.framerate.den = input.framerate.denominator;
|
| + }
|
|
|
| FOREACH_STREAM(set_default_kf_interval(stream, &global));
|
|
|
| @@ -2634,7 +1866,7 @@
|
| vpx_img_alloc(&raw,
|
| input.use_i420 ? VPX_IMG_FMT_I420
|
| : VPX_IMG_FMT_YV12,
|
| - input.w, input.h, 32);
|
| + input.width, input.height, 32);
|
|
|
| FOREACH_STREAM(init_rate_histogram(&stream->rate_hist,
|
| &stream->config.cfg,
|
|
|