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 if(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 if(fwrite(header, 1, 12, outfile)); 00115 } 00116 00117 static int mode_to_num_layers[9] = {2, 2, 3, 3, 3, 3, 5, 2, 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>8) 00154 die ("Invalid mode (0..8) %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, 1)) 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], "%d", &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; // 30 00187 cfg.rc_end_usage = VPX_CBR; 00188 cfg.rc_resize_allowed = 0; 00189 cfg.rc_min_quantizer = 8; 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 = 1000; 00204 00205 // Temporal scaling parameters: 00206 // NOTE: The 3 prediction frames cannot be used interchangeably due to 00207 // differences in the way they are handled throughout the code. The 00208 // frames should be allocated to layers in the order LAST, GF, ARF. 00209 // Other combinations work, but may produce slightly inferior results. 00210 switch (layering_mode) 00211 { 00212 00213 case 0: 00214 { 00215 // 2-layers, 2-frame period 00216 int ids[2] = {0,1}; 00217 cfg.ts_number_layers = 2; 00218 cfg.ts_periodicity = 2; 00219 cfg.ts_rate_decimator[0] = 2; 00220 cfg.ts_rate_decimator[1] = 1; 00221 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00222 00223 flag_periodicity = cfg.ts_periodicity; 00224 #if 1 00225 // 0=L, 1=GF, Intra-layer prediction enabled 00226 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00227 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 00228 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; 00229 layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | 00230 VP8_EFLAG_NO_REF_ARF; 00231 #else 00232 // 0=L, 1=GF, Intra-layer prediction disabled 00233 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00234 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 00235 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; 00236 layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | 00237 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST; 00238 #endif 00239 break; 00240 } 00241 00242 case 1: 00243 { 00244 // 2-layers, 3-frame period 00245 int ids[3] = {0,1,1}; 00246 cfg.ts_number_layers = 2; 00247 cfg.ts_periodicity = 3; 00248 cfg.ts_rate_decimator[0] = 3; 00249 cfg.ts_rate_decimator[1] = 1; 00250 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00251 00252 flag_periodicity = cfg.ts_periodicity; 00253 00254 // 0=L, 1=GF, Intra-layer prediction enabled 00255 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00256 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00257 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00258 layer_flags[1] = 00259 layer_flags[2] = VP8_EFLAG_NO_REF_GF | 00260 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | 00261 VP8_EFLAG_NO_UPD_LAST; 00262 break; 00263 } 00264 00265 case 2: 00266 { 00267 // 3-layers, 6-frame period 00268 int ids[6] = {0,2,2,1,2,2}; 00269 cfg.ts_number_layers = 3; 00270 cfg.ts_periodicity = 6; 00271 cfg.ts_rate_decimator[0] = 6; 00272 cfg.ts_rate_decimator[1] = 3; 00273 cfg.ts_rate_decimator[2] = 1; 00274 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00275 00276 flag_periodicity = cfg.ts_periodicity; 00277 00278 // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled 00279 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00280 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00281 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00282 layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | 00283 VP8_EFLAG_NO_UPD_LAST; 00284 layer_flags[1] = 00285 layer_flags[2] = 00286 layer_flags[4] = 00287 layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST; 00288 break; 00289 } 00290 00291 case 3: 00292 { 00293 // 3-layers, 4-frame period 00294 int ids[4] = {0,2,1,2}; 00295 cfg.ts_number_layers = 3; 00296 cfg.ts_periodicity = 4; 00297 cfg.ts_rate_decimator[0] = 4; 00298 cfg.ts_rate_decimator[1] = 2; 00299 cfg.ts_rate_decimator[2] = 1; 00300 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00301 00302 flag_periodicity = cfg.ts_periodicity; 00303 00304 // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled 00305 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00306 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00307 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00308 layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00309 VP8_EFLAG_NO_UPD_ARF | 00310 VP8_EFLAG_NO_UPD_LAST; 00311 layer_flags[1] = 00312 layer_flags[3] = VP8_EFLAG_NO_REF_ARF | 00313 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | 00314 VP8_EFLAG_NO_UPD_ARF; 00315 break; 00316 } 00317 00318 case 4: 00319 { 00320 // 3-layers, 4-frame period 00321 int ids[4] = {0,2,1,2}; 00322 cfg.ts_number_layers = 3; 00323 cfg.ts_periodicity = 4; 00324 cfg.ts_rate_decimator[0] = 4; 00325 cfg.ts_rate_decimator[1] = 2; 00326 cfg.ts_rate_decimator[2] = 1; 00327 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00328 00329 flag_periodicity = cfg.ts_periodicity; 00330 00331 // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1, 00332 // disabled in layer 2 00333 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00334 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00335 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00336 layer_flags[2] = VP8_EFLAG_NO_REF_ARF | 00337 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; 00338 layer_flags[1] = 00339 layer_flags[3] = VP8_EFLAG_NO_REF_ARF | 00340 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | 00341 VP8_EFLAG_NO_UPD_ARF; 00342 break; 00343 } 00344 00345 case 5: 00346 { 00347 // 3-layers, 4-frame period 00348 int ids[4] = {0,2,1,2}; 00349 cfg.ts_number_layers = 3; 00350 cfg.ts_periodicity = 4; 00351 cfg.ts_rate_decimator[0] = 4; 00352 cfg.ts_rate_decimator[1] = 2; 00353 cfg.ts_rate_decimator[2] = 1; 00354 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00355 00356 flag_periodicity = cfg.ts_periodicity; 00357 00358 // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled 00359 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00360 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00361 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00362 layer_flags[2] = VP8_EFLAG_NO_REF_ARF | 00363 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; 00364 layer_flags[1] = 00365 layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; 00366 break; 00367 } 00368 00369 case 6: 00370 { 00371 // NOTE: Probably of academic interest only 00372 00373 // 5-layers, 16-frame period 00374 int ids[16] = {0,4,3,4,2,4,3,4,1,4,3,4,2,4,3,4}; 00375 cfg.ts_number_layers = 5; 00376 cfg.ts_periodicity = 16; 00377 cfg.ts_rate_decimator[0] = 16; 00378 cfg.ts_rate_decimator[1] = 8; 00379 cfg.ts_rate_decimator[2] = 4; 00380 cfg.ts_rate_decimator[3] = 2; 00381 cfg.ts_rate_decimator[4] = 1; 00382 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00383 00384 flag_periodicity = cfg.ts_periodicity; 00385 00386 layer_flags[0] = VPX_EFLAG_FORCE_KF; 00387 layer_flags[1] = 00388 layer_flags[3] = 00389 layer_flags[5] = 00390 layer_flags[7] = 00391 layer_flags[9] = 00392 layer_flags[11] = 00393 layer_flags[13] = 00394 layer_flags[15] = VP8_EFLAG_NO_UPD_LAST | 00395 VP8_EFLAG_NO_UPD_GF | 00396 VP8_EFLAG_NO_UPD_ARF; 00397 layer_flags[2] = 00398 layer_flags[6] = 00399 layer_flags[10] = 00400 layer_flags[14] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF; 00401 layer_flags[4] = 00402 layer_flags[12] = VP8_EFLAG_NO_REF_LAST | 00403 VP8_EFLAG_NO_UPD_ARF; 00404 layer_flags[8] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF; 00405 break; 00406 } 00407 00408 case 7: 00409 { 00410 // 2-layers 00411 int ids[2] = {0,1}; 00412 cfg.ts_number_layers = 2; 00413 cfg.ts_periodicity = 2; 00414 cfg.ts_rate_decimator[0] = 2; 00415 cfg.ts_rate_decimator[1] = 1; 00416 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00417 00418 flag_periodicity = 8; 00419 00420 // 0=L, 1=GF 00421 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00422 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00423 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00424 layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00425 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; 00426 layer_flags[2] = 00427 layer_flags[4] = 00428 layer_flags[6] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00429 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00430 layer_flags[3] = 00431 layer_flags[5] = VP8_EFLAG_NO_REF_ARF | 00432 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; 00433 layer_flags[7] = VP8_EFLAG_NO_REF_ARF | 00434 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | 00435 VP8_EFLAG_NO_UPD_ARF | 00436 VP8_EFLAG_NO_UPD_ENTROPY; 00437 break; 00438 } 00439 00440 case 8: 00441 default: 00442 { 00443 // 3-layers 00444 int ids[4] = {0,2,1,2}; 00445 cfg.ts_number_layers = 3; 00446 cfg.ts_periodicity = 4; 00447 cfg.ts_rate_decimator[0] = 4; 00448 cfg.ts_rate_decimator[1] = 2; 00449 cfg.ts_rate_decimator[2] = 1; 00450 memcpy(cfg.ts_layer_id, ids, sizeof(ids)); 00451 00452 flag_periodicity = 8; 00453 00454 // 0=L, 1=GF, 2=ARF 00455 layer_flags[0] = VPX_EFLAG_FORCE_KF | 00456 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00457 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00458 layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00459 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; 00460 layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00461 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; 00462 layer_flags[3] = 00463 layer_flags[5] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; 00464 layer_flags[4] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | 00465 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 00466 layer_flags[6] = VP8_EFLAG_NO_REF_ARF | 00467 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; 00468 layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | 00469 VP8_EFLAG_NO_UPD_ARF | 00470 VP8_EFLAG_NO_UPD_ENTROPY; 00471 break; 00472 } 00473 } 00474 00475 // Open input file 00476 if(!(infile = fopen(argv[1], "rb"))) 00477 die("Failed to open %s for reading", argv[1]); 00478 00479 // Open an output file for each stream 00480 for (i=0; i<cfg.ts_number_layers; i++) 00481 { 00482 char file_name[512]; 00483 sprintf (file_name, "%s_%d.ivf", argv[2], i); 00484 if (!(outfile[i] = fopen(file_name, "wb"))) 00485 die("Failed to open %s for writing", file_name); 00486 write_ivf_file_header(outfile[i], &cfg, 0); 00487 } 00488 00489 // Initialize codec 00490 if (vpx_codec_enc_init (&codec, interface, &cfg, 0)) 00491 die_codec (&codec, "Failed to initialize encoder"); 00492 00493 // Cap CPU & first I-frame size 00494 vpx_codec_control (&codec, VP8E_SET_CPUUSED, -6); 00495 vpx_codec_control (&codec, VP8E_SET_STATIC_THRESHOLD, 800); 00496 vpx_codec_control (&codec, VP8E_SET_NOISE_SENSITIVITY, 2); 00497 00498 max_intra_size_pct = (int) (((double)cfg.rc_buf_optimal_sz * 0.5) 00499 * ((double) cfg.g_timebase.den / cfg.g_timebase.num) 00500 / 10.0); 00501 //printf ("max_intra_size_pct=%d\n", max_intra_size_pct); 00502 00503 vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, 00504 max_intra_size_pct); 00505 // vpx_codec_control (&codec, VP8E_SET_TOKEN_PARTITIONS, 00506 // static_cast<vp8e_token_partitions>(_tokenPartitions)); 00507 00508 frame_avail = 1; 00509 while (frame_avail || got_data) { 00510 vpx_codec_iter_t iter = NULL; 00511 const vpx_codec_cx_pkt_t *pkt; 00512 00513 flags = layer_flags[frame_cnt % flag_periodicity]; 00514 00515 frame_avail = read_frame(infile, &raw); 00516 if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts, 00517 1, flags, VPX_DL_REALTIME)) 00518 die_codec(&codec, "Failed to encode frame"); 00519 00520 // Reset KF flag 00521 if (layering_mode != 6) 00522 layer_flags[0] &= ~VPX_EFLAG_FORCE_KF; 00523 00524 got_data = 0; 00525 while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { 00526 got_data = 1; 00527 switch (pkt->kind) { 00528 case VPX_CODEC_CX_FRAME_PKT: 00529 for (i=cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity]; 00530 i<cfg.ts_number_layers; i++) 00531 { 00532 write_ivf_frame_header(outfile[i], pkt); 00533 if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, 00534 outfile[i])); 00535 frames_in_layer[i]++; 00536 } 00537 break; 00538 default: 00539 break; 00540 } 00541 printf (pkt->kind == VPX_CODEC_CX_FRAME_PKT 00542 && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":"."); 00543 fflush (stdout); 00544 } 00545 frame_cnt++; 00546 pts += frame_duration; 00547 } 00548 printf ("\n"); 00549 fclose (infile); 00550 00551 printf ("Processed %d frames.\n",frame_cnt-1); 00552 if (vpx_codec_destroy(&codec)) 00553 die_codec (&codec, "Failed to destroy codec"); 00554 00555 // Try to rewrite the output file headers with the actual frame count 00556 for (i=0; i<cfg.ts_number_layers; i++) 00557 { 00558 if (!fseek(outfile[i], 0, SEEK_SET)) 00559 write_ivf_file_header (outfile[i], &cfg, frames_in_layer[i]); 00560 fclose (outfile[i]); 00561 } 00562 00563 return EXIT_SUCCESS; 00564 } 00565