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 if(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 if(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 unsigned char file_hdr[IVF_FILE_HDR_SZ]; 115 unsigned char frame_hdr[IVF_FRAME_HDR_SZ]; 116 vpx_image_t raw; 117 vpx_codec_err_t res; 118 long width; 119 long height; 120 int frame_avail; 121 int got_data; 122 int flags = 0; 123 @@@@TWOPASS_VARS 124 125 /* Open files */ 126 @@@@USAGE 127 width = strtol(argv[1], NULL, 0); 128 height = strtol(argv[2], NULL, 0); 129 if(width < 16 || width%2 || height <16 || height%2) 130 die("Invalid resolution: %ldx%ld", width, height); 131 if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1)) 132 die("Faile to allocate image", width, height); 133 if(!(outfile = fopen(argv[4], "wb"))) 134 die("Failed to open %s for writing", argv[4]); 135 136 printf("Using %s\n",vpx_codec_iface_name(interface)); 137 138 @@@@ENC_DEF_CFG 139 140 @@@@ENC_SET_CFG 141 @@@@ENC_SET_CFG2 142 143 write_ivf_file_header(outfile, &cfg, 0); 144 145 @@@@TWOPASS_LOOP_BEGIN 146 147 /* Open input file for this encoding pass */ 148 if(!(infile = fopen(argv[3], "rb"))) 149 die("Failed to open %s for reading", argv[3]); 150 151 @@@@@@@@ENC_INIT 152 153 frame_avail = 1; 154 got_data = 0; 155 while(frame_avail || got_data) { 156 vpx_codec_iter_t iter = NULL; 157 const vpx_codec_cx_pkt_t *pkt; 158 159 @@@@@@@@@@@@PER_FRAME_CFG 160 @@@@@@@@@@@@ENCODE_FRAME 161 got_data = 0; 162 while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { 163 got_data = 1; 164 switch(pkt->kind) { 165 @@@@@@@@@@@@@@@@PROCESS_FRAME 166 @@@@@@@@@@@@@@@@PROCESS_STATS 167 default: 168 break; 169 } 170 printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT 171 && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":"."); 172 fflush(stdout); 173 } 174 frame_cnt++; 175 } 176 printf("\n"); 177 fclose(infile); 178 @@@@TWOPASS_LOOP_END 179 180 printf("Processed %d frames.\n",frame_cnt-1); 181 @@@@DESTROY 182 183 /* Try to rewrite the file header with the actual frame count */ 184 if(!fseek(outfile, 0, SEEK_SET)) 185 write_ivf_file_header(outfile, &cfg, frame_cnt-1); 186 fclose(outfile); 187 return EXIT_SUCCESS; 188 } 189