summaryrefslogtreecommitdiff
path: root/code/test
diff options
context:
space:
mode:
authorUros Majstorovic <majstor@majstor.org>2017-09-09 15:36:21 +0200
committerUros Majstorovic <majstor@majstor.org>2017-09-09 15:36:21 +0200
commitd40fd9b1adab64182ce8af0b8e19cfc8a93171d7 (patch)
tree0cb83df16cb6f0625aa7ab60fe96f47be2cb75ab /code/test
parent55364a819692d63080d23e6dc30daf38f02f5524 (diff)
video streaming test updated; not tested
Diffstat (limited to 'code/test')
-rw-r--r--code/test/vid/Makefile15
-rw-r--r--code/test/vid/cap.c36
-rw-r--r--code/test/vid/client.c106
-rw-r--r--code/test/vid/enc.c100
-rw-r--r--code/test/vid/enc.h5
-rw-r--r--code/test/vid/server.c63
-rw-r--r--code/test/vid/server.h5
-rw-r--r--code/test/vid/tools.c145
-rw-r--r--code/test/vid/tools.h12
9 files changed, 355 insertions, 132 deletions
diff --git a/code/test/vid/Makefile b/code/test/vid/Makefile
index 757429d..fbdbe15 100644
--- a/code/test/vid/Makefile
+++ b/code/test/vid/Makefile
@@ -1,17 +1,20 @@
LIBVPX_HOME=../libvpx
-CFLAGS=-D_V4L2_KERNEL_ -I/usr/src/linux-headers-$(uname -r) -I$(LIBVPX_HOME)
+CFLAGS=-D_V4L2_KERNEL_ -I/usr/src/linux-headers-$(uname -r) -I$(LIBVPX_HOME) -I../../core -I../../vconn -I../../util
LDFLAGS=-L$(LIBVPX_HOME)
-deps=$(LIBVPX_HOME)/ivfenc.c.o $(LIBVPX_HOME)/video_writer.c.o
+dep=../../core/libecpcore.a ../../core/crypto/libecpcr.a ../../core/htable/libecpht.a ../../core/posix/libecptr.a ../../core/posix/libecptm.a ../../vconn/libecpvconn.a ../../util/libecputil.a ../init.o
-all: cap
+all: client cap
%.o: %.c
$(CC) $(CFLAGS) -c $<
-cap: cap.o enc.o tools.o
- $(CC) -o $@ $< enc.o tools.o $(deps) -lvpx -lm -pthread $(LDFLAGS)
+cap: cap.o enc.o tools.o server.o
+ $(CC) -o $@ $< enc.o tools.o server.o -lvpx -lm -pthread $(dep) $(LDFLAGS)
+client: client.o tools.o
+ $(CC) -o $@ $< tools.o -lvpx -lm -pthread $(dep) $(LDFLAGS)
+
clean:
rm -f *.o
- rm -f cap
+ rm -f cap client
diff --git a/code/test/vid/cap.c b/code/test/vid/cap.c
index c156fab..99fa500 100644
--- a/code/test/vid/cap.c
+++ b/code/test/vid/cap.c
@@ -398,7 +398,7 @@ int v4l2_set_mmap(int fd, int *buffers_count)
return CAP_OK;
}
-int v4l2_retrieve_frame(int fd, int buffers_count, vpx_image_t *raw, vpx_codec_ctx_t *codec, int frame_count, int kframe_interval)
+int v4l2_retrieve_frame(int fd, int buffers_count, vpx_image_t *raw, vpx_codec_ctx_t *codec, int frame_index, int kframe_interval)
{
int sz;
fd_set fds;
@@ -445,10 +445,11 @@ int v4l2_retrieve_frame(int fd, int buffers_count, vpx_image_t *raw, vpx_codec_c
// printf("Length: %d \tBytesused: %d \tAddress: %p\n", buf.length, buf.bytesused, &buffers[buf.index]);
sz = ALIGN_16B(width) * height * 3 / 2;
- vpx_img_read(raw, buffers[buf.index].start, sz);
- if (frame_count % kframe_interval == 0)
- flags |= VPX_EFLAG_FORCE_KF;
- vpx_encode_frame(codec, raw, frame_count, flags);
+ if (!vpx_img_read(raw, buffers[buf.index].start, sz)) {
+ die_codec(NULL, "Failed to read image.");
+ }
+ if (frame_index % kframe_interval == 0) flags |= VPX_EFLAG_FORCE_KF;
+ vpx_encode_frame(codec, raw, frame_index, flags);
if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) {
CAP_ERROR_RET("failed to queue buffer.");
@@ -475,7 +476,6 @@ int v4l2_close_camera(int fd, int buffers_count)
int main(int argc, char *argv[])
{
- int i, n;
int fd;
int target_bitrate = 200;
double after;
@@ -484,13 +484,12 @@ int main(int argc, char *argv[])
int buffers_count;
int kframe_interval;
vpx_codec_er_flags_t err_resilient;
- int frame_count;
- char *out_fname;
+ char *address;
+ char *key_file;
if (argc != 13) {
- CAP_ERROR_RET("./cap <width> <height> <buffers [4,8]> <video mode [0,1]> <exposure [-4,4]> <hflip [0,1]> <vflip [0,1]> <kframe interval> <bitrate> <err resilient> <num frames> <file name>")
+ CAP_ERROR_RET("./cap <width> <height> <buffers [4,8]> <video mode [0,1]> <exposure [-4,4]> <hflip [0,1]> <vflip [0,1]> <kframe interval> <bitrate> <err resilient> <address> <key file>")
}
- n = 0;
width = (int) atoi(argv[1]);
height = (int) atoi(argv[2]);
n_buffers = (int) atoi(argv[3]);
@@ -508,8 +507,8 @@ int main(int argc, char *argv[])
kframe_interval = (int) atoi(argv[8]);
target_bitrate = (int) atoi(argv[9]);
err_resilient = strtoul(argv[10], NULL, 0);
- frame_count = (int) atoi(argv[11]);
- out_fname = argv[12];
+ address = argv[11];
+ key_file = argv[12];
printf("---- cap parameters -----\nwidth: %d\nheight: %d\nv4l2 buffers: %d\nexposure: %d\nhflip: %d\nvflip: %d\nMode: %s\n", width, height, n_buffers, sensor_exposure, sensor_hflip, sensor_vflip, sensor_video_mode ? "V4L2_MODE_VIDEO" : "V4L2_MODE_IMAGE");
@@ -538,16 +537,21 @@ int main(int argc, char *argv[])
CAP_ERROR_RET("failed to mmap.");
}
+ int n = 0;
int _fps = 30;
const char *codec_arg = "vp9";
vpx_codec_ctx_t codec;
vpx_image_t raw;
- vpx_init(codec_arg, out_fname, width, height, _fps);
- vpx_open(&codec, get_vpx_encoder_by_name(codec_arg)->codec_interface(), width, height, _fps, target_bitrate, err_resilient, &raw);
- for (i = 0; i < frame_count; i++) {
+ vpx_open(codec_arg, width, height, _fps, target_bitrate, err_resilient, &codec, &raw);
+
+ while (1) {
+ if (!conn_is_open()) {
+ sleep(1);
+ continue;
+ }
before = get_wall_time();
- if (v4l2_retrieve_frame(fd, buffers_count, &raw, &codec, i, kframe_interval)) {
+ if (v4l2_retrieve_frame(fd, buffers_count, &raw, &codec, n, kframe_interval)) {
CAP_ERROR_RET("failed to retrieve frame.");
}
after = get_wall_time();
diff --git a/code/test/vid/client.c b/code/test/vid/client.c
new file mode 100644
index 0000000..00b8c0a
--- /dev/null
+++ b/code/test/vid/client.c
@@ -0,0 +1,106 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "core.h"
+#include "util.h"
+
+#include "vpx/vpx_decoder.h"
+#include "vpx/vp8cx.h"
+#include "tools.h"
+
+#define CTYPE_TEST 0
+#define MTYPE_MSG 8
+
+#define FRAG_BUF_SIZE 8192
+#define RBUF_MSG_SIZE 128
+
+ECPContext ctx_c;
+ECPSocket sock_c;
+ECPConnHandler handler_c;
+
+ECPNode node;
+ECPConnection conn;
+
+FILE *outfile;
+vpx_codec_ctx_t codec;
+
+ECPRBRecv rbuf_recv;
+ECPRBMessage rbuf_r_msg[RBUF_MSG_SIZE];
+ECPFragIter frag_iter;
+unsigned char frag_buffer[FRAG_BUF_SIZE];
+
+ssize_t handle_msg(ECPConnection *conn, ecp_seq_t sq, unsigned char t, unsigned char *f, ssize_t sz) {
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_t *img = NULL;
+ if (vpx_codec_decode(&codec, f, (unsigned int)sz, NULL, 0))
+ die_codec(&codec, "Failed to decode frame.");
+
+ while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
+ if (!vpx_img_write_f(img, outfile)) {
+ die_codec(NULL, "Failed to write image.");
+ }
+ }
+
+ return sz;
+}
+
+static void usage(char *arg) {
+ fprintf(stderr, "Usage: %s <node.pub>\n", arg);
+ exit(1);
+}
+
+int main(int argc, char *argv[]) {
+ int rv;
+
+ if (argc != 2) usage(argv[0]);
+
+ rv = ecp_init(&ctx_c);
+ printf("ecp_init RV:%d\n", rv);
+
+ if (!rv) rv = ecp_conn_handler_init(&handler_c);
+ if (!rv) {
+ handler_c.msg[MTYPE_MSG] = handle_msg;
+ ctx_c.handler[CTYPE_TEST] = &handler_c;
+ }
+
+ if (!rv) rv = ecp_sock_create(&sock_c, &ctx_c, NULL);
+ printf("ecp_sock_create RV:%d\n", rv);
+
+ if (!rv) rv = ecp_sock_open(&sock_c, NULL);
+ printf("ecp_sock_open RV:%d\n", rv);
+
+ if (!rv) rv = ecp_start_receiver(&sock_c);
+ printf("ecp_start_receiver RV:%d\n", rv);
+
+ if (!rv) rv = ecp_util_node_load(&ctx_c, &node, argv[1]);
+ printf("ecp_util_node_load RV:%d\n", rv);
+
+ if (!rv) rv = ecp_conn_create(&conn, &sock_c, CTYPE_TEST);
+ printf("ecp_conn_create RV:%d\n", rv);
+
+ if (!rv) rv = ecp_rbuf_create(&conn, NULL, NULL, 0, &rbuf_recv, rbuf_r_msg, RBUF_MSG_SIZE);
+ printf("ecp_rbuf_create RV:%d\n", rv);
+
+ if (!rv) {
+ ecp_frag_iter_init(&frag_iter, frag_buffer, FRAG_BUF_SIZE);
+ rbuf_recv.frag_iter = &frag_iter;
+ }
+
+ if (!rv) rv = ecp_conn_open(&conn, &node);
+ printf("ecp_conn_open RV:%d\n", rv);
+
+ const char *codec_arg = "vp9";
+ const VpxInterface *decoder = get_vpx_decoder_by_name(codec_arg);
+ if (!decoder) die_codec(NULL, "Unknown input codec.");
+
+ printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
+
+ if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
+ die_codec(&codec, "Failed to initialize decoder.");
+
+ while (1) sleep(1);
+
+ if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
+} \ No newline at end of file
diff --git a/code/test/vid/enc.c b/code/test/vid/enc.c
index a1730b4..91fe5e8 100644
--- a/code/test/vid/enc.c
+++ b/code/test/vid/enc.c
@@ -100,68 +100,7 @@
#include <string.h>
#include "enc.h"
-
-static const char *exec_name = "./enc";
-
-void usage_exit(void) {
- fprintf(stderr,
- "Usage: %s <codec> <width> <height> <infile> <outfile> "
- "<keyframe-interval> <error-resilient> <frames to encode>\n"
- "See comments in simple_encoder.c for more information.\n",
- exec_name);
- exit(EXIT_FAILURE);
-}
-
-static VpxVideoWriter *writer;
-
-static VpxVideoWriter *open_writer(const char *file_name, uint32_t fourcc, int width, int height, int fps) {
- VpxVideoInfo info = { 0, 0, 0, { 0, 0 } };
-
- info.codec_fourcc = fourcc;
- info.frame_width = width;
- info.frame_height = height;
- info.time_base.numerator = 1;
- info.time_base.denominator = fps;
-
- return vpx_video_writer_open(file_name, kContainerIVF, &info);
-}
-
-// TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part
-// of vpx_image_t support
-int vpx_img_plane_width(const vpx_image_t *img, int plane) {
- if (plane > 0 && img->x_chroma_shift > 0)
- return (img->d_w + 1) >> img->x_chroma_shift;
- else
- return img->d_w;
-}
-
-int vpx_img_plane_height(const vpx_image_t *img, int plane) {
- if (plane > 0 && img->y_chroma_shift > 0)
- return (img->d_h + 1) >> img->y_chroma_shift;
- else
- return img->d_h;
-}
-
-int vpx_img_read(vpx_image_t *img, void *img_buf, int sz) {
- int plane;
-
- for (plane = 0; plane < 3; ++plane) {
- unsigned char *buf = img->planes[plane];
- const int stride = img->stride[plane];
- const int w = vpx_img_plane_width(img, plane) *
- ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
- const int h = vpx_img_plane_height(img, plane);
- int y;
-
- for (y = 0; y < h; ++y) {
- memcpy(buf, img_buf, w);
- img_buf += w;
- buf += stride;
- }
- }
-
- return 1;
-}
+#include "server.h"
int vpx_encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img, int frame_index, int flags) {
int got_pkts = 0;
@@ -176,9 +115,7 @@ int vpx_encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img, int frame_index,
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)) {
+ if (send_frame(pkt->data.frame.buf, pkt->data.frame.sz, pkt->data.frame.pts) < 0) {
die_codec(codec, "Failed to write compressed frame");
}
printf(keyframe ? "K" : ".");
@@ -190,12 +127,20 @@ int vpx_encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img, int frame_index,
}
-void vpx_open(vpx_codec_ctx_t *codec, vpx_codec_iface_t *codec_interface, int width, int height, int fps, int bitrate, vpx_codec_er_flags_t err_resilient, vpx_image_t *raw) {
+void vpx_open(const char *codec_arg, int width, int height, int fps, int bitrate, vpx_codec_er_flags_t err_resilient, vpx_codec_ctx_t *codec, vpx_image_t *raw) {
vpx_codec_enc_cfg_t cfg;
vpx_codec_err_t res;
- res = vpx_codec_enc_config_default(codec_interface, &cfg, 0);
- if (res) die("Failed to get default codec config.");
+ const VpxInterface *encoder = get_vpx_encoder_by_name(codec_arg);
+ if (!encoder) die_codec(NULL, "Unsupported codec.");
+
+ printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
+
+ if (!vpx_img_alloc(raw, VPX_IMG_FMT_I420, width, height, 1))
+ die_codec(NULL, "Failed to allocate image.");
+
+ res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
+ if (res) die_codec(NULL, "Failed to get default codec config.");
cfg.g_w = width;
cfg.g_h = height;
@@ -205,15 +150,11 @@ void vpx_open(vpx_codec_ctx_t *codec, vpx_codec_iface_t *codec_interface, int wi
cfg.g_error_resilient = err_resilient;
cfg.rc_end_usage = VPX_CBR;
- if (vpx_codec_enc_init(codec, codec_interface, &cfg, 0))
+ if (vpx_codec_enc_init(codec, encoder->codec_interface(), &cfg, 0))
die_codec(codec, "Failed to initialize encoder");
if (vpx_codec_control(codec, VP8E_SET_CPUUSED, 8))
die_codec(codec, "Failed to initialize cpuused");
-
- if (!vpx_img_alloc(raw, VPX_IMG_FMT_I420, width, height, 1)) {
- die("Failed to allocate image.");
- }
}
void vpx_close(vpx_codec_ctx_t *codec, vpx_image_t *raw) {
@@ -223,17 +164,4 @@ void vpx_close(vpx_codec_ctx_t *codec, vpx_image_t *raw) {
vpx_img_free(raw);
if (vpx_codec_destroy(codec)) die_codec(codec, "Failed to destroy codec.");
-
- vpx_video_writer_close(writer);
}
-
-void vpx_init(const char *codec_arg, const char *outfile_arg, int width, int height, int fps) {
- const VpxInterface *encoder = get_vpx_encoder_by_name(codec_arg);
- if (!encoder) die("Unsupported codec.");
-
- writer = open_writer(outfile_arg, encoder->fourcc, width, height, fps);
- if (!writer) die("Failed to open %s for writing.", outfile_arg);
-
- printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
-}
-
diff --git a/code/test/vid/enc.h b/code/test/vid/enc.h
index d534971..5acd8ce 100644
--- a/code/test/vid/enc.h
+++ b/code/test/vid/enc.h
@@ -1,10 +1,7 @@
#include "vpx/vpx_encoder.h"
#include "vpx/vp8cx.h"
#include "tools.h"
-#include "video_writer.h"
-int vpx_img_read(vpx_image_t *img, void *img_buf, int sz);
int vpx_encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img, int frame_index, int flags);
-void vpx_open(vpx_codec_ctx_t *codec, vpx_codec_iface_t *codec_interface, int width, int height, int fps, int bitrate, vpx_codec_er_flags_t err_resilient, vpx_image_t *raw);
+void vpx_open(const char *codec_arg, int width, int height, int fps, int bitrate, vpx_codec_er_flags_t err_resilient, vpx_codec_ctx_t *codec, vpx_image_t *raw);
void vpx_close(vpx_codec_ctx_t *codec, vpx_image_t *raw);
-void vpx_init(const char *codec_arg, const char *outfile_arg, int width, int height, int fps);
diff --git a/code/test/vid/server.c b/code/test/vid/server.c
new file mode 100644
index 0000000..08653f1
--- /dev/null
+++ b/code/test/vid/server.c
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "server.h"
+#include "util.h"
+
+static ECPContext ctx_s;
+static ECPSocket sock_s;
+static ECPDHKey key_perma_s;
+static ECPConnHandler handler_s;
+
+static ECPConnection *conn;
+static int is_open = 0;
+
+#define CTYPE_TEST 0
+#define MTYPE_MSG 8
+
+static ssize_t handle_open(ECPConnection *c, ecp_seq_t sq, unsigned char t, unsigned char *m, ssize_t sz) {
+ ssize_t rv = ecp_conn_handle_open(c, sq, t, m, sz);
+ if (rv < 0) return rv;
+
+ conn = c;
+ is_open = 1;
+
+ return rv;
+}
+
+ssize_t send_frame(unsigned char *buffer, size_t size, ecp_pts_t pts) {
+ return ecp_send(conn, MTYPE_MSG, buffer, size);
+}
+
+int conn_is_open(void) {
+ return is_open;
+}
+
+int init_server(char *address, char *key) {
+ int rv;
+
+ rv = ecp_init(&ctx_s);
+ printf("ecp_init RV:%d\n", rv);
+
+ if (!rv) rv = ecp_conn_handler_init(&handler_s);
+ if (!rv) {
+ handler_s.msg[ECP_MTYPE_OPEN] = handle_open;
+ ctx_s.handler[CTYPE_TEST] = &handler_s;
+ }
+
+ if (!rv) rv = ecp_util_key_load(&ctx_s, &key_perma_s, key);
+ printf("ecp_util_key_load RV:%d\n", rv);
+
+ if (!rv) rv = ecp_sock_create(&sock_s, &ctx_s, &key_perma_s);
+ printf("ecp_sock_create RV:%d\n", rv);
+
+ if (!rv) rv = ecp_sock_open(&sock_s, address);
+ printf("ecp_sock_open RV:%d\n", rv);
+
+ if (!rv) rv = ecp_start_receiver(&sock_s);
+ printf("ecp_start_receiver RV:%d\n", rv);
+
+ return rv;
+}
diff --git a/code/test/vid/server.h b/code/test/vid/server.h
new file mode 100644
index 0000000..3f9c57e
--- /dev/null
+++ b/code/test/vid/server.h
@@ -0,0 +1,5 @@
+#include "core.h"
+
+ssize_t send_frame(unsigned char *buffer, size_t size, ecp_pts_t pts);
+int conn_is_open(void);
+int init_server(char *address, char *key); \ No newline at end of file
diff --git a/code/test/vid/tools.c b/code/test/vid/tools.c
index 6122209..3331670 100644
--- a/code/test/vid/tools.c
+++ b/code/test/vid/tools.c
@@ -27,28 +27,137 @@ const VpxInterface *get_vpx_encoder_by_name(const char *name) {
return NULL;
}
-#define LOG_ERROR(label) \
- do { \
- const char *l = label; \
- va_list ap; \
- va_start(ap, fmt); \
- if (l) fprintf(stderr, "%s: ", l); \
- vfprintf(stderr, fmt, ap); \
- fprintf(stderr, "\n"); \
- va_end(ap); \
- } while (0)
-
-void die(const char *fmt, ...) {
- LOG_ERROR(NULL);
- usage_exit();
+static const VpxInterface vpx_decoders[] = {
+ { "vp8", VP8_FOURCC, &vpx_codec_vp8_dx },
+ { "vp9", VP9_FOURCC, &vpx_codec_vp9_dx },
+};
+
+int get_vpx_decoder_count(void) {
+ return sizeof(vpx_decoders) / sizeof(vpx_decoders[0]);
+}
+
+const VpxInterface *get_vpx_decoder_by_index(int i) { return &vpx_decoders[i]; }
+
+const VpxInterface *get_vpx_decoder_by_name(const char *name) {
+ int i;
+
+ for (i = 0; i < get_vpx_decoder_count(); ++i) {
+ const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+ if (strcmp(decoder->name, name) == 0) return decoder;
+ }
+
+ return NULL;
}
void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
- const char *detail = vpx_codec_error_detail(ctx);
+ if (ctx) {
+ const char *detail = vpx_codec_error_detail(ctx);
- printf("%s: %s\n", s, vpx_codec_error(ctx));
- if (detail) printf(" %s\n", detail);
+ fprintf(stderr, "%s: %s\n", s, vpx_codec_error(ctx));
+ if (detail) fprintf(stderr, " %s\n", detail);
+ } else {
+ fprintf(stderr, "%s", s);
+ }
exit(EXIT_FAILURE);
}
- \ No newline at end of file
+// TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part
+// of vpx_image_t support
+int vpx_img_plane_width(const vpx_image_t *img, int plane) {
+ if (plane > 0 && img->x_chroma_shift > 0)
+ return (img->d_w + 1) >> img->x_chroma_shift;
+ else
+ return img->d_w;
+}
+
+int vpx_img_plane_height(const vpx_image_t *img, int plane) {
+ if (plane > 0 && img->y_chroma_shift > 0)
+ return (img->d_h + 1) >> img->y_chroma_shift;
+ else
+ return img->d_h;
+}
+
+int vpx_img_read(vpx_image_t *img, void *img_buf, int sz) {
+ int plane;
+ int off = 0;
+
+ for (plane = 0; plane < 3; ++plane) {
+ unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int w = vpx_img_plane_width(img, plane) *
+ ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
+ const int h = vpx_img_plane_height(img, plane);
+ int y;
+
+ for (y = 0; y < h; ++y) {
+ if (off + w > sz) return 0;
+ memcpy(buf, img_buf + off, w);
+ off += w;
+ buf += stride;
+ }
+ }
+
+ return 1;
+}
+
+int vpx_img_write(const vpx_image_t *img, void *img_buf, int sz) {
+ int plane;
+ int off = 0;
+
+ for (plane = 0; plane < 3; ++plane) {
+ const unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int w = vpx_img_plane_width(img, plane) *
+ ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
+ const int h = vpx_img_plane_height(img, plane);
+ int y;
+
+ for (y = 0; y < h; ++y) {
+ if (off + w > sz) return 0;
+ memcpy(img_buf + off, buf, w);
+ off += w;
+ buf += stride;
+ }
+ }
+
+ return 1;
+}
+
+int vpx_img_read_f(vpx_image_t *img, FILE *file) {
+ int plane;
+
+ for (plane = 0; plane < 3; ++plane) {
+ unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int w = vpx_img_plane_width(img, plane) *
+ ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
+ const int h = vpx_img_plane_height(img, plane);
+ int y;
+
+ for (y = 0; y < h; ++y) {
+ if (fread(buf, 1, w, file) != (size_t)w) return 0;
+ buf += stride;
+ }
+ }
+
+ return 1;
+}
+
+int vpx_img_write_f(const vpx_image_t *img, FILE *file) {
+ int plane;
+
+ for (plane = 0; plane < 3; ++plane) {
+ const unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int w = vpx_img_plane_width(img, plane) *
+ ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
+ const int h = vpx_img_plane_height(img, plane);
+ int y;
+
+ for (y = 0; y < h; ++y) {
+ if (fwrite(buf, 1, w, file) != (size_t)w) return 0;
+ buf += stride;
+ }
+ }
+}
+
diff --git a/code/test/vid/tools.h b/code/test/vid/tools.h
index 0bbf512..645d5ba 100644
--- a/code/test/vid/tools.h
+++ b/code/test/vid/tools.h
@@ -4,6 +4,7 @@
#include "vpx/vpx_codec.h"
#include "vpx/vpx_image.h"
#include "vpx/vp8cx.h"
+#include "vpx/vp8dx.h"
#define VP8_FOURCC 0x30385056
#define VP9_FOURCC 0x30395056
@@ -19,11 +20,18 @@ typedef struct VpxInterface {
vpx_codec_iface_t *(*const codec_interface)();
} VpxInterface;
-void usage_exit(void);
const VpxInterface *get_vpx_encoder_by_index(int i);
const VpxInterface *get_vpx_encoder_by_name(const char *name);
-void die(const char *fmt, ...);
+const VpxInterface *get_vpx_decoder_by_index(int i);
+const VpxInterface *get_vpx_decoder_by_name(const char *name);
+
void die_codec(vpx_codec_ctx_t *ctx, const char *s);
+int vpx_img_read(vpx_image_t *img, void *img_buf, int sz);
+int vpx_img_write(const vpx_image_t *img, void *img_buf, int sz);
+
+int vpx_img_read_f(vpx_image_t *img, FILE *file);
+int vpx_img_write_f(const vpx_image_t *img, FILE *file);
+
#endif \ No newline at end of file