Home | History | Annotate | Download | only in libvpx
      1 /*
      2  *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 
     12 /*
     13  * This is an example demonstrating how to implement a multi-layer VP8
     14  * encoding scheme based on temporal scalability for video applications
     15  * that benefit from a scalable bitstream.
     16  */
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <stdarg.h>
     20 #include <string.h>
     21 #define VPX_CODEC_DISABLE_COMPAT 1
     22 #include "vpx/vpx_encoder.h"
     23 #include "vpx/vp8cx.h"
     24 #define interface (vpx_codec_vp8_cx())
     25 #define fourcc    0x30385056
     26 
     27 #define IVF_FILE_HDR_SZ  (32)
     28 #define IVF_FRAME_HDR_SZ (12)
     29 
     30 static void mem_put_le16(char *mem, unsigned int val) {
     31     mem[0] = val;
     32     mem[1] = val>>8;
     33 }
     34 
     35 static void mem_put_le32(char *mem, unsigned int val) {
     36     mem[0] = val;
     37     mem[1] = val>>8;
     38     mem[2] = val>>16;
     39     mem[3] = val>>24;
     40 }
     41 
     42 static void die(const char *fmt, ...) {
     43     va_list ap;
     44 
     45     va_start(ap, fmt);
     46     vprintf(fmt, ap);
     47     if(fmt[strlen(fmt)-1] != '\n')
     48         printf("\n");
     49     exit(EXIT_FAILURE);
     50 }
     51 
     52 static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
     53     const char *detail = vpx_codec_error_detail(ctx);
     54 
     55     printf("%s: %s\n", s, vpx_codec_error(ctx));
     56     if(detail)
     57         printf("    %s\n",detail);
     58     exit(EXIT_FAILURE);
     59 }
     60 
     61 static int read_frame(FILE *f, vpx_image_t *img) {
     62     size_t nbytes, to_read;
     63     int    res = 1;
     64 
     65     to_read = img->w*img->h*3/2;
     66     nbytes = fread(img->planes[0], 1, to_read, f);
     67     if(nbytes != to_read) {
     68         res = 0;
     69         if(nbytes > 0)
     70             printf("Warning: Read partial frame. Check your width & height!\n");
     71     }
     72     return res;
     73 }
     74 
     75 static void write_ivf_file_header(FILE *outfile,
     76                                   const vpx_codec_enc_cfg_t *cfg,
     77                                   int frame_cnt) {
     78     char header[32];
     79 
     80     if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
     81         return;
     82     header[0] = 'D';
     83     header[1] = 'K';
     84     header[2] = 'I';
     85     header[3] = 'F';
     86     mem_put_le16(header+4,  0);                   /* version */
     87     mem_put_le16(header+6,  32);                  /* headersize */
     88     mem_put_le32(header+8,  fourcc);              /* headersize */
     89     mem_put_le16(header+12, cfg->g_w);            /* width */
     90     mem_put_le16(header+14, cfg->g_h);            /* height */
     91     mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
     92     mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
     93     mem_put_le32(header+24, frame_cnt);           /* length */
     94     mem_put_le32(header+28, 0);                   /* unused */
     95 
     96     (void) fwrite(header, 1, 32, outfile);
     97 }
     98 
     99 
    100 static void write_ivf_frame_header(FILE *outfile,
    101                                    const vpx_codec_cx_pkt_t *pkt)
    102 {
    103     char             header[12];
    104     vpx_codec_pts_t  pts;
    105 
    106     if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
    107         return;
    108 
    109     pts = pkt->data.frame.pts;
    110     mem_put_le32(header, pkt->data.frame.sz);
    111     mem_put_le32(header+4, pts&0xFFFFFFFF);
    112     mem_put_le32(header+8, pts >> 32);
    113 
    114     (void) fwrite(header, 1, 12, outfile);
    115 }
    116 
    117 static int mode_to_num_layers[12] = {1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3};
    118 
    119 int main(int argc, char **argv) {
    120     FILE                *infile, *outfile[VPX_TS_MAX_LAYERS];
    121     vpx_codec_ctx_t      codec;
    122     vpx_codec_enc_cfg_t  cfg;
    123     int                  frame_cnt = 0;
    124     vpx_image_t          raw;
    125     vpx_codec_err_t      res;
    126     unsigned int         width;
    127     unsigned int         height;
    128     int                  frame_avail;
    129     int                  got_data;
    130     int                  flags = 0;
    131     int                  i;
    132     int                  pts = 0;              /* PTS starts at 0 */
    133     int                  frame_duration = 1;   /* 1 timebase tick per frame */
    134 
    135     int                  layering_mode = 0;
    136     int                  frames_in_layer[VPX_TS_MAX_LAYERS] = {0};
    137     int                  layer_flags[VPX_TS_MAX_PERIODICITY] = {0};
    138     int                  flag_periodicity;
    139     int                  max_intra_size_pct;
    140 
    141     /* Check usage and arguments */
    142     if (argc < 9)
    143         die("Usage: %s <infile> <outfile> <width> <height> <rate_num> "
    144             " <rate_den> <mode> <Rate_0> ... <Rate_nlayers-1>\n", argv[0]);
    145 
    146     width  = strtol (argv[3], NULL, 0);
    147     height = strtol (argv[4], NULL, 0);
    148     if (width < 16 || width%2 || height <16 || height%2)
    149         die ("Invalid resolution: %d x %d", width, height);
    150 
    151     if (!sscanf(argv[7], "%d", &layering_mode))
    152         die ("Invalid mode %s", argv[7]);
    153     if (layering_mode<0 || layering_mode>11)
    154         die ("Invalid mode (0..11) %s", argv[7]);
    155 
    156     if (argc != 8+mode_to_num_layers[layering_mode])
    157         die ("Invalid number of arguments");
    158 
    159     if (!vpx_img_alloc (&raw, VPX_IMG_FMT_I420, width, height, 32))
    160         die ("Failed to allocate image", width, height);
    161 
    162     printf("Using %s\n",vpx_codec_iface_name(interface));
    163 
    164     /* Populate encoder configuration */
    165     res = vpx_codec_enc_config_default(interface, &cfg, 0);
    166     if(res) {
    167         printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
    168         return EXIT_FAILURE;
    169     }
    170 
    171     /* Update the default configuration with our settings */
    172     cfg.g_w = width;
    173     cfg.g_h = height;
    174 
    175     /* Timebase format e.g. 30fps: numerator=1, demoninator=30 */
    176     if (!sscanf (argv[5], "%d", &cfg.g_timebase.num ))
    177         die ("Invalid timebase numerator %s", argv[5]);
    178     if (!sscanf (argv[6], "%d", &cfg.g_timebase.den ))
    179         die ("Invalid timebase denominator %s", argv[6]);
    180 
    181     for (i=8; i<8+mode_to_num_layers[layering_mode]; i++)
    182         if (!sscanf(argv[i], "%ud", &cfg.ts_target_bitrate[i-8]))
    183             die ("Invalid data rate %s", argv[i]);
    184 
    185     /* Real time parameters */
    186     cfg.rc_dropframe_thresh = 0;
    187     cfg.rc_end_usage        = VPX_CBR;
    188     cfg.rc_resize_allowed   = 0;
    189     cfg.rc_min_quantizer    = 2;
    190     cfg.rc_max_quantizer    = 56;
    191     cfg.rc_undershoot_pct   = 100;
    192     cfg.rc_overshoot_pct    = 15;
    193     cfg.rc_buf_initial_sz   = 500;
    194     cfg.rc_buf_optimal_sz   = 600;
    195     cfg.rc_buf_sz           = 1000;
    196 
    197     /* Enable error resilient mode */
    198     cfg.g_error_resilient = 1;
    199     cfg.g_lag_in_frames   = 0;
    200     cfg.kf_mode           = VPX_KF_DISABLED;
    201 
    202     /* Disable automatic keyframe placement */
    203     cfg.kf_min_dist = cfg.kf_max_dist = 3000;
    204 
    205     /* Default setting for bitrate: used in special case of 1 layer (case 0). */
    206     cfg.rc_target_bitrate = cfg.ts_target_bitrate[0];
    207 
    208     /* Temporal scaling parameters: */
    209     /* NOTE: The 3 prediction frames cannot be used interchangeably due to
    210      * differences in the way they are handled throughout the code. The
    211      * frames should be allocated to layers in the order LAST, GF, ARF.
    212      * Other combinations work, but may produce slightly inferior results.
    213      */
    214     switch (layering_mode)
    215     {
    216     case 0:
    217     {
    218         /* 1-layer */
    219        int ids[1] = {0};
    220        cfg.ts_number_layers     = 1;
    221        cfg.ts_periodicity       = 1;
    222        cfg.ts_rate_decimator[0] = 1;
    223        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    224 
    225        flag_periodicity = cfg.ts_periodicity;
    226 
    227        // Update L only.
    228        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    229                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
    230        break;
    231     }
    232     case 1:
    233     {
    234         /* 2-layers, 2-frame period */
    235         int ids[2] = {0,1};
    236         cfg.ts_number_layers     = 2;
    237         cfg.ts_periodicity       = 2;
    238         cfg.ts_rate_decimator[0] = 2;
    239         cfg.ts_rate_decimator[1] = 1;
    240         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    241 
    242         flag_periodicity = cfg.ts_periodicity;
    243 #if 1
    244         /* 0=L, 1=GF, Intra-layer prediction enabled */
    245         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    246                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
    247                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
    248         layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
    249                          VP8_EFLAG_NO_REF_ARF;
    250 #else
    251         /* 0=L, 1=GF, Intra-layer prediction disabled */
    252         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    253                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
    254                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
    255         layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
    256                          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST;
    257 #endif
    258         break;
    259     }
    260 
    261     case 2:
    262     {
    263         /* 2-layers, 3-frame period */
    264         int ids[3] = {0,1,1};
    265         cfg.ts_number_layers     = 2;
    266         cfg.ts_periodicity       = 3;
    267         cfg.ts_rate_decimator[0] = 3;
    268         cfg.ts_rate_decimator[1] = 1;
    269         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    270 
    271         flag_periodicity = cfg.ts_periodicity;
    272 
    273         /* 0=L, 1=GF, Intra-layer prediction enabled */
    274         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    275                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
    276                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
    277         layer_flags[1] =
    278         layer_flags[2] = VP8_EFLAG_NO_REF_GF  |
    279                          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
    280                                                 VP8_EFLAG_NO_UPD_LAST;
    281         break;
    282     }
    283 
    284     case 3:
    285     {
    286         /* 3-layers, 6-frame period */
    287         int ids[6] = {0,2,2,1,2,2};
    288         cfg.ts_number_layers     = 3;
    289         cfg.ts_periodicity       = 6;
    290         cfg.ts_rate_decimator[0] = 6;
    291         cfg.ts_rate_decimator[1] = 3;
    292         cfg.ts_rate_decimator[2] = 1;
    293         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    294 
    295         flag_periodicity = cfg.ts_periodicity;
    296 
    297         /* 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled */
    298         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    299                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
    300                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
    301         layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
    302                                                 VP8_EFLAG_NO_UPD_LAST;
    303         layer_flags[1] =
    304         layer_flags[2] =
    305         layer_flags[4] =
    306         layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
    307         break;
    308     }
    309 
    310     case 4:
    311     {
    312         /* 3-layers, 4-frame period */
    313         int ids[4] = {0,2,1,2};
    314         cfg.ts_number_layers     = 3;
    315         cfg.ts_periodicity       = 4;
    316         cfg.ts_rate_decimator[0] = 4;
    317         cfg.ts_rate_decimator[1] = 2;
    318         cfg.ts_rate_decimator[2] = 1;
    319         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    320 
    321         flag_periodicity = cfg.ts_periodicity;
    322 
    323         /* 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled */
    324         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    325                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
    326                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
    327         layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
    328                          VP8_EFLAG_NO_UPD_ARF |
    329                          VP8_EFLAG_NO_UPD_LAST;
    330         layer_flags[1] =
    331         layer_flags[3] = VP8_EFLAG_NO_REF_ARF |
    332                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
    333                          VP8_EFLAG_NO_UPD_ARF;
    334         break;
    335     }
    336 
    337     case 5:
    338     {
    339         /* 3-layers, 4-frame period */
    340         int ids[4] = {0,2,1,2};
    341         cfg.ts_number_layers     = 3;
    342         cfg.ts_periodicity       = 4;
    343         cfg.ts_rate_decimator[0] = 4;
    344         cfg.ts_rate_decimator[1] = 2;
    345         cfg.ts_rate_decimator[2] = 1;
    346         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    347 
    348         flag_periodicity = cfg.ts_periodicity;
    349 
    350         /* 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1,
    351          * disabled in layer 2
    352          */
    353         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    354                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
    355                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
    356         layer_flags[2] = VP8_EFLAG_NO_REF_ARF |
    357                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
    358         layer_flags[1] =
    359         layer_flags[3] = VP8_EFLAG_NO_REF_ARF |
    360                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
    361                          VP8_EFLAG_NO_UPD_ARF;
    362         break;
    363     }
    364 
    365     case 6:
    366     {
    367         /* 3-layers, 4-frame period */
    368         int ids[4] = {0,2,1,2};
    369         cfg.ts_number_layers     = 3;
    370         cfg.ts_periodicity       = 4;
    371         cfg.ts_rate_decimator[0] = 4;
    372         cfg.ts_rate_decimator[1] = 2;
    373         cfg.ts_rate_decimator[2] = 1;
    374         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    375 
    376         flag_periodicity = cfg.ts_periodicity;
    377 
    378         /* 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled */
    379         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    380                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
    381                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
    382         layer_flags[2] = VP8_EFLAG_NO_REF_ARF |
    383                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
    384         layer_flags[1] =
    385         layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
    386         break;
    387     }
    388 
    389     case 7:
    390     {
    391         /* NOTE: Probably of academic interest only */
    392 
    393         /* 5-layers, 16-frame period */
    394         int ids[16] = {0,4,3,4,2,4,3,4,1,4,3,4,2,4,3,4};
    395         cfg.ts_number_layers     = 5;
    396         cfg.ts_periodicity       = 16;
    397         cfg.ts_rate_decimator[0] = 16;
    398         cfg.ts_rate_decimator[1] = 8;
    399         cfg.ts_rate_decimator[2] = 4;
    400         cfg.ts_rate_decimator[3] = 2;
    401         cfg.ts_rate_decimator[4] = 1;
    402         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    403 
    404         flag_periodicity = cfg.ts_periodicity;
    405 
    406         layer_flags[0]  = VPX_EFLAG_FORCE_KF;
    407         layer_flags[1]  =
    408         layer_flags[3]  =
    409         layer_flags[5]  =
    410         layer_flags[7]  =
    411         layer_flags[9]  =
    412         layer_flags[11] =
    413         layer_flags[13] =
    414         layer_flags[15] = VP8_EFLAG_NO_UPD_LAST |
    415                           VP8_EFLAG_NO_UPD_GF   |
    416                           VP8_EFLAG_NO_UPD_ARF;
    417         layer_flags[2]  =
    418         layer_flags[6]  =
    419         layer_flags[10] =
    420         layer_flags[14] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF;
    421         layer_flags[4]  =
    422         layer_flags[12] = VP8_EFLAG_NO_REF_LAST |
    423                           VP8_EFLAG_NO_UPD_ARF;
    424         layer_flags[8]  = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF;
    425         break;
    426     }
    427 
    428     case 8:
    429     {
    430         /* 2-layers, with sync point at first frame of layer 1. */
    431         int ids[2] = {0,1};
    432         cfg.ts_number_layers     = 2;
    433         cfg.ts_periodicity       = 2;
    434         cfg.ts_rate_decimator[0] = 2;
    435         cfg.ts_rate_decimator[1] = 1;
    436         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    437 
    438         flag_periodicity = 8;
    439 
    440         /* 0=L, 1=GF */
    441         // ARF is used as predictor for all frames, and is only updated on
    442         // key frame. Sync point every 8 frames.
    443 
    444         // Layer 0: predict from L and ARF, update L and G.
    445         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    446                          VP8_EFLAG_NO_REF_GF |
    447                          VP8_EFLAG_NO_UPD_ARF;
    448 
    449         // Layer 1: sync point: predict from L and ARF, and update G.
    450         layer_flags[1] = VP8_EFLAG_NO_REF_GF |
    451                          VP8_EFLAG_NO_UPD_LAST |
    452                          VP8_EFLAG_NO_UPD_ARF;
    453 
    454         // Layer 0, predict from L and ARF, update L.
    455         layer_flags[2] = VP8_EFLAG_NO_REF_GF  |
    456                          VP8_EFLAG_NO_UPD_GF  |
    457                          VP8_EFLAG_NO_UPD_ARF;
    458 
    459         // Layer 1: predict from L, G and ARF, and update G.
    460         layer_flags[3] = VP8_EFLAG_NO_UPD_ARF |
    461                          VP8_EFLAG_NO_UPD_LAST |
    462                          VP8_EFLAG_NO_UPD_ENTROPY;
    463 
    464         // Layer 0
    465         layer_flags[4] = layer_flags[2];
    466 
    467         // Layer 1
    468         layer_flags[5] = layer_flags[3];
    469 
    470         // Layer 0
    471         layer_flags[6] = layer_flags[4];
    472 
    473         // Layer 1
    474         layer_flags[7] = layer_flags[5];
    475         break;
    476     }
    477 
    478     case 9:
    479     {
    480         /* 3-layers */
    481         // Sync points for layer 1 and 2 every 8 frames.
    482 
    483         int ids[4] = {0,2,1,2};
    484         cfg.ts_number_layers     = 3;
    485         cfg.ts_periodicity       = 4;
    486         cfg.ts_rate_decimator[0] = 4;
    487         cfg.ts_rate_decimator[1] = 2;
    488         cfg.ts_rate_decimator[2] = 1;
    489         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    490 
    491         flag_periodicity = 8;
    492 
    493         /* 0=L, 1=GF, 2=ARF */
    494         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
    495                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
    496                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
    497         layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
    498                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
    499         layer_flags[2] = VP8_EFLAG_NO_REF_GF   | VP8_EFLAG_NO_REF_ARF |
    500                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
    501         layer_flags[3] =
    502         layer_flags[5] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
    503         layer_flags[4] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
    504                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
    505         layer_flags[6] = VP8_EFLAG_NO_REF_ARF |
    506                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
    507         layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
    508                          VP8_EFLAG_NO_UPD_ARF |
    509                          VP8_EFLAG_NO_UPD_ENTROPY;
    510         break;
    511     }
    512     case 10:
    513     {
    514         // 3-layers structure where ARF is used as predictor for all frames,
    515         // and is only updated on key frame.
    516         // Sync points for layer 1 and 2 every 8 frames.
    517 
    518         int ids[4] = {0,2,1,2};
    519         cfg.ts_number_layers     = 3;
    520         cfg.ts_periodicity       = 4;
    521         cfg.ts_rate_decimator[0] = 4;
    522         cfg.ts_rate_decimator[1] = 2;
    523         cfg.ts_rate_decimator[2] = 1;
    524         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    525 
    526         flag_periodicity = 8;
    527 
    528         /* 0=L, 1=GF, 2=ARF */
    529 
    530         // Layer 0: predict from L and ARF; update L and G.
    531         layer_flags[0] =  VPX_EFLAG_FORCE_KF  |
    532                           VP8_EFLAG_NO_UPD_ARF |
    533                           VP8_EFLAG_NO_REF_GF;
    534 
    535         // Layer 2: sync point: predict from L and ARF; update none.
    536         layer_flags[1] = VP8_EFLAG_NO_REF_GF |
    537                          VP8_EFLAG_NO_UPD_GF |
    538                          VP8_EFLAG_NO_UPD_ARF |
    539                          VP8_EFLAG_NO_UPD_LAST |
    540                          VP8_EFLAG_NO_UPD_ENTROPY;
    541 
    542         // Layer 1: sync point: predict from L and ARF; update G.
    543         layer_flags[2] = VP8_EFLAG_NO_REF_GF |
    544                          VP8_EFLAG_NO_UPD_ARF |
    545                          VP8_EFLAG_NO_UPD_LAST;
    546 
    547         // Layer 2: predict from L, G, ARF; update none.
    548         layer_flags[3] = VP8_EFLAG_NO_UPD_GF |
    549                          VP8_EFLAG_NO_UPD_ARF |
    550                          VP8_EFLAG_NO_UPD_LAST |
    551                          VP8_EFLAG_NO_UPD_ENTROPY;
    552 
    553         // Layer 0: predict from L and ARF; update L.
    554         layer_flags[4] = VP8_EFLAG_NO_UPD_GF |
    555                          VP8_EFLAG_NO_UPD_ARF |
    556                          VP8_EFLAG_NO_REF_GF;
    557 
    558         // Layer 2: predict from L, G, ARF; update none.
    559         layer_flags[5] = layer_flags[3];
    560 
    561         // Layer 1: predict from L, G, ARF; update G.
    562         layer_flags[6] = VP8_EFLAG_NO_UPD_ARF |
    563                          VP8_EFLAG_NO_UPD_LAST;
    564 
    565         // Layer 2: predict from L, G, ARF; update none.
    566         layer_flags[7] = layer_flags[3];
    567         break;
    568     }
    569     case 11:
    570     default:
    571     {
    572        // 3-layers structure as in case 10, but no sync/refresh points for
    573        // layer 1 and 2.
    574 
    575        int ids[4] = {0,2,1,2};
    576        cfg.ts_number_layers     = 3;
    577        cfg.ts_periodicity       = 4;
    578        cfg.ts_rate_decimator[0] = 4;
    579        cfg.ts_rate_decimator[1] = 2;
    580        cfg.ts_rate_decimator[2] = 1;
    581        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
    582 
    583        flag_periodicity = 8;
    584 
    585        /* 0=L, 1=GF, 2=ARF */
    586 
    587        // Layer 0: predict from L and ARF; update L.
    588        layer_flags[0] = VP8_EFLAG_NO_UPD_GF |
    589                         VP8_EFLAG_NO_UPD_ARF |
    590                         VP8_EFLAG_NO_REF_GF;
    591        layer_flags[4] = layer_flags[0];
    592 
    593        // Layer 1: predict from L, G, ARF; update G.
    594        layer_flags[2] = VP8_EFLAG_NO_UPD_ARF |
    595                         VP8_EFLAG_NO_UPD_LAST;
    596        layer_flags[6] = layer_flags[2];
    597 
    598        // Layer 2: predict from L, G, ARF; update none.
    599        layer_flags[1] = VP8_EFLAG_NO_UPD_GF |
    600                         VP8_EFLAG_NO_UPD_ARF |
    601                         VP8_EFLAG_NO_UPD_LAST |
    602                         VP8_EFLAG_NO_UPD_ENTROPY;
    603        layer_flags[3] = layer_flags[1];
    604        layer_flags[5] = layer_flags[1];
    605        layer_flags[7] = layer_flags[1];
    606        break;
    607     }
    608     }
    609 
    610     /* Open input file */
    611     if(!(infile = fopen(argv[1], "rb")))
    612         die("Failed to open %s for reading", argv[1]);
    613 
    614     /* Open an output file for each stream */
    615     for (i=0; i<cfg.ts_number_layers; i++)
    616     {
    617         char file_name[512];
    618         sprintf (file_name, "%s_%d.ivf", argv[2], i);
    619         if (!(outfile[i] = fopen(file_name, "wb")))
    620             die("Failed to open %s for writing", file_name);
    621         write_ivf_file_header(outfile[i], &cfg, 0);
    622     }
    623 
    624     /* Initialize codec */
    625     if (vpx_codec_enc_init (&codec, interface, &cfg, 0))
    626         die_codec (&codec, "Failed to initialize encoder");
    627 
    628     /* Cap CPU & first I-frame size */
    629     vpx_codec_control (&codec, VP8E_SET_CPUUSED,                -6);
    630     vpx_codec_control (&codec, VP8E_SET_STATIC_THRESHOLD,      1);
    631     vpx_codec_control (&codec, VP8E_SET_NOISE_SENSITIVITY,       1);
    632     vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS,       1);
    633 
    634     max_intra_size_pct = (int) (((double)cfg.rc_buf_optimal_sz * 0.5)
    635                          * ((double) cfg.g_timebase.den / cfg.g_timebase.num)
    636                          / 10.0);
    637     /* printf ("max_intra_size_pct=%d\n", max_intra_size_pct); */
    638 
    639     vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT,
    640                       max_intra_size_pct);
    641 
    642     frame_avail = 1;
    643     while (frame_avail || got_data) {
    644         vpx_codec_iter_t iter = NULL;
    645         const vpx_codec_cx_pkt_t *pkt;
    646 
    647         flags = layer_flags[frame_cnt % flag_periodicity];
    648 
    649         frame_avail = read_frame(infile, &raw);
    650         if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts,
    651                             1, flags, VPX_DL_REALTIME))
    652             die_codec(&codec, "Failed to encode frame");
    653 
    654         /* Reset KF flag */
    655         if (layering_mode != 7)
    656             layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
    657 
    658         got_data = 0;
    659         while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
    660             got_data = 1;
    661             switch (pkt->kind) {
    662             case VPX_CODEC_CX_FRAME_PKT:
    663                 for (i=cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
    664                                               i<cfg.ts_number_layers; i++)
    665                 {
    666                     write_ivf_frame_header(outfile[i], pkt);
    667                     (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
    668                                   outfile[i]);
    669                     frames_in_layer[i]++;
    670                 }
    671                 break;
    672             default:
    673                 break;
    674             }
    675         }
    676         frame_cnt++;
    677         pts += frame_duration;
    678     }
    679     fclose (infile);
    680 
    681     printf ("Processed %d frames.\n",frame_cnt-1);
    682     if (vpx_codec_destroy(&codec))
    683             die_codec (&codec, "Failed to destroy codec");
    684 
    685     /* Try to rewrite the output file headers with the actual frame count */
    686     for (i=0; i<cfg.ts_number_layers; i++)
    687     {
    688         if (!fseek(outfile[i], 0, SEEK_SET))
    689             write_ivf_file_header (outfile[i], &cfg, frames_in_layer[i]);
    690         fclose (outfile[i]);
    691     }
    692 
    693     return EXIT_SUCCESS;
    694 }
    695