WebM VP8 Codec SDK
|
00001 /* 00002 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 00003 * 00004 * Use of this source code is governed by a BSD-style license 00005 * that can be found in the LICENSE file in the root of the source 00006 * tree. An additional intellectual property rights grant can be found 00007 * in the file PATENTS. All contributing project authors may 00008 * be found in the AUTHORS file in the root of the source tree. 00009 */ 00010 00011 00012 /* 00013 * This is an example demonstrating how to implement a multi-layer VP8 00014 * encoding scheme based on temporal scalability for video applications 00015 * that benefit from a scalable bitstream. 00016 */ 00017 #include <stdio.h> 00018 #include <stdlib.h> 00019 #include <stdarg.h> 00020 #include <string.h> 00021 #define VPX_CODEC_DISABLE_COMPAT 1 00022 #include "vpx/vpx_encoder.h" 00023 #include "vpx/vp8cx.h" 00024 #define interface (vpx_codec_vp8_cx()) 00025 #define fourcc 0x30385056 00026 00027 #define IVF_FILE_HDR_SZ (32) 00028 #define IVF_FRAME_HDR_SZ (12) 00029 00030 static void mem_put_le16(char *mem, unsigned int val) { 00031 mem[0] = val; 00032 mem[1] = val>>8; 00033 } 00034 00035 static void mem_put_le32(char *mem, unsigned int val) { 00036 mem[0] = val; 00037 mem[1] = val>>8; 00038 mem[2] = val>>16; 00039 mem[3] = val>>24; 00040 } 00041 00042 static void die(const char *fmt, ...) { 00043 va_list ap; 00044 00045 va_start(ap, fmt); 00046 vprintf(fmt, ap); 00047 if(fmt[strlen(fmt)-1] != '\n') 00048 printf("\n"); 00049 exit(EXIT_FAILURE); 00050 } 00051 00052 static void die_codec(vpx_codec_ctx_t *ctx, const char *s) { 00053 const char *detail = vpx_codec_error_detail(ctx); 00054 00055 printf("%s: %s\n", s, vpx_codec_error(ctx)); 00056 if(detail) 00057 printf(" %s\n",detail); 00058 exit(EXIT_FAILURE); 00059 } 00060 00061 static int read_frame(FILE *f, vpx_image_t *img) { 00062 size_t nbytes, to_read; 00063 int res = 1; 00064 00065 to_read = img->w*img->h*3/2; 00066 nbytes = fread(img->planes[0], 1, to_read, f); 00067 if(nbytes != to_read) { 00068 res = 0; 00069 if(nbytes > 0) 00070 printf("Warning: Read partial frame. Check your width & height!\n"); 00071 } 00072 return res; 00073 } 00074 00075 static void write_ivf_file_header(FILE *outfile, 00076 const vpx_codec_enc_cfg_t *cfg, 00077 int frame_cnt) { 00078 char header[32]; 00079 00080 if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS) 00081 return; 00082 header[0] = 'D'; 00083 header[1] = 'K'; 00084 header[2] = 'I'; 00085 header[3] = 'F'; 00086 mem_put_le16(header+4, 0); /* version */ 00087 mem_put_le16(header+6, 32); /* headersize */ 00088 mem_put_le32(header+8, fourcc); /* headersize */ 00089 mem_put_le16(header+12, cfg->g_w); /* width */ 00090 mem_put_le16(header+14, cfg->g_h); /* height */ 00091 mem_put_le32(header+16, cfg->g_timebase.den); /* rate */ 00092 mem_put_le32(header+20, cfg->g_timebase.num); /* scale */ 00093 mem_put_le32(header+24, frame_cnt); /* length */ 00094 mem_put_le32(header+28, 0); /* unused */ 00095 00096 (void) fwrite(header, 1, 32, outfile); 00097 } 00098 00099 00100 static void write_ivf_frame_header(FILE *outfile, 00101 const vpx_codec_cx_pkt_t *pkt) 00102 { 00103 char header[12]; 00104 vpx_codec_pts_t pts; 00105 00106 if(pkt->kind != VPX_CODEC_CX_FRAME_PKT) 00107 return; 00108 00109 pts = pkt->data.frame.pts; 00110 mem_put_le32(header, pkt->data.frame.sz); 00111 mem_put_le32(header+4, pts&0xFFFFFFFF); 00112 mem_put_le32(header+8, pts >> 32); 00113 00114 (void) fwrite(header, 1, 12, outfile); 00115 } 00116 00117 static int mode_to_num_layers[12] = {1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3}; 00118 00119 int main(int argc, char **argv) { 00120 FILE *infile, *outfile[VPX_TS_MAX_LAYERS]; 00121 vpx_codec_ctx_t codec; 00122 vpx_codec_enc_cfg_t cfg; 00123 int frame_cnt = 0; 00124 vpx_image_t raw; 00125 vpx_codec_err_t res; 00126 unsigned int width; 00127 unsigned int height; 00128 int frame_avail; 00129 int got_data; 00130 int flags = 0; 00131 int i; 00132 int pts = 0; /* PTS starts at 0 */ 00133 int frame_duration = 1; /* 1 timebase tick per frame */ 00134 00135 int layering_mode = 0; 00136 int frames_in_layer[VPX_TS_MAX_LAYERS] = {0}; 00137 int layer_flags[VPX_TS_MAX_PERIODICITY] = {0}; 00138 int flag_periodicity; 00139 int max_intra_size_pct; 00140 00141 /* Check usage and arguments */ 00142 if (argc < 9) 00143 die("Usage: %s <infile> <outfile> <width> <height> <rate_num> " 00144 " <rate_den> <mode> <Rate_0> ... <Rate_nlayers-1>\n", argv[0]); 00145 00146 width = strtol (argv[3], NULL, 0); 00147 height = strtol (argv[4], NULL, 0); 00148 if (width < 16 || width%2 || height <16 || height%2) 00149 die ("Invalid resolution: %d x %d", width, height); 00150 00151 if (!sscanf(argv[7], "%d", &layering_mode)) 00152 die ("Invalid mode %s", argv[7]); 00153 if (layering_mode<0 || layering_mode>11) 00154 die ("Invalid mode (0..11) %s", argv[7]); 00155 00156 if (argc != 8+mode_to_num_layers[layering_mode]) 00157 die ("Invalid number of arguments"); 00158 00159 if (!vpx_img_alloc (&raw, VPX_IMG_FMT_I420, width, height, 32)) 00160 die ("Failed to allocate image", width, height); 00161 00162 printf("Using %s\n",vpx_codec_iface_name(interface)); 00163 00164 /* Populate encoder configuration */ 00165 res = vpx_codec_enc_config_default(interface, &cfg, 0); 00166 if(res) { 00167 printf("Failed to get config: %s\n", vpx_codec_err_to_string(res)); 00168 return EXIT_FAILURE; 00169 } 00170 00171 /* Update the default configuration with our settings */ 00172 cfg.g_w = width; 00173 cfg.g_h = height; 00174 00175 /* Timebase format e.g. 30fps: numerator=1, demoninator=30 */ 00176 if (!sscanf (argv[5], "%d", &cfg.g_timebase.num )) 00177 die ("Invalid timebase numerator %s", argv[5]); 00178 if (!sscanf (argv[6], "%d", &cfg.g_timebase.den )) 00179 die ("Invalid timebase denominator %s", argv[6]); 00180 00181 for (i=8; i<8+mode_to_num_layers[layering_mode]; i++) 00182 if (!sscanf(argv[i], "%ud", &cfg.ts_target_bitrate[i-8])) 00183 die ("Invalid data rate %s", argv[i]); 00184 00185 /* Real time parameters */ 00186 cfg.rc_dropframe_thresh = 0; 00187 cfg.rc_end_usage = VPX_CBR; 00188 cfg.rc_resize_allowed = 0; 00189 cfg.rc_min_quantizer = 2; 00190 cfg.rc_max_quantizer = 56; 00191 cfg.rc_undershoot_pct = 100; 00192 cfg.rc_overshoot_pct = 15; 00193 cfg.rc_buf_initial_sz = 500; 00194 cfg.rc_buf_optimal_sz = 600; 00195 cfg.rc_buf_sz = 1000; 00196 00197 /* Enable error resilient mode */ 00198 cfg.g_error_resilient = 1; 00199 cfg.g_lag_in_frames = 0; 00200 cfg.kf_mode = VPX_KF_DISABLED; 00201 00202 /* Disable automatic keyframe placement */ 00203 cfg.kf_min_dist = cfg.kf_max_dist = 3000; 00204 00205 /* Default setting for bitrate: used in special case of 1 layer (case 0). */ 00206 cfg.rc_target_bitrate = cfg.ts_target_bitrate[0]; 00207 00208 /* Temporal scaling parameters: */ 00209 /* NOTE: The 3 prediction frames cannot be used interchangeably due to 00210 * differences in the way they are handled throughout the code. The 00211 * frames should be allocated to layers in the order LAST, GF, ARF. 00212 * Other combinations work, but may produce slightly inferior results. 00213 */ 00214 switch (layering_mode) 00215 { 00216 case 0: 00217 { 00218 /* 1-layer */ 00219 int ids[1] = {0}; 00220 cfg.ts_number_layers = 1; 00221 cfg.ts_periodicity = 1; 00222 cfg.ts_rate_decimator[0] = 1; 00223 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00224 00225 flag_periodicity = cfg.ts_periodicity; 00226 00227 // Update L only. 00228 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00229 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00230 break; 00231 } 00232 case 1: 00233 { 00234 /* 2-layers, 2-frame period */ 00235 int ids[2] = {0,1}; 00236 cfg.ts_number_layers = 2; 00237 cfg.ts_periodicity = 2; 00238 cfg.ts_rate_decimator[0] = 2; 00239 cfg.ts_rate_decimator[1] = 1; 00240 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00241 00242 flag_periodicity = cfg.ts_periodicity; 00243 #if 1 00244 /* 0=L, 1=GF, Intra-layer prediction enabled */ 00245 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00246 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 00247 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; 00248 layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | 00249 VP8_EFLAG_NO_REF_ARF; 00250 #else 00251 /* 0=L, 1=GF, Intra-layer prediction disabled */ 00252 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00253 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 00254 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; 00255 layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | 00256 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST; 00257 #endif 00258 break; 00259 } 00260 00261 case 2: 00262 { 00263 /* 2-layers, 3-frame period */ 00264 int ids[3] = {0,1,1}; 00265 cfg.ts_number_layers = 2; 00266 cfg.ts_periodicity = 3; 00267 cfg.ts_rate_decimator[0] = 3; 00268 cfg.ts_rate_decimator[1] = 1; 00269 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00270 00271 flag_periodicity = cfg.ts_periodicity; 00272 00273 /* 0=L, 1=GF, Intra-layer prediction enabled */ 00274 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00275 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00276 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00277 layer_flags[1] = 00278 layer_flags[2] = VP8_EFLAG_NO_REF_GF | 00279 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | 00280 VP8_EFLAG_NO_UPD_LAST; 00281 break; 00282 } 00283 00284 case 3: 00285 { 00286 /* 3-layers, 6-frame period */ 00287 int ids[6] = {0,2,2,1,2,2}; 00288 cfg.ts_number_layers = 3; 00289 cfg.ts_periodicity = 6; 00290 cfg.ts_rate_decimator[0] = 6; 00291 cfg.ts_rate_decimator[1] = 3; 00292 cfg.ts_rate_decimator[2] = 1; 00293 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00294 00295 flag_periodicity = cfg.ts_periodicity; 00296 00297 /* 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled */ 00298 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00299 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00300 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00301 layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | 00302 VP8_EFLAG_NO_UPD_LAST; 00303 layer_flags[1] = 00304 layer_flags[2] = 00305 layer_flags[4] = 00306 layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST; 00307 break; 00308 } 00309 00310 case 4: 00311 { 00312 /* 3-layers, 4-frame period */ 00313 int ids[4] = {0,2,1,2}; 00314 cfg.ts_number_layers = 3; 00315 cfg.ts_periodicity = 4; 00316 cfg.ts_rate_decimator[0] = 4; 00317 cfg.ts_rate_decimator[1] = 2; 00318 cfg.ts_rate_decimator[2] = 1; 00319 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00320 00321 flag_periodicity = cfg.ts_periodicity; 00322 00323 /* 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled */ 00324 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00325 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00326 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00327 layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00328 VP8_EFLAG_NO_UPD_ARF | 00329 VP8_EFLAG_NO_UPD_LAST; 00330 layer_flags[1] = 00331 layer_flags[3] = VP8_EFLAG_NO_REF_ARF | 00332 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | 00333 VP8_EFLAG_NO_UPD_ARF; 00334 break; 00335 } 00336 00337 case 5: 00338 { 00339 /* 3-layers, 4-frame period */ 00340 int ids[4] = {0,2,1,2}; 00341 cfg.ts_number_layers = 3; 00342 cfg.ts_periodicity = 4; 00343 cfg.ts_rate_decimator[0] = 4; 00344 cfg.ts_rate_decimator[1] = 2; 00345 cfg.ts_rate_decimator[2] = 1; 00346 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00347 00348 flag_periodicity = cfg.ts_periodicity; 00349 00350 /* 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1, 00351 * disabled in layer 2 00352 */ 00353 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00354 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00355 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00356 layer_flags[2] = VP8_EFLAG_NO_REF_ARF | 00357 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; 00358 layer_flags[1] = 00359 layer_flags[3] = VP8_EFLAG_NO_REF_ARF | 00360 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | 00361 VP8_EFLAG_NO_UPD_ARF; 00362 break; 00363 } 00364 00365 case 6: 00366 { 00367 /* 3-layers, 4-frame period */ 00368 int ids[4] = {0,2,1,2}; 00369 cfg.ts_number_layers = 3; 00370 cfg.ts_periodicity = 4; 00371 cfg.ts_rate_decimator[0] = 4; 00372 cfg.ts_rate_decimator[1] = 2; 00373 cfg.ts_rate_decimator[2] = 1; 00374 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00375 00376 flag_periodicity = cfg.ts_periodicity; 00377 00378 /* 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled */ 00379 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00380 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00381 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00382 layer_flags[2] = VP8_EFLAG_NO_REF_ARF | 00383 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; 00384 layer_flags[1] = 00385 layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; 00386 break; 00387 } 00388 00389 case 7: 00390 { 00391 /* NOTE: Probably of academic interest only */ 00392 00393 /* 5-layers, 16-frame period */ 00394 int ids[16] = {0,4,3,4,2,4,3,4,1,4,3,4,2,4,3,4}; 00395 cfg.ts_number_layers = 5; 00396 cfg.ts_periodicity = 16; 00397 cfg.ts_rate_decimator[0] = 16; 00398 cfg.ts_rate_decimator[1] = 8; 00399 cfg.ts_rate_decimator[2] = 4; 00400 cfg.ts_rate_decimator[3] = 2; 00401 cfg.ts_rate_decimator[4] = 1; 00402 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00403 00404 flag_periodicity = cfg.ts_periodicity; 00405 00406 layer_flags[0] = VPX_EFLAG_FORCE_KF; 00407 layer_flags[1] = 00408 layer_flags[3] = 00409 layer_flags[5] = 00410 layer_flags[7] = 00411 layer_flags[9] = 00412 layer_flags[11] = 00413 layer_flags[13] = 00414 layer_flags[15] = VP8_EFLAG_NO_UPD_LAST | 00415 VP8_EFLAG_NO_UPD_GF | 00416 VP8_EFLAG_NO_UPD_ARF; 00417 layer_flags[2] = 00418 layer_flags[6] = 00419 layer_flags[10] = 00420 layer_flags[14] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF; 00421 layer_flags[4] = 00422 layer_flags[12] = VP8_EFLAG_NO_REF_LAST | 00423 VP8_EFLAG_NO_UPD_ARF; 00424 layer_flags[8] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF; 00425 break; 00426 } 00427 00428 case 8: 00429 { 00430 /* 2-layers, with sync point at first frame of layer 1. */ 00431 int ids[2] = {0,1}; 00432 cfg.ts_number_layers = 2; 00433 cfg.ts_periodicity = 2; 00434 cfg.ts_rate_decimator[0] = 2; 00435 cfg.ts_rate_decimator[1] = 1; 00436 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00437 00438 flag_periodicity = 8; 00439 00440 /* 0=L, 1=GF */ 00441 // ARF is used as predictor for all frames, and is only updated on 00442 // key frame. Sync point every 8 frames. 00443 00444 // Layer 0: predict from L and ARF, update L and G. 00445 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00446 VP8_EFLAG_NO_REF_GF | 00447 VP8_EFLAG_NO_UPD_ARF; 00448 00449 // Layer 1: sync point: predict from L and ARF, and update G. 00450 layer_flags[1] = VP8_EFLAG_NO_REF_GF | 00451 VP8_EFLAG_NO_UPD_LAST | 00452 VP8_EFLAG_NO_UPD_ARF; 00453 00454 // Layer 0, predict from L and ARF, update L. 00455 layer_flags[2] = VP8_EFLAG_NO_REF_GF | 00456 VP8_EFLAG_NO_UPD_GF | 00457 VP8_EFLAG_NO_UPD_ARF; 00458 00459 // Layer 1: predict from L, G and ARF, and update G. 00460 layer_flags[3] = VP8_EFLAG_NO_UPD_ARF | 00461 VP8_EFLAG_NO_UPD_LAST | 00462 VP8_EFLAG_NO_UPD_ENTROPY; 00463 00464 // Layer 0 00465 layer_flags[4] = layer_flags[2]; 00466 00467 // Layer 1 00468 layer_flags[5] = layer_flags[3]; 00469 00470 // Layer 0 00471 layer_flags[6] = layer_flags[4]; 00472 00473 // Layer 1 00474 layer_flags[7] = layer_flags[5]; 00475 break; 00476 } 00477 00478 case 9: 00479 { 00480 /* 3-layers */ 00481 // Sync points for layer 1 and 2 every 8 frames. 00482 00483 int ids[4] = {0,2,1,2}; 00484 cfg.ts_number_layers = 3; 00485 cfg.ts_periodicity = 4; 00486 cfg.ts_rate_decimator[0] = 4; 00487 cfg.ts_rate_decimator[1] = 2; 00488 cfg.ts_rate_decimator[2] = 1; 00489 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00490 00491 flag_periodicity = 8; 00492 00493 /* 0=L, 1=GF, 2=ARF */ 00494 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00495 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00496 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00497 layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00498 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; 00499 layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00500 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; 00501 layer_flags[3] = 00502 layer_flags[5] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; 00503 layer_flags[4] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00504 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00505 layer_flags[6] = VP8_EFLAG_NO_REF_ARF | 00506 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; 00507 layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | 00508 VP8_EFLAG_NO_UPD_ARF | 00509 VP8_EFLAG_NO_UPD_ENTROPY; 00510 break; 00511 } 00512 case 10: 00513 { 00514 // 3-layers structure where ARF is used as predictor for all frames, 00515 // and is only updated on key frame. 00516 // Sync points for layer 1 and 2 every 8 frames. 00517 00518 int ids[4] = {0,2,1,2}; 00519 cfg.ts_number_layers = 3; 00520 cfg.ts_periodicity = 4; 00521 cfg.ts_rate_decimator[0] = 4; 00522 cfg.ts_rate_decimator[1] = 2; 00523 cfg.ts_rate_decimator[2] = 1; 00524 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00525 00526 flag_periodicity = 8; 00527 00528 /* 0=L, 1=GF, 2=ARF */ 00529 00530 // Layer 0: predict from L and ARF; update L and G. 00531 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00532 VP8_EFLAG_NO_UPD_ARF | 00533 VP8_EFLAG_NO_REF_GF; 00534 00535 // Layer 2: sync point: predict from L and ARF; update none. 00536 layer_flags[1] = VP8_EFLAG_NO_REF_GF | 00537 VP8_EFLAG_NO_UPD_GF | 00538 VP8_EFLAG_NO_UPD_ARF | 00539 VP8_EFLAG_NO_UPD_LAST | 00540 VP8_EFLAG_NO_UPD_ENTROPY; 00541 00542 // Layer 1: sync point: predict from L and ARF; update G. 00543 layer_flags[2] = VP8_EFLAG_NO_REF_GF | 00544 VP8_EFLAG_NO_UPD_ARF | 00545 VP8_EFLAG_NO_UPD_LAST; 00546 00547 // Layer 2: predict from L, G, ARF; update none. 00548 layer_flags[3] = VP8_EFLAG_NO_UPD_GF | 00549 VP8_EFLAG_NO_UPD_ARF | 00550 VP8_EFLAG_NO_UPD_LAST | 00551 VP8_EFLAG_NO_UPD_ENTROPY; 00552 00553 // Layer 0: predict from L and ARF; update L. 00554 layer_flags[4] = VP8_EFLAG_NO_UPD_GF | 00555 VP8_EFLAG_NO_UPD_ARF | 00556 VP8_EFLAG_NO_REF_GF; 00557 00558 // Layer 2: predict from L, G, ARF; update none. 00559 layer_flags[5] = layer_flags[3]; 00560 00561 // Layer 1: predict from L, G, ARF; update G. 00562 layer_flags[6] = VP8_EFLAG_NO_UPD_ARF | 00563 VP8_EFLAG_NO_UPD_LAST; 00564 00565 // Layer 2: predict from L, G, ARF; update none. 00566 layer_flags[7] = layer_flags[3]; 00567 break; 00568 } 00569 case 11: 00570 default: 00571 { 00572 // 3-layers structure as in case 10, but no sync/refresh points for 00573 // layer 1 and 2. 00574 00575 int ids[4] = {0,2,1,2}; 00576 cfg.ts_number_layers = 3; 00577 cfg.ts_periodicity = 4; 00578 cfg.ts_rate_decimator[0] = 4; 00579 cfg.ts_rate_decimator[1] = 2; 00580 cfg.ts_rate_decimator[2] = 1; 00581 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00582 00583 flag_periodicity = 8; 00584 00585 /* 0=L, 1=GF, 2=ARF */ 00586 00587 // Layer 0: predict from L and ARF; update L. 00588 layer_flags[0] = VP8_EFLAG_NO_UPD_GF | 00589 VP8_EFLAG_NO_UPD_ARF | 00590 VP8_EFLAG_NO_REF_GF; 00591 layer_flags[4] = layer_flags[0]; 00592 00593 // Layer 1: predict from L, G, ARF; update G. 00594 layer_flags[2] = VP8_EFLAG_NO_UPD_ARF | 00595 VP8_EFLAG_NO_UPD_LAST; 00596 layer_flags[6] = layer_flags[2]; 00597 00598 // Layer 2: predict from L, G, ARF; update none. 00599 layer_flags[1] = VP8_EFLAG_NO_UPD_GF | 00600 VP8_EFLAG_NO_UPD_ARF | 00601 VP8_EFLAG_NO_UPD_LAST | 00602 VP8_EFLAG_NO_UPD_ENTROPY; 00603 layer_flags[3] = layer_flags[1]; 00604 layer_flags[5] = layer_flags[1]; 00605 layer_flags[7] = layer_flags[1]; 00606 break; 00607 } 00608 } 00609 00610 /* Open input file */ 00611 if(!(infile = fopen(argv[1], "rb"))) 00612 die("Failed to open %s for reading", argv[1]); 00613 00614 /* Open an output file for each stream */ 00615 for (i=0; i<cfg.ts_number_layers; i++) 00616 { 00617 char file_name[512]; 00618 sprintf (file_name, "%s_%d.ivf", argv[2], i); 00619 if (!(outfile[i] = fopen(file_name, "wb"))) 00620 die("Failed to open %s for writing", file_name); 00621 write_ivf_file_header(outfile[i], &cfg, 0); 00622 } 00623 00624 /* Initialize codec */ 00625 if (vpx_codec_enc_init (&codec, interface, &cfg, 0)) 00626 die_codec (&codec, "Failed to initialize encoder"); 00627 00628 /* Cap CPU & first I-frame size */ 00629 vpx_codec_control (&codec, VP8E_SET_CPUUSED, -6); 00630 vpx_codec_control (&codec, VP8E_SET_STATIC_THRESHOLD, 1); 00631 vpx_codec_control (&codec, VP8E_SET_NOISE_SENSITIVITY, 1); 00632 vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1); 00633 00634 max_intra_size_pct = (int) (((double)cfg.rc_buf_optimal_sz * 0.5) 00635 * ((double) cfg.g_timebase.den / cfg.g_timebase.num) 00636 / 10.0); 00637 /* printf ("max_intra_size_pct=%d\n", max_intra_size_pct); */ 00638 00639 vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, 00640 max_intra_size_pct); 00641 00642 frame_avail = 1; 00643 while (frame_avail || got_data) { 00644 vpx_codec_iter_t iter = NULL; 00645 const vpx_codec_cx_pkt_t *pkt; 00646 00647 flags = layer_flags[frame_cnt % flag_periodicity]; 00648 00649 frame_avail = read_frame(infile, &raw); 00650 if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts, 00651 1, flags, VPX_DL_REALTIME)) 00652 die_codec(&codec, "Failed to encode frame"); 00653 00654 /* Reset KF flag */ 00655 if (layering_mode != 7) 00656 layer_flags[0] &= ~VPX_EFLAG_FORCE_KF; 00657 00658 got_data = 0; 00659 while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { 00660 got_data = 1; 00661 switch (pkt->kind) { 00662 case VPX_CODEC_CX_FRAME_PKT: 00663 for (i=cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity]; 00664 i<cfg.ts_number_layers; i++) 00665 { 00666 write_ivf_frame_header(outfile[i], pkt); 00667 (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, 00668 outfile[i]); 00669 frames_in_layer[i]++; 00670 } 00671 break; 00672 default: 00673 break; 00674 } 00675 } 00676 frame_cnt++; 00677 pts += frame_duration; 00678 } 00679 fclose (infile); 00680 00681 printf ("Processed %d frames.\n",frame_cnt-1); 00682 if (vpx_codec_destroy(&codec)) 00683 die_codec (&codec, "Failed to destroy codec"); 00684 00685 /* Try to rewrite the output file headers with the actual frame count */ 00686 for (i=0; i<cfg.ts_number_layers; i++) 00687 { 00688 if (!fseek(outfile[i], 0, SEEK_SET)) 00689 write_ivf_file_header (outfile[i], &cfg, frames_in_layer[i]); 00690 fclose (outfile[i]); 00691 } 00692 00693 return EXIT_SUCCESS; 00694 }