00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #include <string.h>
00051
00052 #include "vpx/vp8cx.h"
00053 #include "vpx/vpx_encoder.h"
00054 #include "vp8/common/common.h"
00055
00056 #include "../tools_common.h"
00057 #include "../video_writer.h"
00058
00059 static const char *exec_name;
00060
00061 void usage_exit(void) {
00062 fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile> <frame>\n",
00063 exec_name);
00064 exit(EXIT_FAILURE);
00065 }
00066
00067 static int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img,
00068 int frame_index, VpxVideoWriter *writer) {
00069 int got_pkts = 0;
00070 vpx_codec_iter_t iter = NULL;
00071 const vpx_codec_cx_pkt_t *pkt = NULL;
00072 const vpx_codec_err_t res =
00073 vpx_codec_encode(codec, img, frame_index, 1, 0, VPX_DL_GOOD_QUALITY);
00074 if (res != VPX_CODEC_OK) die_codec(codec, "Failed to encode frame");
00075
00076 while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
00077 got_pkts = 1;
00078
00079 if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
00080 const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
00081 if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
00082 pkt->data.frame.sz,
00083 pkt->data.frame.pts)) {
00084 die_codec(codec, "Failed to write compressed frame");
00085 }
00086
00087 printf(keyframe ? "K" : ".");
00088 fflush(stdout);
00089 }
00090 }
00091
00092 return got_pkts;
00093 }
00094
00095 int main(int argc, char **argv) {
00096 FILE *infile = NULL;
00097 vpx_codec_ctx_t codec;
00098 vpx_codec_enc_cfg_t cfg;
00099 int frame_count = 0;
00100 vpx_image_t raw;
00101 vpx_codec_err_t res;
00102 VpxVideoInfo info;
00103 VpxVideoWriter *writer = NULL;
00104 const VpxInterface *encoder = NULL;
00105 int update_frame_num = 0;
00106 const int fps = 30;
00107 const int bitrate = 200;
00108
00109 vp8_zero(codec);
00110 vp8_zero(cfg);
00111 vp8_zero(info);
00112
00113 exec_name = argv[0];
00114
00115 if (argc != 6) die("Invalid number of arguments");
00116
00117
00118 encoder = get_vpx_encoder_by_name("vp8");
00119 if (!encoder) die("Unsupported codec.");
00120
00121 update_frame_num = atoi(argv[5]);
00122 if (!update_frame_num) die("Couldn't parse frame number '%s'\n", argv[5]);
00123
00124 info.codec_fourcc = encoder->fourcc;
00125 info.frame_width = (int)strtol(argv[1], NULL, 0);
00126 info.frame_height = (int)strtol(argv[2], NULL, 0);
00127 info.time_base.numerator = 1;
00128 info.time_base.denominator = fps;
00129
00130 if (info.frame_width <= 0 || info.frame_height <= 0 ||
00131 (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
00132 die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
00133 }
00134
00135 if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
00136 info.frame_height, 1)) {
00137 die("Failed to allocate image.");
00138 }
00139
00140 printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
00141
00142 res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
00143 if (res) die_codec(&codec, "Failed to get default codec config.");
00144
00145 cfg.g_w = info.frame_width;
00146 cfg.g_h = info.frame_height;
00147 cfg.g_timebase.num = info.time_base.numerator;
00148 cfg.g_timebase.den = info.time_base.denominator;
00149 cfg.rc_target_bitrate = bitrate;
00150
00151 writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
00152 if (!writer) die("Failed to open %s for writing.", argv[4]);
00153
00154 if (!(infile = fopen(argv[3], "rb")))
00155 die("Failed to open %s for reading.", argv[3]);
00156
00157 if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
00158 die_codec(&codec, "Failed to initialize encoder");
00159
00160
00161 while (vpx_img_read(&raw, infile)) {
00162 if (frame_count + 1 == update_frame_num) {
00163 vpx_ref_frame_t ref;
00164 ref.frame_type = VP8_LAST_FRAME;
00165 ref.img = raw;
00166 if (vpx_codec_control(&codec, VP8_SET_REFERENCE, &ref))
00167 die_codec(&codec, "Failed to set reference frame");
00168 }
00169
00170 encode_frame(&codec, &raw, frame_count++, writer);
00171 }
00172
00173
00174 while (encode_frame(&codec, NULL, -1, writer)) {
00175 }
00176
00177 printf("\n");
00178 fclose(infile);
00179 printf("Processed %d frames.\n", frame_count);
00180
00181 vpx_img_free(&raw);
00182 if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
00183
00184 vpx_video_writer_close(writer);
00185
00186 return EXIT_SUCCESS;
00187 }