1dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org/* 2dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org * 4dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org * Use of this source code is governed by a BSD-style license 5dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org * that can be found in the LICENSE file in the root of the source 6dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org * tree. An additional intellectual property rights grant can be found 7dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org * in the file PATENTS. All contributing project authors may 8dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org * be found in the AUTHORS file in the root of the source tree. 9dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org */ 10dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org 11dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Simple Encoder 12dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// ============== 13dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 14dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// This is an example of a simple encoder loop. It takes an input file in 15dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// YV12 format, passes it through the encoder, and writes the compressed 16dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// frames to disk in IVF format. Other decoder examples build upon this 17dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// one. 18dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 19dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// The details of the IVF format have been elided from this example for 20dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// simplicity of presentation, as IVF files will not generally be used by 21dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// your application. In general, an IVF file consists of a file header, 22dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// followed by a variable number of frames. Each frame consists of a frame 23dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// header followed by a variable length payload. The length of the payload 24dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// is specified in the first four bytes of the frame header. The payload is 25dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// the raw compressed data. 26dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 27dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Standard Includes 28dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// ----------------- 29dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// For encoders, you only have to include `vpx_encoder.h` and then any 30dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// header files for the specific codecs you use. In this case, we're using 3187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org// vp8. 32dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 33dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Getting The Default Configuration 34dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// --------------------------------- 35dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Encoders have the notion of "usage profiles." For example, an encoder 36dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// may want to publish default configurations for both a video 37411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org// conferencing application and a best quality offline encoder. These 38dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// obviously have very different default settings. Consult the 39dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// documentation for your codec to see if it provides any default 40dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// configurations. All codecs provide a default configuration, number 0, 41dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// which is valid for material in the vacinity of QCIF/QVGA. 42dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 43dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Updating The Configuration 44dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// --------------------------------- 45dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Almost all applications will want to update the default configuration 46dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// with settings specific to their usage. Here we set the width and height 47dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// of the video file to that specified on the command line. We also scale 48dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// the default bitrate based on the ratio between the default resolution 49dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// and the resolution specified on the command line. 50dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 51dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Initializing The Codec 52dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// ---------------------- 53dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// The encoder is initialized by the following code. 54dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 55dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Encoding A Frame 56dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// ---------------- 57dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// The frame is read as a continuous block (size width * height * 3 / 2) 58dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// from the input file. If a frame was read (the input file has not hit 59dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// EOF) then the frame is passed to the encoder. Otherwise, a NULL 60dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// is passed, indicating the End-Of-Stream condition to the encoder. The 61dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// `frame_cnt` is reused as the presentation time stamp (PTS) and each 62dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// frame is shown for one frame-time in duration. The flags parameter is 63dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// unused in this example. The deadline is set to VPX_DL_REALTIME to 64dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// make the example run as quickly as possible. 6593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org 6693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Forced Keyframes 6793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// ---------------- 6893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Keyframes can be forced by setting the VPX_EFLAG_FORCE_KF bit of the 6993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// flags passed to `vpx_codec_control()`. In this example, we force a 7093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// keyframe every <keyframe-interval> frames. Note, the output stream can 7193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// contain additional keyframes beyond those that have been forced using the 7293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// VPX_EFLAG_FORCE_KF flag because of automatic keyframe placement by the 7393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// encoder. 74dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 75dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Processing The Encoded Data 76dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// --------------------------- 77dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Each packet of type `VPX_CODEC_CX_FRAME_PKT` contains the encoded data 78dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// for this frame. We write a IVF frame header, followed by the raw data. 79dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 80dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Cleanup 81dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// ------- 82dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// The `vpx_codec_destroy` call frees any memory allocated by the codec. 83dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// 84dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// Error Handling 85dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// -------------- 86dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// This example does not special case any error return codes. If there was 87dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// an error, a descriptive message is printed and the program exits. With 88dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// few exeptions, vpx_codec functions return an enumerated error status, 89dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org// with the value `0` indicating success. 90411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org// 91411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org// Error Resiliency Features 92411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org// ------------------------- 93411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org// Error resiliency is controlled by the g_error_resilient member of the 94411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org// configuration structure. Use the `decode_with_drops` example to decode with 95411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org// frames 5-10 dropped. Compare the output for a file encoded with this example 96411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org// versus one encoded with the `simple_encoder` example. 97dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org 98dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#include <stdio.h> 99dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#include <stdlib.h> 100dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#include <string.h> 10176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 102dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#include "vpx/vpx_encoder.h" 103dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org 10476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include "./tools_common.h" 10576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include "./video_writer.h" 106dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org 10776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgstatic const char *exec_name; 108dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org 10976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgvoid usage_exit() { 110411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org fprintf(stderr, 111411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org "Usage: %s <codec> <width> <height> <infile> <outfile> " 11293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org "<keyframe-interval> [<error-resilient>]\nSee comments in " 11393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org "simple_encoder.c for more information.\n", 11476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org exec_name); 11576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org exit(EXIT_FAILURE); 116dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org} 117dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org 11841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.orgstatic int encode_frame(vpx_codec_ctx_t *codec, 11941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org vpx_image_t *img, 12041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org int frame_index, 12141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org int flags, 12241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org VpxVideoWriter *writer) { 12341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org int got_pkts = 0; 12476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org vpx_codec_iter_t iter = NULL; 12576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org const vpx_codec_cx_pkt_t *pkt = NULL; 12693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, 12793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org flags, VPX_DL_GOOD_QUALITY); 12876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (res != VPX_CODEC_OK) 12976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die_codec(codec, "Failed to encode frame"); 13076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 13176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) { 13241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org got_pkts = 1; 13341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org 13476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { 13576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; 13676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (!vpx_video_writer_write_frame(writer, 13776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org pkt->data.frame.buf, 13876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org pkt->data.frame.sz, 13976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org pkt->data.frame.pts)) { 14076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die_codec(codec, "Failed to write compressed frame"); 14176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org } 14276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org printf(keyframe ? "K" : "."); 14376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org fflush(stdout); 144dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org } 14576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org } 14641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org 14741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org return got_pkts; 148dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org} 149dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org 150dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.orgint main(int argc, char **argv) { 15176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org FILE *infile = NULL; 15276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org vpx_codec_ctx_t codec; 15376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org vpx_codec_enc_cfg_t cfg; 15476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org int frame_count = 0; 15576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org vpx_image_t raw; 15676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org vpx_codec_err_t res; 15776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org VpxVideoInfo info = {0}; 15876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org VpxVideoWriter *writer = NULL; 15976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org const VpxInterface *encoder = NULL; 16076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org const int fps = 30; // TODO(dkovalev) add command line argument 16176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument 16293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org int keyframe_interval = 0; 16393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org 16493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org // TODO(dkovalev): Add some simple command line parsing code to make the 16593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org // command line more flexible. 166411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org const char *codec_arg = NULL; 167411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org const char *width_arg = NULL; 168411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org const char *height_arg = NULL; 169411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org const char *infile_arg = NULL; 170411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org const char *outfile_arg = NULL; 17193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org const char *keyframe_interval_arg = NULL; 17276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 17376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org exec_name = argv[0]; 17476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 17593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org if (argc < 7) 17676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die("Invalid number of arguments"); 17776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 178411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org codec_arg = argv[1]; 179411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org width_arg = argv[2]; 180411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org height_arg = argv[3]; 181411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org infile_arg = argv[4]; 182411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org outfile_arg = argv[5]; 18393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org keyframe_interval_arg = argv[6]; 184411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org 18576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org encoder = get_vpx_encoder_by_name(codec_arg); 18676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (!encoder) 18776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die("Unsupported codec."); 18876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 18976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org info.codec_fourcc = encoder->fourcc; 19076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org info.frame_width = strtol(width_arg, NULL, 0); 19176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org info.frame_height = strtol(height_arg, NULL, 0); 19276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org info.time_base.numerator = 1; 19376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org info.time_base.denominator = fps; 19476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 19576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (info.frame_width <= 0 || 19676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org info.frame_height <= 0 || 19776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org (info.frame_width % 2) != 0 || 19876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org (info.frame_height % 2) != 0) { 19976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); 20076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org } 20176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 20276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, 20376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org info.frame_height, 1)) { 20476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die("Failed to allocate image."); 20576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org } 20676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 20793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org keyframe_interval = strtol(keyframe_interval_arg, NULL, 0); 20893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org if (keyframe_interval < 0) 20993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org die("Invalid keyframe interval value."); 21093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org 211ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); 21276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 213ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); 21476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (res) 21576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die_codec(&codec, "Failed to get default codec config."); 21676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 21776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org cfg.g_w = info.frame_width; 21876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org cfg.g_h = info.frame_height; 21976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org cfg.g_timebase.num = info.time_base.numerator; 22076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org cfg.g_timebase.den = info.time_base.denominator; 22176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org cfg.rc_target_bitrate = bitrate; 22293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org cfg.g_error_resilient = argc > 7 ? strtol(argv[7], NULL, 0) : 0; 22376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 22476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info); 22576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (!writer) 22676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die("Failed to open %s for writing.", outfile_arg); 22776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 22876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (!(infile = fopen(infile_arg, "rb"))) 22976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die("Failed to open %s for reading.", infile_arg); 23076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 231ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) 23276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die_codec(&codec, "Failed to initialize encoder"); 23376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 23441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org // Encode frames. 23593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org while (vpx_img_read(&raw, infile)) { 23693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org int flags = 0; 23793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org if (keyframe_interval > 0 && frame_count % keyframe_interval == 0) 23893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org flags |= VPX_EFLAG_FORCE_KF; 23993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org encode_frame(&codec, &raw, frame_count++, flags, writer); 24093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org } 24141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org 24241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org // Flush encoder. 24341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org while (encode_frame(&codec, NULL, -1, 0, writer)) {}; 24476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 24576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org printf("\n"); 24676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org fclose(infile); 24776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org printf("Processed %d frames.\n", frame_count); 24876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 24976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org vpx_img_free(&raw); 25076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (vpx_codec_destroy(&codec)) 25176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org die_codec(&codec, "Failed to destroy codec."); 25276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 25376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org vpx_video_writer_close(writer); 25476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org 25576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org return EXIT_SUCCESS; 256dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org} 257