Adding video reader/writer APIs.
Right now only IVF format is supported which is enough for example code. Other formats like y4m, webm, raw yuv will be supported later. Change-Id: I34c6f20731c1851947587ca5c589d7856b675164
This commit is contained in:
parent
cebda1b65c
commit
37e6fd3d76
13
examples.mk
13
examples.mk
@ -77,20 +77,29 @@ EXAMPLES-$(CONFIG_VP8_DECODER) += simple_decoder.c
|
||||
simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
|
||||
simple_decoder.SRCS += ivfdec.h ivfdec.c
|
||||
simple_decoder.SRCS += tools_common.h tools_common.c
|
||||
simple_decoder.SRCS += video_common.h
|
||||
simple_decoder.SRCS += video_reader.h video_reader.c
|
||||
simple_decoder.DESCRIPTION = Simplified decoder loop
|
||||
EXAMPLES-$(CONFIG_VP8_DECODER) += postproc.c
|
||||
postproc.SRCS += ivfdec.h ivfdec.c
|
||||
postproc.SRCS += tools_common.h tools_common.c
|
||||
postproc.SRCS += video_common.h
|
||||
postproc.SRCS += video_reader.h video_reader.c
|
||||
postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7
|
||||
postproc.DESCRIPTION = Decoder postprocessor control
|
||||
EXAMPLES-$(CONFIG_VP8_DECODER) += decode_to_md5.c
|
||||
decode_to_md5.SRCS += md5_utils.h md5_utils.c
|
||||
decode_to_md5.SRCS += ivfdec.h ivfdec.c
|
||||
decode_to_md5.SRCS += tools_common.h tools_common.c
|
||||
decode_to_md5.SRCS += video_common.h
|
||||
decode_to_md5.SRCS += video_reader.h video_reader.c
|
||||
decode_to_md5.GUID = 59120B9B-2735-4BFE-B022-146CA340FE42
|
||||
decode_to_md5.DESCRIPTION = Frame by frame MD5 checksum
|
||||
|
||||
EXAMPLES-$(CONFIG_VP8_ENCODER) += simple_encoder.c
|
||||
simple_encoder.SRCS += ivfenc.h ivfenc.c
|
||||
simple_encoder.SRCS += tools_common.h tools_common.c
|
||||
simple_encoder.SRCS += video_common.h
|
||||
simple_encoder.SRCS += video_writer.h video_writer.c
|
||||
simple_encoder.GUID = 4607D299-8A71-4D2C-9B1D-071899B6FBFD
|
||||
simple_encoder.DESCRIPTION = Simplified encoder loop
|
||||
EXAMPLES-$(CONFIG_VP8_ENCODER) += twopass_encoder.c
|
||||
@ -103,6 +112,8 @@ ifeq ($(CONFIG_DECODERS),yes)
|
||||
EXAMPLES-$(CONFIG_VP8_ENCODER) += decode_with_drops.c
|
||||
decode_with_drops.SRCS += ivfdec.h ivfdec.c
|
||||
decode_with_drops.SRCS += tools_common.h tools_common.c
|
||||
decode_with_drops.SRCS += video_common.h
|
||||
decode_with_drops.SRCS += video_reader.h video_reader.c
|
||||
endif
|
||||
decode_with_drops.GUID = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26
|
||||
decode_with_drops.DESCRIPTION = Drops frames while decoding
|
||||
|
@ -38,9 +38,9 @@
|
||||
#include "vpx/vp8dx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
|
||||
#include "./ivfdec.h"
|
||||
#include "./md5_utils.h"
|
||||
#include "./tools_common.h"
|
||||
#include "./video_reader.h"
|
||||
#include "./vpx_config.h"
|
||||
|
||||
static void get_image_md5(const vpx_image_t *img, unsigned char digest[16]) {
|
||||
@ -79,41 +79,42 @@ void usage_exit() {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile;
|
||||
int frame_cnt = 0;
|
||||
FILE *outfile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_iface_t *iface;
|
||||
int flags = 0, frame_cnt = 0;
|
||||
vpx_video_t *video;
|
||||
vpx_codec_iface_t *iface = NULL;
|
||||
VpxVideoReader *reader = NULL;
|
||||
const VpxVideoInfo *info = NULL;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 3)
|
||||
die("Invalid number of arguments");
|
||||
die("Invalid number of arguments.");
|
||||
|
||||
if (!(infile = fopen(argv[1], "rb")))
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
reader = vpx_video_reader_open(argv[1]);
|
||||
if (!reader)
|
||||
die("Failed to open %s for reading.", argv[1]);
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
die("Failed to open %s for writing.", argv[2]);
|
||||
|
||||
video = vpx_video_open_file(infile);
|
||||
if (!video)
|
||||
die("%s is not an IVF file.", argv[1]);
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
iface = get_codec_interface(vpx_video_get_fourcc(video));
|
||||
iface = get_codec_interface(info->codec_fourcc);
|
||||
if (!iface)
|
||||
die("Unknown FOURCC code.");
|
||||
die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(iface));
|
||||
|
||||
if (vpx_codec_dec_init(&codec, iface, NULL, flags))
|
||||
if (vpx_codec_dec_init(&codec, iface, NULL, 0))
|
||||
die_codec(&codec, "Failed to initialize decoder");
|
||||
|
||||
while (vpx_video_read_frame(video)) {
|
||||
while (vpx_video_reader_read_frame(reader)) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img = NULL;
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame = vpx_video_get_frame(video, &frame_size);
|
||||
const unsigned char *frame = vpx_video_reader_get_frame(reader,
|
||||
&frame_size);
|
||||
if (vpx_codec_decode(&codec, frame, frame_size, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
|
||||
@ -129,11 +130,10 @@ int main(int argc, char **argv) {
|
||||
|
||||
printf("Processed %d frames.\n", frame_cnt);
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
vpx_video_close(video);
|
||||
vpx_video_reader_close(reader);
|
||||
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -56,14 +56,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./ivfdec.h"
|
||||
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
|
||||
#include "vpx/vp8dx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
|
||||
#include "./tools_common.h"
|
||||
#include "./video_reader.h"
|
||||
#include "./vpx_config.h"
|
||||
|
||||
static const char *exec_name;
|
||||
@ -74,52 +73,55 @@ void usage_exit() {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile;
|
||||
int frame_cnt = 0;
|
||||
FILE *outfile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_iface_t *iface;
|
||||
int flags = 0, frame_cnt = 0;
|
||||
vpx_video_t *video;
|
||||
int n, m, is_range;
|
||||
char *nptr;
|
||||
vpx_codec_iface_t *iface = NULL;
|
||||
VpxVideoReader *reader = NULL;
|
||||
const VpxVideoInfo *info = NULL;
|
||||
int n = 0;
|
||||
int m = 0;
|
||||
int is_range = 0;
|
||||
char *nptr = NULL;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 4)
|
||||
die("Invalid number of arguments");
|
||||
die("Invalid number of arguments.");
|
||||
|
||||
if (!(infile = fopen(argv[1], "rb")))
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
reader = vpx_video_reader_open(argv[1]);
|
||||
if (!reader)
|
||||
die("Failed to open %s for reading.", argv[1]);
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
die("Failed to open %s for writing.", argv[2]);
|
||||
|
||||
n = strtol(argv[3], &nptr, 0);
|
||||
m = strtol(nptr + 1, NULL, 0);
|
||||
is_range = (*nptr == '-');
|
||||
if (!n || !m || (*nptr != '-' && *nptr != '/'))
|
||||
die("Couldn't parse pattern %s\n", argv[3]);
|
||||
die("Couldn't parse pattern %s.\n", argv[3]);
|
||||
|
||||
video = vpx_video_open_file(infile);
|
||||
if (!video)
|
||||
die("%s is not a supported input file.", argv[1]);
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
iface = get_codec_interface(vpx_video_get_fourcc(video));
|
||||
iface = get_codec_interface(info->codec_fourcc);
|
||||
if (!iface)
|
||||
die("Unknown FOURCC code.");
|
||||
die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(iface));
|
||||
|
||||
if (vpx_codec_dec_init(&codec, iface, NULL, flags))
|
||||
die_codec(&codec, "Failed to initialize decoder");
|
||||
if (vpx_codec_dec_init(&codec, iface, NULL, 0))
|
||||
die_codec(&codec, "Failed to initialize decoder.");
|
||||
|
||||
while (vpx_video_read_frame(video)) {
|
||||
while (vpx_video_reader_read_frame(reader)) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img = NULL;
|
||||
size_t frame_size = 0;
|
||||
int skip;
|
||||
const unsigned char *frame = vpx_video_get_frame(video, &frame_size);
|
||||
const unsigned char *frame = vpx_video_reader_get_frame(reader,
|
||||
&frame_size);
|
||||
if (vpx_codec_decode(&codec, frame, frame_size, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
die_codec(&codec, "Failed to decode frame.");
|
||||
|
||||
++frame_cnt;
|
||||
|
||||
@ -140,15 +142,13 @@ int main(int argc, char **argv) {
|
||||
|
||||
printf("Processed %d frames.\n", frame_cnt);
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
|
||||
vpx_video_get_width(video), vpx_video_get_height(video), argv[2]);
|
||||
|
||||
vpx_video_close(video);
|
||||
info->frame_width, info->frame_height, argv[2]);
|
||||
|
||||
vpx_video_reader_close(reader);
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -43,14 +43,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./ivfdec.h"
|
||||
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
|
||||
#include "vpx/vp8dx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
|
||||
#include "./tools_common.h"
|
||||
#include "./video_reader.h"
|
||||
#include "./vpx_config.h"
|
||||
|
||||
static const char *exec_name;
|
||||
@ -61,35 +60,34 @@ void usage_exit() {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_iface_t *iface;
|
||||
int frame_cnt = 0;
|
||||
vpx_video_t *video;
|
||||
FILE *outfile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_err_t res;
|
||||
vpx_codec_iface_t *iface = NULL;
|
||||
VpxVideoReader *reader = NULL;
|
||||
const VpxVideoInfo *info = NULL;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 3)
|
||||
die("Invalid number of arguments");
|
||||
die("Invalid number of arguments.");
|
||||
|
||||
if (!(infile = fopen(argv[1], "rb")))
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
reader = vpx_video_reader_open(argv[1]);
|
||||
if (!reader)
|
||||
die("Failed to open %s for reading.", argv[1]);
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
|
||||
video = vpx_video_open_file(infile);
|
||||
if (!video)
|
||||
die("%s is not a supported input file.", argv[1]);
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
iface = get_codec_interface(vpx_video_get_fourcc(video));
|
||||
iface = get_codec_interface(info->codec_fourcc);
|
||||
if (!iface)
|
||||
die("Unknown FOURCC code.");
|
||||
die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(iface));
|
||||
|
||||
|
||||
res = vpx_codec_dec_init(&codec, iface, NULL, VPX_CODEC_USE_POSTPROC);
|
||||
if (res == VPX_CODEC_INCAPABLE) {
|
||||
printf("NOTICE: Postproc not supported.\n");
|
||||
@ -97,13 +95,14 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
if (res)
|
||||
die_codec(&codec, "Failed to initialize decoder");
|
||||
die_codec(&codec, "Failed to initialize decoder.");
|
||||
|
||||
while (vpx_video_read_frame(video)) {
|
||||
while (vpx_video_reader_read_frame(reader)) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img = NULL;
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame = vpx_video_get_frame(video, &frame_size);
|
||||
const unsigned char *frame = vpx_video_reader_get_frame(reader,
|
||||
&frame_size);
|
||||
|
||||
++frame_cnt;
|
||||
|
||||
@ -111,12 +110,12 @@ int main(int argc, char **argv) {
|
||||
vp8_postproc_cfg_t pp = {0, 0, 0};
|
||||
|
||||
if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
|
||||
die_codec(&codec, "Failed to turn off postproc");
|
||||
die_codec(&codec, "Failed to turn off postproc.");
|
||||
} else if (frame_cnt % 30 == 16) {
|
||||
vp8_postproc_cfg_t pp = {VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE,
|
||||
4, 0};
|
||||
if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
|
||||
die_codec(&codec, "Failed to turn on postproc");
|
||||
die_codec(&codec, "Failed to turn on postproc.");
|
||||
};
|
||||
|
||||
// Decode the frame with 15ms deadline
|
||||
@ -133,11 +132,10 @@ int main(int argc, char **argv) {
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
|
||||
vpx_video_get_width(video), vpx_video_get_height(video), argv[2]);
|
||||
info->frame_width, info->frame_height, argv[2]);
|
||||
|
||||
vpx_video_close(video);
|
||||
vpx_video_reader_close(reader);
|
||||
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -86,8 +86,8 @@
|
||||
#include "vpx/vp8dx.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
|
||||
#include "./ivfdec.h"
|
||||
#include "./tools_common.h"
|
||||
#include "./video_reader.h"
|
||||
#include "./vpx_config.h"
|
||||
|
||||
static const char *exec_name;
|
||||
@ -98,43 +98,44 @@ void usage_exit() {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile;
|
||||
int frame_cnt = 0;
|
||||
FILE *outfile = NULL;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_iface_t *iface;
|
||||
int flags = 0, frame_cnt = 0;
|
||||
vpx_video_t *video;
|
||||
vpx_codec_iface_t *iface = NULL;
|
||||
VpxVideoReader *reader = NULL;
|
||||
const VpxVideoInfo *info = NULL;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 3)
|
||||
die("Invalid number of arguments");
|
||||
die("Invalid number of arguments.");
|
||||
|
||||
if (!(infile = fopen(argv[1], "rb")))
|
||||
die("Failed to open %s for reading", argv[1]);
|
||||
reader = vpx_video_reader_open(argv[1]);
|
||||
if (!reader)
|
||||
die("Failed to open %s for reading.", argv[1]);
|
||||
|
||||
if (!(outfile = fopen(argv[2], "wb")))
|
||||
die("Failed to open %s for writing", argv[2]);
|
||||
die("Failed to open %s for writing.", argv[2]);
|
||||
|
||||
video = vpx_video_open_file(infile);
|
||||
if (!video)
|
||||
die("%s is not an IVF file.", argv[1]);
|
||||
info = vpx_video_reader_get_info(reader);
|
||||
|
||||
iface = get_codec_interface(vpx_video_get_fourcc(video));
|
||||
iface = get_codec_interface(info->codec_fourcc);
|
||||
if (!iface)
|
||||
die("Unknown FOURCC code.");
|
||||
die("Unknown input codec.");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(iface));
|
||||
|
||||
if (vpx_codec_dec_init(&codec, iface, NULL, flags))
|
||||
die_codec(&codec, "Failed to initialize decoder");
|
||||
if (vpx_codec_dec_init(&codec, iface, NULL, 0))
|
||||
die_codec(&codec, "Failed to initialize decoder.");
|
||||
|
||||
while (vpx_video_read_frame(video)) {
|
||||
while (vpx_video_reader_read_frame(reader)) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img = NULL;
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame = vpx_video_get_frame(video, &frame_size);
|
||||
const unsigned char *frame = vpx_video_reader_get_frame(reader,
|
||||
&frame_size);
|
||||
if (vpx_codec_decode(&codec, frame, frame_size, NULL, 0))
|
||||
die_codec(&codec, "Failed to decode frame");
|
||||
die_codec(&codec, "Failed to decode frame.");
|
||||
|
||||
while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
|
||||
vpx_img_write(img, outfile);
|
||||
@ -147,12 +148,11 @@ int main(int argc, char **argv) {
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
|
||||
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
|
||||
vpx_video_get_width(video), vpx_video_get_height(video), argv[2]);
|
||||
info->frame_width, info->frame_height, argv[2]);
|
||||
|
||||
vpx_video_close(video);
|
||||
vpx_video_reader_close(reader);
|
||||
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -83,54 +83,29 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx/vpx_encoder.h"
|
||||
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
|
||||
#include "./tools_common.h"
|
||||
#include "./video_writer.h"
|
||||
|
||||
#define interface (vpx_codec_vp8_cx())
|
||||
#define fourcc 0x30385056
|
||||
|
||||
#define IVF_FILE_HDR_SZ (32)
|
||||
#define IVF_FRAME_HDR_SZ (12)
|
||||
static const char *exec_name;
|
||||
|
||||
static void mem_put_le16(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
}
|
||||
|
||||
static void mem_put_le32(char *mem, unsigned int val) {
|
||||
mem[0] = val;
|
||||
mem[1] = val>>8;
|
||||
mem[2] = val>>16;
|
||||
mem[3] = val>>24;
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
if(fmt[strlen(fmt)-1] != '\n')
|
||||
printf("\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
if(detail)
|
||||
printf(" %s\n",detail);
|
||||
void usage_exit() {
|
||||
fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int read_frame(FILE *f, vpx_image_t *img) {
|
||||
size_t nbytes, to_read;
|
||||
int res = 1;
|
||||
|
||||
to_read = img->w*img->h*3/2;
|
||||
nbytes = fread(img->planes[0], 1, to_read, f);
|
||||
size_t to_read = img->w * img->h * 3 / 2;
|
||||
size_t nbytes = fread(img->planes[0], 1, to_read, f);
|
||||
if (nbytes != to_read) {
|
||||
res = 0;
|
||||
if (nbytes > 0)
|
||||
@ -139,138 +114,100 @@ static int read_frame(FILE *f, vpx_image_t *img) {
|
||||
return res;
|
||||
}
|
||||
|
||||
static void write_ivf_file_header(FILE *outfile,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
char header[32];
|
||||
|
||||
if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
|
||||
return;
|
||||
header[0] = 'D';
|
||||
header[1] = 'K';
|
||||
header[2] = 'I';
|
||||
header[3] = 'F';
|
||||
mem_put_le16(header+4, 0); /* version */
|
||||
mem_put_le16(header+6, 32); /* headersize */
|
||||
mem_put_le32(header+8, fourcc); /* headersize */
|
||||
mem_put_le16(header+12, cfg->g_w); /* width */
|
||||
mem_put_le16(header+14, cfg->g_h); /* height */
|
||||
mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
|
||||
mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
|
||||
mem_put_le32(header+24, frame_cnt); /* length */
|
||||
mem_put_le32(header+28, 0); /* unused */
|
||||
|
||||
(void) fwrite(header, 1, 32, outfile);
|
||||
}
|
||||
|
||||
|
||||
static void write_ivf_frame_header(FILE *outfile,
|
||||
const vpx_codec_cx_pkt_t *pkt)
|
||||
{
|
||||
char header[12];
|
||||
vpx_codec_pts_t pts;
|
||||
|
||||
if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
|
||||
return;
|
||||
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, pkt->data.frame.sz);
|
||||
mem_put_le32(header+4, pts&0xFFFFFFFF);
|
||||
mem_put_le32(header+8, pts >> 32);
|
||||
|
||||
(void) fwrite(header, 1, 12, outfile);
|
||||
static int is_valid_dimension(int value) {
|
||||
return value >= 16 && (value % 2 == 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *infile, *outfile;
|
||||
FILE *infile;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t cfg;
|
||||
int frame_cnt = 0;
|
||||
int frame_count = 0;
|
||||
vpx_image_t raw;
|
||||
vpx_codec_err_t res;
|
||||
long width;
|
||||
long height;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
int flags = 0;
|
||||
VpxVideoInfo info;
|
||||
VpxVideoWriter *writer;
|
||||
const int fps = 30; // TODO(dkovalev) add command line argument
|
||||
const int bitrate = 100; // kbit/s TODO(dkovalev) add command line argument
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
/* Open files */
|
||||
if (argc != 5)
|
||||
die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
|
||||
width = strtol(argv[1], NULL, 0);
|
||||
height = strtol(argv[2], NULL, 0);
|
||||
if(width < 16 || width%2 || height <16 || height%2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
|
||||
die("Faile to allocate image", width, height);
|
||||
if(!(outfile = fopen(argv[4], "wb")))
|
||||
die("Failed to open %s for writing", argv[4]);
|
||||
die("Invalid number of arguments");
|
||||
|
||||
info.codec_fourcc = VP8_FOURCC;
|
||||
info.frame_width = strtol(argv[1], NULL, 0);
|
||||
info.frame_height = strtol(argv[2], NULL, 0);
|
||||
info.time_base.numerator = 1;
|
||||
info.time_base.denominator = fps;
|
||||
|
||||
if (!is_valid_dimension(info.frame_width) ||
|
||||
!is_valid_dimension(info.frame_height))
|
||||
die("Invalid resolution: %dx%d", info.frame_width, info.frame_height);
|
||||
|
||||
if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
|
||||
info.frame_height, 1))
|
||||
die("Failed to allocate image");
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(interface));
|
||||
|
||||
/* Populate encoder configuration */
|
||||
res = vpx_codec_enc_config_default(interface, &cfg, 0);
|
||||
if (res) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Update the default configuration with our settings */
|
||||
cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
|
||||
/ cfg.g_w / cfg.g_h;
|
||||
cfg.g_w = width;
|
||||
cfg.g_h = height;
|
||||
cfg.g_w = info.frame_width;
|
||||
cfg.g_h = info.frame_height;
|
||||
cfg.g_timebase.num = info.time_base.numerator;
|
||||
cfg.g_timebase.den = info.time_base.denominator;
|
||||
cfg.rc_target_bitrate = bitrate;
|
||||
|
||||
write_ivf_file_header(outfile, &cfg, 0);
|
||||
writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
|
||||
if (!writer)
|
||||
die("Failed to open %s for writing.", argv[4]);
|
||||
|
||||
|
||||
/* Open input file for this encoding pass */
|
||||
// Open input file for this encoding pass
|
||||
if (!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading", argv[3]);
|
||||
die("Failed to open %s for reading.", argv[3]);
|
||||
|
||||
/* Initialize codec */
|
||||
// Initialize codec
|
||||
if (vpx_codec_enc_init(&codec, interface, &cfg, 0))
|
||||
die_codec(&codec, "Failed to initialize encoder");
|
||||
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
while(frame_avail || got_data) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
|
||||
frame_avail = read_frame(infile, &raw);
|
||||
if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
|
||||
1, flags, VPX_DL_REALTIME))
|
||||
while (read_frame(infile, &raw)) {
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt = NULL;
|
||||
res = vpx_codec_encode(&codec, &raw, frame_count, 1, 0,
|
||||
VPX_DL_GOOD_QUALITY);
|
||||
if (res != VPX_CODEC_OK)
|
||||
die_codec(&codec, "Failed to encode frame");
|
||||
got_data = 0;
|
||||
while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
|
||||
got_data = 1;
|
||||
switch(pkt->kind) {
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
(void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
|
||||
outfile);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
++frame_count;
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(&codec, &iter)) != NULL) {
|
||||
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||
const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
|
||||
if (!vpx_video_writer_write_frame(writer,
|
||||
pkt->data.frame.buf,
|
||||
pkt->data.frame.sz,
|
||||
pkt->data.frame.pts))
|
||||
die_codec(&codec, "Failed to write compressed frame.");
|
||||
printf(keyframe ? "K" : ".");
|
||||
}
|
||||
printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
|
||||
&& (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
|
||||
fflush(stdout);
|
||||
}
|
||||
frame_cnt++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
fclose(infile);
|
||||
|
||||
printf("Processed %d frames.\n",frame_cnt-1);
|
||||
printf("Processed %d frames.\n", frame_count);
|
||||
vpx_img_free(&raw);
|
||||
if (vpx_codec_destroy(&codec))
|
||||
die_codec(&codec, "Failed to destroy codec");
|
||||
die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
vpx_video_writer_close(writer);
|
||||
|
||||
/* Try to rewrite the file header with the actual frame count */
|
||||
if(!fseek(outfile, 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile, &cfg, frame_cnt-1);
|
||||
fclose(outfile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
65
ivfdec.c
65
ivfdec.c
@ -108,68 +108,3 @@ int ivf_read_frame(FILE *infile, uint8_t **buffer,
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct vpx_video {
|
||||
FILE *file;
|
||||
unsigned char *buffer;
|
||||
size_t buffer_size;
|
||||
size_t frame_size;
|
||||
unsigned int fourcc;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
vpx_video_t *vpx_video_open_file(FILE *file) {
|
||||
char raw_hdr[32];
|
||||
vpx_video_t *video;
|
||||
|
||||
if (fread(raw_hdr, 1, 32, file) != 32)
|
||||
return NULL; // Can't read file header;
|
||||
|
||||
if (memcmp(IVF_SIGNATURE, raw_hdr, 4) != 0)
|
||||
return NULL; // Wrong IVF signature
|
||||
|
||||
if (mem_get_le16(raw_hdr + 4) != 0)
|
||||
return NULL; // Wrong IVF version
|
||||
|
||||
video = (vpx_video_t *)malloc(sizeof(*video));
|
||||
video->file = file;
|
||||
video->buffer = NULL;
|
||||
video->buffer_size = 0;
|
||||
video->frame_size = 0;
|
||||
video->fourcc = mem_get_le32(raw_hdr + 8);
|
||||
video->width = mem_get_le16(raw_hdr + 12);
|
||||
video->height = mem_get_le16(raw_hdr + 14);
|
||||
return video;
|
||||
}
|
||||
|
||||
void vpx_video_close(vpx_video_t *video) {
|
||||
if (video) {
|
||||
free(video->buffer);
|
||||
free(video);
|
||||
}
|
||||
}
|
||||
|
||||
int vpx_video_get_width(vpx_video_t *video) {
|
||||
return video->width;
|
||||
}
|
||||
|
||||
int vpx_video_get_height(vpx_video_t *video) {
|
||||
return video->height;
|
||||
}
|
||||
|
||||
unsigned int vpx_video_get_fourcc(vpx_video_t *video) {
|
||||
return video->fourcc;
|
||||
}
|
||||
|
||||
int vpx_video_read_frame(vpx_video_t *video) {
|
||||
return !ivf_read_frame(video->file, &video->buffer, &video->frame_size,
|
||||
&video->buffer_size);
|
||||
}
|
||||
|
||||
const unsigned char *vpx_video_get_frame(vpx_video_t *video, size_t *size) {
|
||||
if (size)
|
||||
*size = video->frame_size;
|
||||
|
||||
return video->buffer;
|
||||
}
|
||||
|
28
ivfdec.h
28
ivfdec.h
@ -21,34 +21,6 @@ int file_is_ivf(struct VpxInputContext *input);
|
||||
int ivf_read_frame(FILE *infile, uint8_t **buffer,
|
||||
size_t *bytes_read, size_t *buffer_size);
|
||||
|
||||
// The following code is work in progress. It is going to be in a separate file
|
||||
// and support transparent reading of IVF and Y4M formats. Right now only IVF
|
||||
// format is supported for simplicity. The main goal the API is to be
|
||||
// simple and easy to use in example code (and probably in vpxenc/vpxdec later).
|
||||
// All low-level details like memory buffer management are hidden from API
|
||||
// users.
|
||||
struct vpx_video;
|
||||
typedef struct vpx_video vpx_video_t;
|
||||
|
||||
// Opens the input file and inspects it to determine file type. Returns an
|
||||
// opaque vpx_video_t* upon success, or NULL upon failure.
|
||||
vpx_video_t *vpx_video_open_file(FILE *file);
|
||||
|
||||
// Frees all resources associated with vpx_video_t returned from
|
||||
// vpx_video_open_file() call
|
||||
void vpx_video_close(vpx_video_t *video);
|
||||
|
||||
int vpx_video_get_width(vpx_video_t *video);
|
||||
int vpx_video_get_height(vpx_video_t *video);
|
||||
unsigned int vpx_video_get_fourcc(vpx_video_t *video);
|
||||
|
||||
// Reads video frame bytes from the file and stores them into internal buffer.
|
||||
int vpx_video_read_frame(vpx_video_t *video);
|
||||
|
||||
// Returns the pointer to internal memory buffer with frame bytes read from
|
||||
// last call to vpx_video_read_frame().
|
||||
const unsigned char *vpx_video_get_frame(vpx_video_t *video, size_t *size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
23
video_common.h
Normal file
23
video_common.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef VIDEO_COMMON_H_
|
||||
#define VIDEO_COMMON_H_
|
||||
|
||||
#include "./tools_common.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t codec_fourcc;
|
||||
int frame_width;
|
||||
int frame_height;
|
||||
struct VpxRational time_base;
|
||||
} VpxVideoInfo;
|
||||
|
||||
#endif // VIDEO_COMMON_H_
|
81
video_reader.c
Normal file
81
video_reader.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./ivfdec.h"
|
||||
#include "./video_reader.h"
|
||||
|
||||
static const char *const kIVFSignature = "DKIF";
|
||||
|
||||
struct VpxVideoReaderStruct {
|
||||
VpxVideoInfo info;
|
||||
FILE *file;
|
||||
uint8_t *buffer;
|
||||
size_t buffer_size;
|
||||
size_t frame_size;
|
||||
};
|
||||
|
||||
VpxVideoReader *vpx_video_reader_open(const char *filename) {
|
||||
char header[32];
|
||||
VpxVideoReader *reader = NULL;
|
||||
FILE *const file = fopen(filename, "rb");
|
||||
if (!file)
|
||||
return NULL; // Can't open file
|
||||
|
||||
if (fread(header, 1, 32, file) != 32)
|
||||
return NULL; // Can't read file header
|
||||
|
||||
if (memcmp(kIVFSignature, header, 4) != 0)
|
||||
return NULL; // Wrong IVF signature
|
||||
|
||||
if (mem_get_le16(header + 4) != 0)
|
||||
return NULL; // Wrong IVF version
|
||||
|
||||
reader = calloc(1, sizeof(*reader));
|
||||
if (!reader)
|
||||
return NULL; // Can't allocate VpxVideoReader
|
||||
|
||||
reader->file = file;
|
||||
reader->info.codec_fourcc = mem_get_le32(header + 8);
|
||||
reader->info.frame_width = mem_get_le16(header + 12);
|
||||
reader->info.frame_height = mem_get_le16(header + 14);
|
||||
reader->info.time_base.numerator = mem_get_le32(header + 16);
|
||||
reader->info.time_base.denominator = mem_get_le32(header + 20);
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
void vpx_video_reader_close(VpxVideoReader *reader) {
|
||||
if (reader) {
|
||||
fclose(reader->file);
|
||||
free(reader->buffer);
|
||||
free(reader);
|
||||
}
|
||||
}
|
||||
|
||||
int vpx_video_reader_read_frame(VpxVideoReader *reader) {
|
||||
return !ivf_read_frame(reader->file, &reader->buffer, &reader->frame_size,
|
||||
&reader->buffer_size);
|
||||
}
|
||||
|
||||
const uint8_t *vpx_video_reader_get_frame(VpxVideoReader *reader,
|
||||
size_t *size) {
|
||||
if (size)
|
||||
*size = reader->frame_size;
|
||||
|
||||
return reader->buffer;
|
||||
}
|
||||
|
||||
const VpxVideoInfo *vpx_video_reader_get_info(VpxVideoReader *reader) {
|
||||
return &reader->info;
|
||||
}
|
||||
|
52
video_reader.h
Normal file
52
video_reader.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef VIDEO_READER_H_
|
||||
#define VIDEO_READER_H_
|
||||
|
||||
#include "./video_common.h"
|
||||
|
||||
// The following code is work in progress. It is going to support transparent
|
||||
// reading of input files. Right now only IVF format is supported for
|
||||
// simplicity. The main goal the API is to be simple and easy to use in example
|
||||
// code and in vpxenc/vpxdec later. All low-level details like memory
|
||||
// buffer management are hidden from API users.
|
||||
struct VpxVideoReaderStruct;
|
||||
typedef struct VpxVideoReaderStruct VpxVideoReader;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Opens the input file for reading and inspects it to determine file type.
|
||||
// Returns an opaque VpxVideoReader* upon success, or NULL upon failure.
|
||||
// Right now only IVF format is supported.
|
||||
VpxVideoReader *vpx_video_reader_open(const char *filename);
|
||||
|
||||
// Frees all resources associated with VpxVideoReader* returned from
|
||||
// vpx_video_reader_open() call.
|
||||
void vpx_video_reader_close(VpxVideoReader *reader);
|
||||
|
||||
// Reads frame from the file and stores it in internal buffer.
|
||||
int vpx_video_reader_read_frame(VpxVideoReader *reader);
|
||||
|
||||
// Returns the pointer to memory buffer with frame data read by last call to
|
||||
// vpx_video_reader_read_frame().
|
||||
const uint8_t *vpx_video_reader_get_frame(VpxVideoReader *reader,
|
||||
size_t *size);
|
||||
|
||||
// Fills VpxVideoInfo with information from opened video file.
|
||||
const VpxVideoInfo *vpx_video_reader_get_info(VpxVideoReader *reader);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // VIDEO_READER_H_
|
80
video_writer.c
Normal file
80
video_writer.c
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "./ivfenc.h"
|
||||
#include "./video_writer.h"
|
||||
#include "vpx/vpx_encoder.h"
|
||||
|
||||
struct VpxVideoWriterStruct {
|
||||
VpxVideoInfo info;
|
||||
FILE *file;
|
||||
int frame_count;
|
||||
};
|
||||
|
||||
static void write_header(FILE *file, const VpxVideoInfo *info,
|
||||
int frame_count) {
|
||||
struct vpx_codec_enc_cfg cfg;
|
||||
cfg.g_w = info->frame_width;
|
||||
cfg.g_h = info->frame_height;
|
||||
cfg.g_timebase.num = info->time_base.numerator;
|
||||
cfg.g_timebase.den = info->time_base.denominator;
|
||||
|
||||
ivf_write_file_header(file, &cfg, info->codec_fourcc, frame_count);
|
||||
}
|
||||
|
||||
VpxVideoWriter *vpx_video_writer_open(const char *filename,
|
||||
VpxContainer container,
|
||||
const VpxVideoInfo *info) {
|
||||
if (container == kContainerIVF) {
|
||||
VpxVideoWriter *writer = NULL;
|
||||
FILE *const file = fopen(filename, "wb");
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
writer = malloc(sizeof(*writer));
|
||||
if (!writer)
|
||||
return NULL;
|
||||
|
||||
writer->frame_count = 0;
|
||||
writer->info = *info;
|
||||
writer->file = file;
|
||||
|
||||
write_header(writer->file, info, 0);
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vpx_video_writer_close(VpxVideoWriter *writer) {
|
||||
if (writer) {
|
||||
// Rewriting frame header with real frame count
|
||||
rewind(writer->file);
|
||||
write_header(writer->file, &writer->info, writer->frame_count);
|
||||
|
||||
fclose(writer->file);
|
||||
free(writer);
|
||||
}
|
||||
}
|
||||
|
||||
int vpx_video_writer_write_frame(VpxVideoWriter *writer,
|
||||
const uint8_t *buffer, size_t size,
|
||||
int64_t pts) {
|
||||
ivf_write_frame_header(writer->file, pts, size);
|
||||
if (fwrite(buffer, 1, size, writer->file) != size)
|
||||
return 0;
|
||||
|
||||
++writer->frame_count;
|
||||
|
||||
return 1;
|
||||
}
|
47
video_writer.h
Normal file
47
video_writer.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef VIDEO_WRITER_H_
|
||||
#define VIDEO_WRITER_H_
|
||||
|
||||
#include "./video_common.h"
|
||||
|
||||
typedef enum {
|
||||
kContainerIVF
|
||||
} VpxContainer;
|
||||
|
||||
struct VpxVideoWriterStruct;
|
||||
typedef struct VpxVideoWriterStruct VpxVideoWriter;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Finds and opens writer for specified container format.
|
||||
// Returns an opaque VpxVideoWriter* upon success, or NULL upon failure.
|
||||
// Right now only IVF format is supported.
|
||||
VpxVideoWriter *vpx_video_writer_open(const char *filename,
|
||||
VpxContainer container,
|
||||
const VpxVideoInfo *info);
|
||||
|
||||
// Frees all resources associated with VpxVideoWriter* returned from
|
||||
// vpx_video_writer_open() call.
|
||||
void vpx_video_writer_close(VpxVideoWriter *writer);
|
||||
|
||||
// Writes frame bytes to the file.
|
||||
int vpx_video_writer_write_frame(VpxVideoWriter *writer,
|
||||
const uint8_t *buffer, size_t size,
|
||||
int64_t pts);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // VIDEO_WRITER_H_
|
Loading…
Reference in New Issue
Block a user