190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/* 2f71323e297a928af368937089d3ed71239786f86Andreas Huber * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber * 4f71323e297a928af368937089d3ed71239786f86Andreas Huber * Use of this source code is governed by a BSD-style license 5f71323e297a928af368937089d3ed71239786f86Andreas Huber * that can be found in the LICENSE file in the root of the source 6f71323e297a928af368937089d3ed71239786f86Andreas Huber * tree. An additional intellectual property rights grant can be found 7f71323e297a928af368937089d3ed71239786f86Andreas Huber * in the file PATENTS. All contributing project authors may 8f71323e297a928af368937089d3ed71239786f86Andreas Huber * be found in the AUTHORS file in the root of the source tree. 990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber */ 1090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 1190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 1290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/* 1390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@*INTRODUCTION 1490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber */ 1590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <stdio.h> 1690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <stdlib.h> 1790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <stdarg.h> 1890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <string.h> 1990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define VPX_CODEC_DISABLE_COMPAT 1 20f71323e297a928af368937089d3ed71239786f86Andreas Huber#include "vpx/vpx_encoder.h" 21f71323e297a928af368937089d3ed71239786f86Andreas Huber#include "vpx/vp8cx.h" 2279f15823c34ae1e423108295e416213200bb280fAndreas Huber#define interface (vpx_codec_vp8_cx()) 2390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define fourcc 0x30385056 2490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@EXTRA_INCLUDES 2590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 2690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define IVF_FILE_HDR_SZ (32) 2790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define IVF_FRAME_HDR_SZ (12) 2890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 2990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic void mem_put_le16(char *mem, unsigned int val) { 3090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem[0] = val; 3190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem[1] = val>>8; 3290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 3390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 3490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic void mem_put_le32(char *mem, unsigned int val) { 3590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem[0] = val; 3690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem[1] = val>>8; 3790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem[2] = val>>16; 3890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem[3] = val>>24; 3990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 4090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 4190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic void die(const char *fmt, ...) { 4290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber va_list ap; 4390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 4490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber va_start(ap, fmt); 4590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber vprintf(fmt, ap); 4690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if(fmt[strlen(fmt)-1] != '\n') 4790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber printf("\n"); 4890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber exit(EXIT_FAILURE); 4990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 5090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 5190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@DIE_CODEC 5290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 5390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic int read_frame(FILE *f, vpx_image_t *img) { 5490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber size_t nbytes, to_read; 5590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int res = 1; 5690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 5790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber to_read = img->w*img->h*3/2; 5890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber nbytes = fread(img->planes[0], 1, to_read, f); 5990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if(nbytes != to_read) { 6090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber res = 0; 6190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if(nbytes > 0) 6290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber printf("Warning: Read partial frame. Check your width & height!\n"); 6390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 6490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return res; 6590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 6690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 6790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic void write_ivf_file_header(FILE *outfile, 6890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber const vpx_codec_enc_cfg_t *cfg, 6990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int frame_cnt) { 7090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char header[32]; 7190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 7290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS) 7390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return; 7490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber header[0] = 'D'; 7590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber header[1] = 'K'; 7690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber header[2] = 'I'; 7790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber header[3] = 'F'; 7890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le16(header+4, 0); /* version */ 7990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le16(header+6, 32); /* headersize */ 8090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le32(header+8, fourcc); /* headersize */ 8190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le16(header+12, cfg->g_w); /* width */ 8290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le16(header+14, cfg->g_h); /* height */ 8390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le32(header+16, cfg->g_timebase.den); /* rate */ 8490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le32(header+20, cfg->g_timebase.num); /* scale */ 8590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le32(header+24, frame_cnt); /* length */ 8690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le32(header+28, 0); /* unused */ 8790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 88538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if(fwrite(header, 1, 32, outfile)); 8990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 9090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 9190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 9290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic void write_ivf_frame_header(FILE *outfile, 9390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber const vpx_codec_cx_pkt_t *pkt) 9490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 9590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char header[12]; 9690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber vpx_codec_pts_t pts; 9790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 9890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if(pkt->kind != VPX_CODEC_CX_FRAME_PKT) 9990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return; 10090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 10190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber pts = pkt->data.frame.pts; 10290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le32(header, pkt->data.frame.sz); 10390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le32(header+4, pts&0xFFFFFFFF); 10490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber mem_put_le32(header+8, pts >> 32); 10590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 106538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if(fwrite(header, 1, 12, outfile)); 10790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 10890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 10990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberint main(int argc, char **argv) { 11090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber FILE *infile, *outfile; 11190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber vpx_codec_ctx_t codec; 11290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber vpx_codec_enc_cfg_t cfg; 11390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int frame_cnt = 0; 11490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned char file_hdr[IVF_FILE_HDR_SZ]; 11590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned char frame_hdr[IVF_FRAME_HDR_SZ]; 11690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber vpx_image_t raw; 11790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber vpx_codec_err_t res; 11890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber long width; 11990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber long height; 12090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int frame_avail; 12190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int got_data; 12290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int flags = 0; 12390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@TWOPASS_VARS 12490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 12590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber /* Open files */ 12690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@USAGE 12790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber width = strtol(argv[1], NULL, 0); 12890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber height = strtol(argv[2], NULL, 0); 12990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if(width < 16 || width%2 || height <16 || height%2) 13090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber die("Invalid resolution: %ldx%ld", width, height); 131f71323e297a928af368937089d3ed71239786f86Andreas Huber if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1)) 13290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber die("Faile to allocate image", width, height); 13390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if(!(outfile = fopen(argv[4], "wb"))) 13490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber die("Failed to open %s for writing", argv[4]); 13590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 13690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber printf("Using %s\n",vpx_codec_iface_name(interface)); 13790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 13890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@ENC_DEF_CFG 13990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 14090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@ENC_SET_CFG 14190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@ENC_SET_CFG2 14290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 14390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber write_ivf_file_header(outfile, &cfg, 0); 14490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 14590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@TWOPASS_LOOP_BEGIN 14690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 14790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber /* Open input file for this encoding pass */ 14890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if(!(infile = fopen(argv[3], "rb"))) 14990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber die("Failed to open %s for reading", argv[3]); 15090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 15190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@@@@@ENC_INIT 15290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 15390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber frame_avail = 1; 15490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber got_data = 0; 15590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber while(frame_avail || got_data) { 15690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber vpx_codec_iter_t iter = NULL; 15790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber const vpx_codec_cx_pkt_t *pkt; 15890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 15990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@@@@@@@@@PER_FRAME_CFG 16090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@@@@@@@@@ENCODE_FRAME 16190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber got_data = 0; 16290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { 16390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber got_data = 1; 16490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber switch(pkt->kind) { 16590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@@@@@@@@@@@@@PROCESS_FRAME 16690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@@@@@@@@@@@@@PROCESS_STATS 16790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber default: 16890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber break; 16990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 17090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT 17190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":"."); 17290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fflush(stdout); 17390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 17490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber frame_cnt++; 17590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 17690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber printf("\n"); 17790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fclose(infile); 17890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@TWOPASS_LOOP_END 17990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 18090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber printf("Processed %d frames.\n",frame_cnt-1); 18190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber@@@@DESTROY 18290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 18390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber /* Try to rewrite the file header with the actual frame count */ 18490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if(!fseek(outfile, 0, SEEK_SET)) 18590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber write_ivf_file_header(outfile, &cfg, frame_cnt-1); 18690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fclose(outfile); 18790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return EXIT_SUCCESS; 18890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 189