1 /* 2 * Copyright (c) 2010 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 @*INTRODUCTION 14 */ 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <stdarg.h> 18 #include <string.h> 19 #define VPX_CODEC_DISABLE_COMPAT 1 20 #include "vpx/vpx_encoder.h" 21 #include "vpx/vp8cx.h" 22 #define interface (vpx_codec_vp8_cx()) 23 #define fourcc 0x30385056 24 @EXTRA_INCLUDES 25 26 #define IVF_FILE_HDR_SZ (32) 27 #define IVF_FRAME_HDR_SZ (12) 28 29 static void mem_put_le16(char *mem, unsigned int val) { 30 mem[0] = val; 31 mem[1] = val>>8; 32 } 33 34 static void mem_put_le32(char *mem, unsigned int val) { 35 mem[0] = val; 36 mem[1] = val>>8; 37 mem[2] = val>>16; 38 mem[3] = val>>24; 39 } 40 41 static void die(const char *fmt, ...) { 42 va_list ap; 43 44 va_start(ap, fmt); 45 vprintf(fmt, ap); 46 if(fmt[strlen(fmt)-1] != '\n') 47 printf("\n"); 48 exit(EXIT_FAILURE); 49 } 50 51 @DIE_CODEC 52 53 static int read_frame(FILE *f, vpx_image_t *img) { 54 size_t nbytes, to_read; 55 int res = 1; 56 57 to_read = img->w*img->h*3/2; 58 nbytes = fread(img->planes[0], 1, to_read, f); 59 if(nbytes != to_read) { 60 res = 0; 61 if(nbytes > 0) 62 printf("Warning: Read partial frame. Check your width & height!\n"); 63 } 64 return res; 65 } 66 67 static void write_ivf_file_header(FILE *outfile, 68 const vpx_codec_enc_cfg_t *cfg, 69 int frame_cnt) { 70 char header[32]; 71 72 if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS) 73 return; 74 header[0] = 'D'; 75 header[1] = 'K'; 76 header[2] = 'I'; 77 header[3] = 'F'; 78 mem_put_le16(header+4, 0); /* version */ 79 mem_put_le16(header+6, 32); /* headersize */ 80 mem_put_le32(header+8, fourcc); /* headersize */ 81 mem_put_le16(header+12, cfg->g_w); /* width */ 82 mem_put_le16(header+14, cfg->g_h); /* height */ 83 mem_put_le32(header+16, cfg->g_timebase.den); /* rate */ 84 mem_put_le32(header+20, cfg->g_timebase.num); /* scale */ 85 mem_put_le32(header+24, frame_cnt); /* length */ 86 mem_put_le32(header+28, 0); /* unused */ 87 88 (void) fwrite(header, 1, 32, outfile); 89 } 90 91 92 static void write_ivf_frame_header(FILE *outfile, 93 const vpx_codec_cx_pkt_t *pkt) 94 { 95 char header[12]; 96 vpx_codec_pts_t pts; 97 98 if(pkt->kind != VPX_CODEC_CX_FRAME_PKT) 99 return; 100 101 pts = pkt->data.frame.pts; 102 mem_put_le32(header, pkt->data.frame.sz); 103 mem_put_le32(header+4, pts&0xFFFFFFFF); 104 mem_put_le32(header+8, pts >> 32); 105 106 (void) fwrite(header, 1, 12, outfile); 107 } 108 109 int main(int argc, char **argv) { 110 FILE *infile, *outfile; 111 vpx_codec_ctx_t codec; 112 vpx_codec_enc_cfg_t cfg; 113 int frame_cnt = 0; 114 vpx_image_t raw; 115 vpx_codec_err_t res; 116 long width; 117 long height; 118 int frame_avail; 119 int got_data; 120 int flags = 0; 121 @@@@TWOPASS_VARS 122 123 /* Open files */ 124 @@@@USAGE 125 width = strtol(argv[1], NULL, 0); 126 height = strtol(argv[2], NULL, 0); 127 if(width < 16 || width%2 || height <16 || height%2) 128 die("Invalid resolution: %ldx%ld", width, height); 129 if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1)) 130 die("Faile to allocate image", width, height); 131 if(!(outfile = fopen(argv[4], "wb"))) 132 die("Failed to open %s for writing", argv[4]); 133 134 printf("Using %s\n",vpx_codec_iface_name(interface)); 135 136 @@@@ENC_DEF_CFG 137 138 @@@@ENC_SET_CFG 139 @@@@ENC_SET_CFG2 140 141 write_ivf_file_header(outfile, &cfg, 0); 142 143 @@@@TWOPASS_LOOP_BEGIN 144 145 /* Open input file for this encoding pass */ 146 if(!(infile = fopen(argv[3], "rb"))) 147 die("Failed to open %s for reading", argv[3]); 148 149 @@@@@@@@ENC_INIT 150 151 frame_avail = 1; 152 got_data = 0; 153 while(frame_avail || got_data) { 154 vpx_codec_iter_t iter = NULL; 155 const vpx_codec_cx_pkt_t *pkt; 156 157 @@@@@@@@@@@@PER_FRAME_CFG 158 @@@@@@@@@@@@ENCODE_FRAME 159 got_data = 0; 160 while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { 161 got_data = 1; 162 switch(pkt->kind) { 163 @@@@@@@@@@@@@@@@PROCESS_FRAME 164 @@@@@@@@@@@@@@@@PROCESS_STATS 165 default: 166 break; 167 } 168 printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT 169 && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":"."); 170 fflush(stdout); 171 } 172 frame_cnt++; 173 } 174 printf("\n"); 175 fclose(infile); 176 @@@@TWOPASS_LOOP_END 177 178 printf("Processed %d frames.\n",frame_cnt-1); 179 @@@@DESTROY 180 181 /* Try to rewrite the file header with the actual frame count */ 182 if(!fseek(outfile, 0, SEEK_SET)) 183 write_ivf_file_header(outfile, &cfg, frame_cnt-1); 184 fclose(outfile); 185 return EXIT_SUCCESS; 186 } 187