1/* 2 * Copyright (c) 2014 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#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14 15#include "vpx/vpx_encoder.h" 16#include "vpx/vp8cx.h" 17 18#include "../tools_common.h" 19#include "../video_writer.h" 20 21static const char *exec_name; 22 23void usage_exit(void) { 24 fprintf(stderr, "vp9_lossless_encoder: Example demonstrating VP9 lossless " 25 "encoding feature. Supports raw input only.\n"); 26 fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name); 27 exit(EXIT_FAILURE); 28} 29 30static int encode_frame(vpx_codec_ctx_t *codec, 31 vpx_image_t *img, 32 int frame_index, 33 int flags, 34 VpxVideoWriter *writer) { 35 int got_pkts = 0; 36 vpx_codec_iter_t iter = NULL; 37 const vpx_codec_cx_pkt_t *pkt = NULL; 38 const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, 39 flags, VPX_DL_GOOD_QUALITY); 40 if (res != VPX_CODEC_OK) 41 die_codec(codec, "Failed to encode frame"); 42 43 while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) { 44 got_pkts = 1; 45 46 if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { 47 const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; 48 if (!vpx_video_writer_write_frame(writer, 49 pkt->data.frame.buf, 50 pkt->data.frame.sz, 51 pkt->data.frame.pts)) { 52 die_codec(codec, "Failed to write compressed frame"); 53 } 54 printf(keyframe ? "K" : "."); 55 fflush(stdout); 56 } 57 } 58 59 return got_pkts; 60} 61 62int main(int argc, char **argv) { 63 FILE *infile = NULL; 64 vpx_codec_ctx_t codec; 65 vpx_codec_enc_cfg_t cfg; 66 int frame_count = 0; 67 vpx_image_t raw; 68 vpx_codec_err_t res; 69 VpxVideoInfo info = {0}; 70 VpxVideoWriter *writer = NULL; 71 const VpxInterface *encoder = NULL; 72 const int fps = 30; 73 74 exec_name = argv[0]; 75 76 if (argc < 5) 77 die("Invalid number of arguments"); 78 79 encoder = get_vpx_encoder_by_name("vp9"); 80 if (!encoder) 81 die("Unsupported codec."); 82 83 info.codec_fourcc = encoder->fourcc; 84 info.frame_width = strtol(argv[1], NULL, 0); 85 info.frame_height = strtol(argv[2], NULL, 0); 86 info.time_base.numerator = 1; 87 info.time_base.denominator = fps; 88 89 if (info.frame_width <= 0 || 90 info.frame_height <= 0 || 91 (info.frame_width % 2) != 0 || 92 (info.frame_height % 2) != 0) { 93 die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); 94 } 95 96 if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, 97 info.frame_height, 1)) { 98 die("Failed to allocate image."); 99 } 100 101 printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); 102 103 res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); 104 if (res) 105 die_codec(&codec, "Failed to get default codec config."); 106 107 cfg.g_w = info.frame_width; 108 cfg.g_h = info.frame_height; 109 cfg.g_timebase.num = info.time_base.numerator; 110 cfg.g_timebase.den = info.time_base.denominator; 111 112 writer = vpx_video_writer_open(argv[4], kContainerIVF, &info); 113 if (!writer) 114 die("Failed to open %s for writing.", argv[4]); 115 116 if (!(infile = fopen(argv[3], "rb"))) 117 die("Failed to open %s for reading.", argv[3]); 118 119 if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) 120 die_codec(&codec, "Failed to initialize encoder"); 121 122 if (vpx_codec_control_(&codec, VP9E_SET_LOSSLESS, 1)) 123 die_codec(&codec, "Failed to use lossless mode"); 124 125 // Encode frames. 126 while (vpx_img_read(&raw, infile)) { 127 encode_frame(&codec, &raw, frame_count++, 0, writer); 128 } 129 130 // Flush encoder. 131 while (encode_frame(&codec, NULL, -1, 0, writer)) {} 132 133 printf("\n"); 134 fclose(infile); 135 printf("Processed %d frames.\n", frame_count); 136 137 vpx_img_free(&raw); 138 if (vpx_codec_destroy(&codec)) 139 die_codec(&codec, "Failed to destroy codec."); 140 141 vpx_video_writer_close(writer); 142 143 return EXIT_SUCCESS; 144} 145