11b362b15af34006e6a11974088a46d42b903418eJohann/*
21b362b15af34006e6a11974088a46d42b903418eJohann *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
31b362b15af34006e6a11974088a46d42b903418eJohann *
41b362b15af34006e6a11974088a46d42b903418eJohann *  Use of this source code is governed by a BSD-style license
51b362b15af34006e6a11974088a46d42b903418eJohann *  that can be found in the LICENSE file in the root of the source
61b362b15af34006e6a11974088a46d42b903418eJohann *  tree. An additional intellectual property rights grant can be found
71b362b15af34006e6a11974088a46d42b903418eJohann *  in the file PATENTS.  All contributing project authors may
81b362b15af34006e6a11974088a46d42b903418eJohann *  be found in the AUTHORS file in the root of the source tree.
91b362b15af34006e6a11974088a46d42b903418eJohann */
101b362b15af34006e6a11974088a46d42b903418eJohann
111b362b15af34006e6a11974088a46d42b903418eJohann/*
121b362b15af34006e6a11974088a46d42b903418eJohann * This is an example demonstrating multi-resolution encoding in VP8.
131b362b15af34006e6a11974088a46d42b903418eJohann * High-resolution input video is down-sampled to lower-resolutions. The
141b362b15af34006e6a11974088a46d42b903418eJohann * encoder then encodes the video and outputs multiple bitstreams with
151b362b15af34006e6a11974088a46d42b903418eJohann * different resolutions.
161b362b15af34006e6a11974088a46d42b903418eJohann */
171b362b15af34006e6a11974088a46d42b903418eJohann#include <stdio.h>
181b362b15af34006e6a11974088a46d42b903418eJohann#include <stdlib.h>
191b362b15af34006e6a11974088a46d42b903418eJohann#include <stdarg.h>
201b362b15af34006e6a11974088a46d42b903418eJohann#include <string.h>
21b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include <math.h>
221b362b15af34006e6a11974088a46d42b903418eJohann#define VPX_CODEC_DISABLE_COMPAT 1
231b362b15af34006e6a11974088a46d42b903418eJohann#include "vpx/vpx_encoder.h"
241b362b15af34006e6a11974088a46d42b903418eJohann#include "vpx/vp8cx.h"
251b362b15af34006e6a11974088a46d42b903418eJohann#include "vpx_ports/mem_ops.h"
26b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include "./tools_common.h"
271b362b15af34006e6a11974088a46d42b903418eJohann#define interface (vpx_codec_vp8_cx())
281b362b15af34006e6a11974088a46d42b903418eJohann#define fourcc    0x30385056
291b362b15af34006e6a11974088a46d42b903418eJohann
301b362b15af34006e6a11974088a46d42b903418eJohann#define IVF_FILE_HDR_SZ  (32)
311b362b15af34006e6a11974088a46d42b903418eJohann#define IVF_FRAME_HDR_SZ (12)
321b362b15af34006e6a11974088a46d42b903418eJohann
331b362b15af34006e6a11974088a46d42b903418eJohann/*
341b362b15af34006e6a11974088a46d42b903418eJohann * The input video frame is downsampled several times to generate a multi-level
351b362b15af34006e6a11974088a46d42b903418eJohann * hierarchical structure. NUM_ENCODERS is defined as the number of encoding
361b362b15af34006e6a11974088a46d42b903418eJohann * levels required. For example, if the size of input video is 1280x720,
371b362b15af34006e6a11974088a46d42b903418eJohann * NUM_ENCODERS is 3, and down-sampling factor is 2, the encoder outputs 3
381b362b15af34006e6a11974088a46d42b903418eJohann * bitstreams with resolution of 1280x720(level 0), 640x360(level 1), and
391b362b15af34006e6a11974088a46d42b903418eJohann * 320x180(level 2) respectively.
401b362b15af34006e6a11974088a46d42b903418eJohann */
411b362b15af34006e6a11974088a46d42b903418eJohann#define NUM_ENCODERS 3
421b362b15af34006e6a11974088a46d42b903418eJohann
431b362b15af34006e6a11974088a46d42b903418eJohann/* This example uses the scaler function in libyuv. */
441b362b15af34006e6a11974088a46d42b903418eJohann#include "third_party/libyuv/include/libyuv/basic_types.h"
451b362b15af34006e6a11974088a46d42b903418eJohann#include "third_party/libyuv/include/libyuv/scale.h"
461b362b15af34006e6a11974088a46d42b903418eJohann#include "third_party/libyuv/include/libyuv/cpu_id.h"
471b362b15af34006e6a11974088a46d42b903418eJohann
481b362b15af34006e6a11974088a46d42b903418eJohannstatic void die(const char *fmt, ...) {
491b362b15af34006e6a11974088a46d42b903418eJohann    va_list ap;
501b362b15af34006e6a11974088a46d42b903418eJohann
511b362b15af34006e6a11974088a46d42b903418eJohann    va_start(ap, fmt);
521b362b15af34006e6a11974088a46d42b903418eJohann    vprintf(fmt, ap);
531b362b15af34006e6a11974088a46d42b903418eJohann    if(fmt[strlen(fmt)-1] != '\n')
541b362b15af34006e6a11974088a46d42b903418eJohann        printf("\n");
551b362b15af34006e6a11974088a46d42b903418eJohann    exit(EXIT_FAILURE);
561b362b15af34006e6a11974088a46d42b903418eJohann}
571b362b15af34006e6a11974088a46d42b903418eJohann
581b362b15af34006e6a11974088a46d42b903418eJohannstatic void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
591b362b15af34006e6a11974088a46d42b903418eJohann    const char *detail = vpx_codec_error_detail(ctx);
601b362b15af34006e6a11974088a46d42b903418eJohann
611b362b15af34006e6a11974088a46d42b903418eJohann    printf("%s: %s\n", s, vpx_codec_error(ctx));
621b362b15af34006e6a11974088a46d42b903418eJohann    if(detail)
631b362b15af34006e6a11974088a46d42b903418eJohann        printf("    %s\n",detail);
641b362b15af34006e6a11974088a46d42b903418eJohann    exit(EXIT_FAILURE);
651b362b15af34006e6a11974088a46d42b903418eJohann}
661b362b15af34006e6a11974088a46d42b903418eJohann
671b362b15af34006e6a11974088a46d42b903418eJohannint (*read_frame_p)(FILE *f, vpx_image_t *img);
681b362b15af34006e6a11974088a46d42b903418eJohann
691b362b15af34006e6a11974088a46d42b903418eJohannstatic int read_frame(FILE *f, vpx_image_t *img) {
701b362b15af34006e6a11974088a46d42b903418eJohann    size_t nbytes, to_read;
711b362b15af34006e6a11974088a46d42b903418eJohann    int    res = 1;
721b362b15af34006e6a11974088a46d42b903418eJohann
731b362b15af34006e6a11974088a46d42b903418eJohann    to_read = img->w*img->h*3/2;
741b362b15af34006e6a11974088a46d42b903418eJohann    nbytes = fread(img->planes[0], 1, to_read, f);
751b362b15af34006e6a11974088a46d42b903418eJohann    if(nbytes != to_read) {
761b362b15af34006e6a11974088a46d42b903418eJohann        res = 0;
771b362b15af34006e6a11974088a46d42b903418eJohann        if(nbytes > 0)
781b362b15af34006e6a11974088a46d42b903418eJohann            printf("Warning: Read partial frame. Check your width & height!\n");
791b362b15af34006e6a11974088a46d42b903418eJohann    }
801b362b15af34006e6a11974088a46d42b903418eJohann    return res;
811b362b15af34006e6a11974088a46d42b903418eJohann}
821b362b15af34006e6a11974088a46d42b903418eJohann
831b362b15af34006e6a11974088a46d42b903418eJohannstatic int read_frame_by_row(FILE *f, vpx_image_t *img) {
841b362b15af34006e6a11974088a46d42b903418eJohann    size_t nbytes, to_read;
851b362b15af34006e6a11974088a46d42b903418eJohann    int    res = 1;
861b362b15af34006e6a11974088a46d42b903418eJohann    int plane;
871b362b15af34006e6a11974088a46d42b903418eJohann
881b362b15af34006e6a11974088a46d42b903418eJohann    for (plane = 0; plane < 3; plane++)
891b362b15af34006e6a11974088a46d42b903418eJohann    {
901b362b15af34006e6a11974088a46d42b903418eJohann        unsigned char *ptr;
911b362b15af34006e6a11974088a46d42b903418eJohann        int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
921b362b15af34006e6a11974088a46d42b903418eJohann        int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
931b362b15af34006e6a11974088a46d42b903418eJohann        int r;
941b362b15af34006e6a11974088a46d42b903418eJohann
951b362b15af34006e6a11974088a46d42b903418eJohann        /* Determine the correct plane based on the image format. The for-loop
961b362b15af34006e6a11974088a46d42b903418eJohann         * always counts in Y,U,V order, but this may not match the order of
971b362b15af34006e6a11974088a46d42b903418eJohann         * the data on disk.
981b362b15af34006e6a11974088a46d42b903418eJohann         */
991b362b15af34006e6a11974088a46d42b903418eJohann        switch (plane)
1001b362b15af34006e6a11974088a46d42b903418eJohann        {
1011b362b15af34006e6a11974088a46d42b903418eJohann        case 1:
1021b362b15af34006e6a11974088a46d42b903418eJohann            ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12? VPX_PLANE_V : VPX_PLANE_U];
1031b362b15af34006e6a11974088a46d42b903418eJohann            break;
1041b362b15af34006e6a11974088a46d42b903418eJohann        case 2:
1051b362b15af34006e6a11974088a46d42b903418eJohann            ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12?VPX_PLANE_U : VPX_PLANE_V];
1061b362b15af34006e6a11974088a46d42b903418eJohann            break;
1071b362b15af34006e6a11974088a46d42b903418eJohann        default:
1081b362b15af34006e6a11974088a46d42b903418eJohann            ptr = img->planes[plane];
1091b362b15af34006e6a11974088a46d42b903418eJohann        }
1101b362b15af34006e6a11974088a46d42b903418eJohann
1111b362b15af34006e6a11974088a46d42b903418eJohann        for (r = 0; r < h; r++)
1121b362b15af34006e6a11974088a46d42b903418eJohann        {
1131b362b15af34006e6a11974088a46d42b903418eJohann            to_read = w;
1141b362b15af34006e6a11974088a46d42b903418eJohann
1151b362b15af34006e6a11974088a46d42b903418eJohann            nbytes = fread(ptr, 1, to_read, f);
1161b362b15af34006e6a11974088a46d42b903418eJohann            if(nbytes != to_read) {
1171b362b15af34006e6a11974088a46d42b903418eJohann                res = 0;
1181b362b15af34006e6a11974088a46d42b903418eJohann                if(nbytes > 0)
1191b362b15af34006e6a11974088a46d42b903418eJohann                    printf("Warning: Read partial frame. Check your width & height!\n");
1201b362b15af34006e6a11974088a46d42b903418eJohann                break;
1211b362b15af34006e6a11974088a46d42b903418eJohann            }
1221b362b15af34006e6a11974088a46d42b903418eJohann
1231b362b15af34006e6a11974088a46d42b903418eJohann            ptr += img->stride[plane];
1241b362b15af34006e6a11974088a46d42b903418eJohann        }
1251b362b15af34006e6a11974088a46d42b903418eJohann        if (!res)
1261b362b15af34006e6a11974088a46d42b903418eJohann            break;
1271b362b15af34006e6a11974088a46d42b903418eJohann    }
1281b362b15af34006e6a11974088a46d42b903418eJohann
1291b362b15af34006e6a11974088a46d42b903418eJohann    return res;
1301b362b15af34006e6a11974088a46d42b903418eJohann}
1311b362b15af34006e6a11974088a46d42b903418eJohann
1321b362b15af34006e6a11974088a46d42b903418eJohannstatic void write_ivf_file_header(FILE *outfile,
1331b362b15af34006e6a11974088a46d42b903418eJohann                                  const vpx_codec_enc_cfg_t *cfg,
1341b362b15af34006e6a11974088a46d42b903418eJohann                                  int frame_cnt) {
1351b362b15af34006e6a11974088a46d42b903418eJohann    char header[32];
1361b362b15af34006e6a11974088a46d42b903418eJohann
1371b362b15af34006e6a11974088a46d42b903418eJohann    if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
1381b362b15af34006e6a11974088a46d42b903418eJohann        return;
1391b362b15af34006e6a11974088a46d42b903418eJohann    header[0] = 'D';
1401b362b15af34006e6a11974088a46d42b903418eJohann    header[1] = 'K';
1411b362b15af34006e6a11974088a46d42b903418eJohann    header[2] = 'I';
1421b362b15af34006e6a11974088a46d42b903418eJohann    header[3] = 'F';
1431b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le16(header+4,  0);                   /* version */
1441b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le16(header+6,  32);                  /* headersize */
1451b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le32(header+8,  fourcc);              /* headersize */
1461b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le16(header+12, cfg->g_w);            /* width */
1471b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le16(header+14, cfg->g_h);            /* height */
1481b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
1491b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
1501b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le32(header+24, frame_cnt);           /* length */
1511b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le32(header+28, 0);                   /* unused */
1521b362b15af34006e6a11974088a46d42b903418eJohann
1531b362b15af34006e6a11974088a46d42b903418eJohann    (void) fwrite(header, 1, 32, outfile);
1541b362b15af34006e6a11974088a46d42b903418eJohann}
1551b362b15af34006e6a11974088a46d42b903418eJohann
1561b362b15af34006e6a11974088a46d42b903418eJohannstatic void write_ivf_frame_header(FILE *outfile,
1571b362b15af34006e6a11974088a46d42b903418eJohann                                   const vpx_codec_cx_pkt_t *pkt)
1581b362b15af34006e6a11974088a46d42b903418eJohann{
1591b362b15af34006e6a11974088a46d42b903418eJohann    char             header[12];
1601b362b15af34006e6a11974088a46d42b903418eJohann    vpx_codec_pts_t  pts;
1611b362b15af34006e6a11974088a46d42b903418eJohann
1621b362b15af34006e6a11974088a46d42b903418eJohann    if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
1631b362b15af34006e6a11974088a46d42b903418eJohann        return;
1641b362b15af34006e6a11974088a46d42b903418eJohann
1651b362b15af34006e6a11974088a46d42b903418eJohann    pts = pkt->data.frame.pts;
1661b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le32(header, pkt->data.frame.sz);
1671b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le32(header+4, pts&0xFFFFFFFF);
1681b362b15af34006e6a11974088a46d42b903418eJohann    mem_put_le32(header+8, pts >> 32);
1691b362b15af34006e6a11974088a46d42b903418eJohann
1701b362b15af34006e6a11974088a46d42b903418eJohann    (void) fwrite(header, 1, 12, outfile);
1711b362b15af34006e6a11974088a46d42b903418eJohann}
1721b362b15af34006e6a11974088a46d42b903418eJohann
1731b362b15af34006e6a11974088a46d42b903418eJohannint main(int argc, char **argv)
1741b362b15af34006e6a11974088a46d42b903418eJohann{
1751b362b15af34006e6a11974088a46d42b903418eJohann    FILE                *infile, *outfile[NUM_ENCODERS];
1761b362b15af34006e6a11974088a46d42b903418eJohann    vpx_codec_ctx_t      codec[NUM_ENCODERS];
1771b362b15af34006e6a11974088a46d42b903418eJohann    vpx_codec_enc_cfg_t  cfg[NUM_ENCODERS];
1781b362b15af34006e6a11974088a46d42b903418eJohann    vpx_codec_pts_t      frame_cnt = 0;
1791b362b15af34006e6a11974088a46d42b903418eJohann    vpx_image_t          raw[NUM_ENCODERS];
1801b362b15af34006e6a11974088a46d42b903418eJohann    vpx_codec_err_t      res[NUM_ENCODERS];
1811b362b15af34006e6a11974088a46d42b903418eJohann
1821b362b15af34006e6a11974088a46d42b903418eJohann    int                  i;
1831b362b15af34006e6a11974088a46d42b903418eJohann    long                 width;
1841b362b15af34006e6a11974088a46d42b903418eJohann    long                 height;
1851b362b15af34006e6a11974088a46d42b903418eJohann    int                  frame_avail;
1861b362b15af34006e6a11974088a46d42b903418eJohann    int                  got_data;
1871b362b15af34006e6a11974088a46d42b903418eJohann    int                  flags = 0;
1881b362b15af34006e6a11974088a46d42b903418eJohann
1891b362b15af34006e6a11974088a46d42b903418eJohann    /*Currently, only realtime mode is supported in multi-resolution encoding.*/
1901b362b15af34006e6a11974088a46d42b903418eJohann    int                  arg_deadline = VPX_DL_REALTIME;
1911b362b15af34006e6a11974088a46d42b903418eJohann
1921b362b15af34006e6a11974088a46d42b903418eJohann    /* Set show_psnr to 1/0 to show/not show PSNR. Choose show_psnr=0 if you
1931b362b15af34006e6a11974088a46d42b903418eJohann       don't need to know PSNR, which will skip PSNR calculation and save
1941b362b15af34006e6a11974088a46d42b903418eJohann       encoding time. */
1951b362b15af34006e6a11974088a46d42b903418eJohann    int                  show_psnr = 0;
1961b362b15af34006e6a11974088a46d42b903418eJohann    uint64_t             psnr_sse_total[NUM_ENCODERS] = {0};
1971b362b15af34006e6a11974088a46d42b903418eJohann    uint64_t             psnr_samples_total[NUM_ENCODERS] = {0};
1981b362b15af34006e6a11974088a46d42b903418eJohann    double               psnr_totals[NUM_ENCODERS][4] = {{0,0}};
1991b362b15af34006e6a11974088a46d42b903418eJohann    int                  psnr_count[NUM_ENCODERS] = {0};
2001b362b15af34006e6a11974088a46d42b903418eJohann
2011b362b15af34006e6a11974088a46d42b903418eJohann    /* Set the required target bitrates for each resolution level.
2021b362b15af34006e6a11974088a46d42b903418eJohann     * If target bitrate for highest-resolution level is set to 0,
2031b362b15af34006e6a11974088a46d42b903418eJohann     * (i.e. target_bitrate[0]=0), we skip encoding at that level.
2041b362b15af34006e6a11974088a46d42b903418eJohann     */
205ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    unsigned int         target_bitrate[NUM_ENCODERS]={1000, 500, 100};
2061b362b15af34006e6a11974088a46d42b903418eJohann    /* Enter the frame rate of the input video */
2071b362b15af34006e6a11974088a46d42b903418eJohann    int                  framerate = 30;
2081b362b15af34006e6a11974088a46d42b903418eJohann    /* Set down-sampling factor for each resolution level.
2091b362b15af34006e6a11974088a46d42b903418eJohann       dsf[0] controls down sampling from level 0 to level 1;
2101b362b15af34006e6a11974088a46d42b903418eJohann       dsf[1] controls down sampling from level 1 to level 2;
2111b362b15af34006e6a11974088a46d42b903418eJohann       dsf[2] is not used. */
2121b362b15af34006e6a11974088a46d42b903418eJohann    vpx_rational_t dsf[NUM_ENCODERS] = {{2, 1}, {2, 1}, {1, 1}};
2131b362b15af34006e6a11974088a46d42b903418eJohann
2141b362b15af34006e6a11974088a46d42b903418eJohann    if(argc!= (5+NUM_ENCODERS))
2151b362b15af34006e6a11974088a46d42b903418eJohann        die("Usage: %s <width> <height> <infile> <outfile(s)> <output psnr?>\n",
2161b362b15af34006e6a11974088a46d42b903418eJohann            argv[0]);
2171b362b15af34006e6a11974088a46d42b903418eJohann
2181b362b15af34006e6a11974088a46d42b903418eJohann    printf("Using %s\n",vpx_codec_iface_name(interface));
2191b362b15af34006e6a11974088a46d42b903418eJohann
2201b362b15af34006e6a11974088a46d42b903418eJohann    width = strtol(argv[1], NULL, 0);
2211b362b15af34006e6a11974088a46d42b903418eJohann    height = strtol(argv[2], NULL, 0);
2221b362b15af34006e6a11974088a46d42b903418eJohann
2231b362b15af34006e6a11974088a46d42b903418eJohann    if(width < 16 || width%2 || height <16 || height%2)
2241b362b15af34006e6a11974088a46d42b903418eJohann        die("Invalid resolution: %ldx%ld", width, height);
2251b362b15af34006e6a11974088a46d42b903418eJohann
2261b362b15af34006e6a11974088a46d42b903418eJohann    /* Open input video file for encoding */
2271b362b15af34006e6a11974088a46d42b903418eJohann    if(!(infile = fopen(argv[3], "rb")))
2281b362b15af34006e6a11974088a46d42b903418eJohann        die("Failed to open %s for reading", argv[3]);
2291b362b15af34006e6a11974088a46d42b903418eJohann
2301b362b15af34006e6a11974088a46d42b903418eJohann    /* Open output file for each encoder to output bitstreams */
2311b362b15af34006e6a11974088a46d42b903418eJohann    for (i=0; i< NUM_ENCODERS; i++)
2321b362b15af34006e6a11974088a46d42b903418eJohann    {
2331b362b15af34006e6a11974088a46d42b903418eJohann        if(!target_bitrate[i])
2341b362b15af34006e6a11974088a46d42b903418eJohann        {
2351b362b15af34006e6a11974088a46d42b903418eJohann            outfile[i] = NULL;
2361b362b15af34006e6a11974088a46d42b903418eJohann            continue;
2371b362b15af34006e6a11974088a46d42b903418eJohann        }
2381b362b15af34006e6a11974088a46d42b903418eJohann
2391b362b15af34006e6a11974088a46d42b903418eJohann        if(!(outfile[i] = fopen(argv[i+4], "wb")))
2401b362b15af34006e6a11974088a46d42b903418eJohann            die("Failed to open %s for writing", argv[i+4]);
2411b362b15af34006e6a11974088a46d42b903418eJohann    }
2421b362b15af34006e6a11974088a46d42b903418eJohann
2431b362b15af34006e6a11974088a46d42b903418eJohann    show_psnr = strtol(argv[NUM_ENCODERS + 4], NULL, 0);
2441b362b15af34006e6a11974088a46d42b903418eJohann
2451b362b15af34006e6a11974088a46d42b903418eJohann    /* Populate default encoder configuration */
2461b362b15af34006e6a11974088a46d42b903418eJohann    for (i=0; i< NUM_ENCODERS; i++)
2471b362b15af34006e6a11974088a46d42b903418eJohann    {
2481b362b15af34006e6a11974088a46d42b903418eJohann        res[i] = vpx_codec_enc_config_default(interface, &cfg[i], 0);
2491b362b15af34006e6a11974088a46d42b903418eJohann        if(res[i]) {
2501b362b15af34006e6a11974088a46d42b903418eJohann            printf("Failed to get config: %s\n", vpx_codec_err_to_string(res[i]));
2511b362b15af34006e6a11974088a46d42b903418eJohann            return EXIT_FAILURE;
2521b362b15af34006e6a11974088a46d42b903418eJohann        }
2531b362b15af34006e6a11974088a46d42b903418eJohann    }
2541b362b15af34006e6a11974088a46d42b903418eJohann
2551b362b15af34006e6a11974088a46d42b903418eJohann    /*
2561b362b15af34006e6a11974088a46d42b903418eJohann     * Update the default configuration according to needs of the application.
2571b362b15af34006e6a11974088a46d42b903418eJohann     */
2581b362b15af34006e6a11974088a46d42b903418eJohann    /* Highest-resolution encoder settings */
2591b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].g_w = width;
2601b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].g_h = height;
2611b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].g_threads = 1;                           /* number of threads used */
2621b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_dropframe_thresh = 30;
2631b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_end_usage = VPX_CBR;
2641b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_resize_allowed = 0;
2651b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_min_quantizer = 4;
2661b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_max_quantizer = 56;
2671b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_undershoot_pct = 98;
2681b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_overshoot_pct = 100;
2691b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_buf_initial_sz = 500;
2701b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_buf_optimal_sz = 600;
2711b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_buf_sz = 1000;
2721b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].g_error_resilient = 1;              /* Enable error resilient mode */
2731b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].g_lag_in_frames   = 0;
2741b362b15af34006e6a11974088a46d42b903418eJohann
2751b362b15af34006e6a11974088a46d42b903418eJohann    /* Disable automatic keyframe placement */
2761b362b15af34006e6a11974088a46d42b903418eJohann    /* Note: These 3 settings are copied to all levels. But, except the lowest
2771b362b15af34006e6a11974088a46d42b903418eJohann     * resolution level, all other levels are set to VPX_KF_DISABLED internally.
2781b362b15af34006e6a11974088a46d42b903418eJohann     */
2791b362b15af34006e6a11974088a46d42b903418eJohann    //cfg[0].kf_mode           = VPX_KF_DISABLED;
2801b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].kf_mode           = VPX_KF_AUTO;
2811b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].kf_min_dist = 3000;
2821b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].kf_max_dist = 3000;
2831b362b15af34006e6a11974088a46d42b903418eJohann
2841b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].rc_target_bitrate = target_bitrate[0];       /* Set target bitrate */
2851b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].g_timebase.num = 1;                          /* Set fps */
2861b362b15af34006e6a11974088a46d42b903418eJohann    cfg[0].g_timebase.den = framerate;
2871b362b15af34006e6a11974088a46d42b903418eJohann
2881b362b15af34006e6a11974088a46d42b903418eJohann    /* Other-resolution encoder settings */
2891b362b15af34006e6a11974088a46d42b903418eJohann    for (i=1; i< NUM_ENCODERS; i++)
2901b362b15af34006e6a11974088a46d42b903418eJohann    {
2911b362b15af34006e6a11974088a46d42b903418eJohann        memcpy(&cfg[i], &cfg[0], sizeof(vpx_codec_enc_cfg_t));
2921b362b15af34006e6a11974088a46d42b903418eJohann
2931b362b15af34006e6a11974088a46d42b903418eJohann        cfg[i].g_threads = 1;                       /* number of threads used */
2941b362b15af34006e6a11974088a46d42b903418eJohann        cfg[i].rc_target_bitrate = target_bitrate[i];
2951b362b15af34006e6a11974088a46d42b903418eJohann
2961b362b15af34006e6a11974088a46d42b903418eJohann        /* Note: Width & height of other-resolution encoders are calculated
2971b362b15af34006e6a11974088a46d42b903418eJohann         * from the highest-resolution encoder's size and the corresponding
2981b362b15af34006e6a11974088a46d42b903418eJohann         * down_sampling_factor.
2991b362b15af34006e6a11974088a46d42b903418eJohann         */
3001b362b15af34006e6a11974088a46d42b903418eJohann        {
3011b362b15af34006e6a11974088a46d42b903418eJohann            unsigned int iw = cfg[i-1].g_w*dsf[i-1].den + dsf[i-1].num - 1;
3021b362b15af34006e6a11974088a46d42b903418eJohann            unsigned int ih = cfg[i-1].g_h*dsf[i-1].den + dsf[i-1].num - 1;
3031b362b15af34006e6a11974088a46d42b903418eJohann            cfg[i].g_w = iw/dsf[i-1].num;
3041b362b15af34006e6a11974088a46d42b903418eJohann            cfg[i].g_h = ih/dsf[i-1].num;
3051b362b15af34006e6a11974088a46d42b903418eJohann        }
3061b362b15af34006e6a11974088a46d42b903418eJohann
3071b362b15af34006e6a11974088a46d42b903418eJohann        /* Make width & height to be multiplier of 2. */
3081b362b15af34006e6a11974088a46d42b903418eJohann        // Should support odd size ???
3091b362b15af34006e6a11974088a46d42b903418eJohann        if((cfg[i].g_w)%2)cfg[i].g_w++;
3101b362b15af34006e6a11974088a46d42b903418eJohann        if((cfg[i].g_h)%2)cfg[i].g_h++;
3111b362b15af34006e6a11974088a46d42b903418eJohann    }
3121b362b15af34006e6a11974088a46d42b903418eJohann
3131b362b15af34006e6a11974088a46d42b903418eJohann    /* Allocate image for each encoder */
3141b362b15af34006e6a11974088a46d42b903418eJohann    for (i=0; i< NUM_ENCODERS; i++)
3151b362b15af34006e6a11974088a46d42b903418eJohann        if(!vpx_img_alloc(&raw[i], VPX_IMG_FMT_I420, cfg[i].g_w, cfg[i].g_h, 32))
3161b362b15af34006e6a11974088a46d42b903418eJohann            die("Failed to allocate image", cfg[i].g_w, cfg[i].g_h);
3171b362b15af34006e6a11974088a46d42b903418eJohann
3181b362b15af34006e6a11974088a46d42b903418eJohann    if (raw[0].stride[VPX_PLANE_Y] == raw[0].d_w)
3191b362b15af34006e6a11974088a46d42b903418eJohann        read_frame_p = read_frame;
3201b362b15af34006e6a11974088a46d42b903418eJohann    else
3211b362b15af34006e6a11974088a46d42b903418eJohann        read_frame_p = read_frame_by_row;
3221b362b15af34006e6a11974088a46d42b903418eJohann
3231b362b15af34006e6a11974088a46d42b903418eJohann    for (i=0; i< NUM_ENCODERS; i++)
3241b362b15af34006e6a11974088a46d42b903418eJohann        if(outfile[i])
3251b362b15af34006e6a11974088a46d42b903418eJohann            write_ivf_file_header(outfile[i], &cfg[i], 0);
3261b362b15af34006e6a11974088a46d42b903418eJohann
3271b362b15af34006e6a11974088a46d42b903418eJohann    /* Initialize multi-encoder */
3281b362b15af34006e6a11974088a46d42b903418eJohann    if(vpx_codec_enc_init_multi(&codec[0], interface, &cfg[0], NUM_ENCODERS,
3291b362b15af34006e6a11974088a46d42b903418eJohann                                (show_psnr ? VPX_CODEC_USE_PSNR : 0), &dsf[0]))
3301b362b15af34006e6a11974088a46d42b903418eJohann        die_codec(&codec[0], "Failed to initialize encoder");
3311b362b15af34006e6a11974088a46d42b903418eJohann
3321b362b15af34006e6a11974088a46d42b903418eJohann    /* The extra encoding configuration parameters can be set as follows. */
3331b362b15af34006e6a11974088a46d42b903418eJohann    /* Set encoding speed */
3341b362b15af34006e6a11974088a46d42b903418eJohann    for ( i=0; i<NUM_ENCODERS; i++)
3351b362b15af34006e6a11974088a46d42b903418eJohann    {
3361b362b15af34006e6a11974088a46d42b903418eJohann        int speed = -6;
3371b362b15af34006e6a11974088a46d42b903418eJohann        if(vpx_codec_control(&codec[i], VP8E_SET_CPUUSED, speed))
3381b362b15af34006e6a11974088a46d42b903418eJohann            die_codec(&codec[i], "Failed to set cpu_used");
3391b362b15af34006e6a11974088a46d42b903418eJohann    }
340ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
341ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    /* Set static threshold. */
342ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for ( i=0; i<NUM_ENCODERS; i++)
3431b362b15af34006e6a11974088a46d42b903418eJohann    {
344ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        unsigned int static_thresh = 1;
3451b362b15af34006e6a11974088a46d42b903418eJohann        if(vpx_codec_control(&codec[i], VP8E_SET_STATIC_THRESHOLD, static_thresh))
3461b362b15af34006e6a11974088a46d42b903418eJohann            die_codec(&codec[i], "Failed to set static threshold");
3471b362b15af34006e6a11974088a46d42b903418eJohann    }
348ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3491b362b15af34006e6a11974088a46d42b903418eJohann    /* Set NOISE_SENSITIVITY to do TEMPORAL_DENOISING */
350ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    /* Enable denoising for the highest-resolution encoder. */
351ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if(vpx_codec_control(&codec[0], VP8E_SET_NOISE_SENSITIVITY, 1))
352ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        die_codec(&codec[0], "Failed to set noise_sensitivity");
353ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for ( i=1; i< NUM_ENCODERS; i++)
3541b362b15af34006e6a11974088a46d42b903418eJohann    {
3551b362b15af34006e6a11974088a46d42b903418eJohann        if(vpx_codec_control(&codec[i], VP8E_SET_NOISE_SENSITIVITY, 0))
3561b362b15af34006e6a11974088a46d42b903418eJohann            die_codec(&codec[i], "Failed to set noise_sensitivity");
3571b362b15af34006e6a11974088a46d42b903418eJohann    }
3581b362b15af34006e6a11974088a46d42b903418eJohann
359ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3601b362b15af34006e6a11974088a46d42b903418eJohann    frame_avail = 1;
3611b362b15af34006e6a11974088a46d42b903418eJohann    got_data = 0;
3621b362b15af34006e6a11974088a46d42b903418eJohann
3631b362b15af34006e6a11974088a46d42b903418eJohann    while(frame_avail || got_data)
3641b362b15af34006e6a11974088a46d42b903418eJohann    {
3651b362b15af34006e6a11974088a46d42b903418eJohann        vpx_codec_iter_t iter[NUM_ENCODERS]={NULL};
3661b362b15af34006e6a11974088a46d42b903418eJohann        const vpx_codec_cx_pkt_t *pkt[NUM_ENCODERS];
3671b362b15af34006e6a11974088a46d42b903418eJohann
3681b362b15af34006e6a11974088a46d42b903418eJohann        flags = 0;
3691b362b15af34006e6a11974088a46d42b903418eJohann        frame_avail = read_frame_p(infile, &raw[0]);
3701b362b15af34006e6a11974088a46d42b903418eJohann
3711b362b15af34006e6a11974088a46d42b903418eJohann        if(frame_avail)
3721b362b15af34006e6a11974088a46d42b903418eJohann        {
3731b362b15af34006e6a11974088a46d42b903418eJohann            for ( i=1; i<NUM_ENCODERS; i++)
3741b362b15af34006e6a11974088a46d42b903418eJohann            {
3751b362b15af34006e6a11974088a46d42b903418eJohann                /*Scale the image down a number of times by downsampling factor*/
3761b362b15af34006e6a11974088a46d42b903418eJohann                /* FilterMode 1 or 2 give better psnr than FilterMode 0. */
3771b362b15af34006e6a11974088a46d42b903418eJohann                I420Scale(raw[i-1].planes[VPX_PLANE_Y], raw[i-1].stride[VPX_PLANE_Y],
3781b362b15af34006e6a11974088a46d42b903418eJohann                          raw[i-1].planes[VPX_PLANE_U], raw[i-1].stride[VPX_PLANE_U],
3791b362b15af34006e6a11974088a46d42b903418eJohann                          raw[i-1].planes[VPX_PLANE_V], raw[i-1].stride[VPX_PLANE_V],
3801b362b15af34006e6a11974088a46d42b903418eJohann                          raw[i-1].d_w, raw[i-1].d_h,
3811b362b15af34006e6a11974088a46d42b903418eJohann                          raw[i].planes[VPX_PLANE_Y], raw[i].stride[VPX_PLANE_Y],
3821b362b15af34006e6a11974088a46d42b903418eJohann                          raw[i].planes[VPX_PLANE_U], raw[i].stride[VPX_PLANE_U],
3831b362b15af34006e6a11974088a46d42b903418eJohann                          raw[i].planes[VPX_PLANE_V], raw[i].stride[VPX_PLANE_V],
3841b362b15af34006e6a11974088a46d42b903418eJohann                          raw[i].d_w, raw[i].d_h, 1);
3851b362b15af34006e6a11974088a46d42b903418eJohann            }
3861b362b15af34006e6a11974088a46d42b903418eJohann        }
3871b362b15af34006e6a11974088a46d42b903418eJohann
3881b362b15af34006e6a11974088a46d42b903418eJohann        /* Encode each frame at multi-levels */
3891b362b15af34006e6a11974088a46d42b903418eJohann        if(vpx_codec_encode(&codec[0], frame_avail? &raw[0] : NULL,
3901b362b15af34006e6a11974088a46d42b903418eJohann            frame_cnt, 1, flags, arg_deadline))
3911b362b15af34006e6a11974088a46d42b903418eJohann            die_codec(&codec[0], "Failed to encode frame");
3921b362b15af34006e6a11974088a46d42b903418eJohann
3931b362b15af34006e6a11974088a46d42b903418eJohann        for (i=NUM_ENCODERS-1; i>=0 ; i--)
3941b362b15af34006e6a11974088a46d42b903418eJohann        {
3951b362b15af34006e6a11974088a46d42b903418eJohann            got_data = 0;
3961b362b15af34006e6a11974088a46d42b903418eJohann
3971b362b15af34006e6a11974088a46d42b903418eJohann            while( (pkt[i] = vpx_codec_get_cx_data(&codec[i], &iter[i])) )
3981b362b15af34006e6a11974088a46d42b903418eJohann            {
3991b362b15af34006e6a11974088a46d42b903418eJohann                got_data = 1;
4001b362b15af34006e6a11974088a46d42b903418eJohann                switch(pkt[i]->kind) {
4011b362b15af34006e6a11974088a46d42b903418eJohann                    case VPX_CODEC_CX_FRAME_PKT:
4021b362b15af34006e6a11974088a46d42b903418eJohann                        write_ivf_frame_header(outfile[i], pkt[i]);
4031b362b15af34006e6a11974088a46d42b903418eJohann                        (void) fwrite(pkt[i]->data.frame.buf, 1,
4041b362b15af34006e6a11974088a46d42b903418eJohann                                      pkt[i]->data.frame.sz, outfile[i]);
4051b362b15af34006e6a11974088a46d42b903418eJohann                    break;
4061b362b15af34006e6a11974088a46d42b903418eJohann                    case VPX_CODEC_PSNR_PKT:
4071b362b15af34006e6a11974088a46d42b903418eJohann                        if (show_psnr)
4081b362b15af34006e6a11974088a46d42b903418eJohann                        {
4091b362b15af34006e6a11974088a46d42b903418eJohann                            int j;
4101b362b15af34006e6a11974088a46d42b903418eJohann
4111b362b15af34006e6a11974088a46d42b903418eJohann                            psnr_sse_total[i] += pkt[i]->data.psnr.sse[0];
4121b362b15af34006e6a11974088a46d42b903418eJohann                            psnr_samples_total[i] += pkt[i]->data.psnr.samples[0];
4131b362b15af34006e6a11974088a46d42b903418eJohann                            for (j = 0; j < 4; j++)
4141b362b15af34006e6a11974088a46d42b903418eJohann                            {
4151b362b15af34006e6a11974088a46d42b903418eJohann                                //fprintf(stderr, "%.3lf ", pkt[i]->data.psnr.psnr[j]);
4161b362b15af34006e6a11974088a46d42b903418eJohann                                psnr_totals[i][j] += pkt[i]->data.psnr.psnr[j];
4171b362b15af34006e6a11974088a46d42b903418eJohann                            }
4181b362b15af34006e6a11974088a46d42b903418eJohann                            psnr_count[i]++;
4191b362b15af34006e6a11974088a46d42b903418eJohann                        }
4201b362b15af34006e6a11974088a46d42b903418eJohann
4211b362b15af34006e6a11974088a46d42b903418eJohann                        break;
4221b362b15af34006e6a11974088a46d42b903418eJohann                    default:
4231b362b15af34006e6a11974088a46d42b903418eJohann                        break;
4241b362b15af34006e6a11974088a46d42b903418eJohann                }
4251b362b15af34006e6a11974088a46d42b903418eJohann                printf(pkt[i]->kind == VPX_CODEC_CX_FRAME_PKT
4261b362b15af34006e6a11974088a46d42b903418eJohann                       && (pkt[i]->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
4271b362b15af34006e6a11974088a46d42b903418eJohann                fflush(stdout);
4281b362b15af34006e6a11974088a46d42b903418eJohann            }
4291b362b15af34006e6a11974088a46d42b903418eJohann        }
4301b362b15af34006e6a11974088a46d42b903418eJohann        frame_cnt++;
4311b362b15af34006e6a11974088a46d42b903418eJohann    }
4321b362b15af34006e6a11974088a46d42b903418eJohann    printf("\n");
4331b362b15af34006e6a11974088a46d42b903418eJohann
4341b362b15af34006e6a11974088a46d42b903418eJohann    fclose(infile);
4351b362b15af34006e6a11974088a46d42b903418eJohann
4361b362b15af34006e6a11974088a46d42b903418eJohann    printf("Processed %ld frames.\n",(long int)frame_cnt-1);
4371b362b15af34006e6a11974088a46d42b903418eJohann    for (i=0; i< NUM_ENCODERS; i++)
4381b362b15af34006e6a11974088a46d42b903418eJohann    {
4391b362b15af34006e6a11974088a46d42b903418eJohann        /* Calculate PSNR and print it out */
4401b362b15af34006e6a11974088a46d42b903418eJohann        if ( (show_psnr) && (psnr_count[i]>0) )
4411b362b15af34006e6a11974088a46d42b903418eJohann        {
4421b362b15af34006e6a11974088a46d42b903418eJohann            int j;
443b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            double ovpsnr = sse_to_psnr(psnr_samples_total[i], 255.0,
444b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                                        psnr_sse_total[i]);
4451b362b15af34006e6a11974088a46d42b903418eJohann
4461b362b15af34006e6a11974088a46d42b903418eJohann            fprintf(stderr, "\n ENC%d PSNR (Overall/Avg/Y/U/V)", i);
4471b362b15af34006e6a11974088a46d42b903418eJohann
4481b362b15af34006e6a11974088a46d42b903418eJohann            fprintf(stderr, " %.3lf", ovpsnr);
4491b362b15af34006e6a11974088a46d42b903418eJohann            for (j = 0; j < 4; j++)
4501b362b15af34006e6a11974088a46d42b903418eJohann            {
4511b362b15af34006e6a11974088a46d42b903418eJohann                fprintf(stderr, " %.3lf", psnr_totals[i][j]/psnr_count[i]);
4521b362b15af34006e6a11974088a46d42b903418eJohann            }
4531b362b15af34006e6a11974088a46d42b903418eJohann        }
4541b362b15af34006e6a11974088a46d42b903418eJohann
4551b362b15af34006e6a11974088a46d42b903418eJohann        if(vpx_codec_destroy(&codec[i]))
4561b362b15af34006e6a11974088a46d42b903418eJohann            die_codec(&codec[i], "Failed to destroy codec");
4571b362b15af34006e6a11974088a46d42b903418eJohann
4581b362b15af34006e6a11974088a46d42b903418eJohann        vpx_img_free(&raw[i]);
4591b362b15af34006e6a11974088a46d42b903418eJohann
4601b362b15af34006e6a11974088a46d42b903418eJohann        if(!outfile[i])
4611b362b15af34006e6a11974088a46d42b903418eJohann            continue;
4621b362b15af34006e6a11974088a46d42b903418eJohann
4631b362b15af34006e6a11974088a46d42b903418eJohann        /* Try to rewrite the file header with the actual frame count */
4641b362b15af34006e6a11974088a46d42b903418eJohann        if(!fseek(outfile[i], 0, SEEK_SET))
4651b362b15af34006e6a11974088a46d42b903418eJohann            write_ivf_file_header(outfile[i], &cfg[i], frame_cnt-1);
4661b362b15af34006e6a11974088a46d42b903418eJohann        fclose(outfile[i]);
4671b362b15af34006e6a11974088a46d42b903418eJohann    }
4681b362b15af34006e6a11974088a46d42b903418eJohann    printf("\n");
4691b362b15af34006e6a11974088a46d42b903418eJohann
4701b362b15af34006e6a11974088a46d42b903418eJohann    return EXIT_SUCCESS;
4711b362b15af34006e6a11974088a46d42b903418eJohann}
472