summaryrefslogtreecommitdiff
path: root/modules/daala/decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/daala/decode.c')
-rw-r--r--modules/daala/decode.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/modules/daala/decode.c b/modules/daala/decode.c
new file mode 100644
index 0000000..646605e
--- /dev/null
+++ b/modules/daala/decode.c
@@ -0,0 +1,177 @@
+/**
+ * @file daala/decode.c Experimental video-codec using Daala -- decoder
+ *
+ * Copyright (C) 2010 - 2015 Creytiv.com
+ */
+
+#include <string.h>
+#include <re.h>
+#include <rem.h>
+#include <baresip.h>
+#include <daala/daaladec.h>
+#include "daala.h"
+
+
+struct viddec_state {
+ daala_dec_ctx *dec;
+
+ bool got_headers;
+
+ daala_info di;
+ daala_comment dc;
+ daala_setup_info *ds;
+
+ struct {
+ bool valid;
+ size_t n_frame;
+ size_t n_header;
+ size_t n_keyframe;
+ size_t n_packet;
+ } stats;
+};
+
+
+static void dump_stats(const struct viddec_state *vds)
+{
+ re_printf("~~~~~ Daala Decoder stats ~~~~~\n");
+ re_printf("num frames: %zu\n", vds->stats.n_frame);
+ re_printf("num headers: %zu\n", vds->stats.n_header);
+ re_printf("key-frames packets: %zu\n", vds->stats.n_keyframe);
+ re_printf("total packets: %zu\n", vds->stats.n_packet);
+}
+
+
+static void destructor(void *arg)
+{
+ struct viddec_state *vds = arg;
+
+ if (vds->stats.valid)
+ dump_stats(vds);
+
+ if (vds->dec)
+ daala_decode_free(vds->dec);
+
+ if (vds->ds)
+ daala_setup_free(vds->ds);
+ daala_comment_clear(&vds->dc);
+ daala_info_clear(&vds->di);
+}
+
+
+int daala_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc,
+ const char *fmtp)
+{
+ struct viddec_state *vds;
+ int err = 0;
+ (void)vc;
+ (void)fmtp;
+
+ if (!vdsp)
+ return EINVAL;
+
+ vds = *vdsp;
+
+ if (vds)
+ return 0;
+
+ vds = mem_zalloc(sizeof(*vds), destructor);
+ if (!vds)
+ return ENOMEM;
+
+ daala_info_init(&vds->di);
+ daala_comment_init(&vds->dc);
+
+ if (err)
+ mem_deref(vds);
+ else
+ *vdsp = vds;
+
+ return err;
+}
+
+
+int daala_decode(struct viddec_state *vds, struct vidframe *frame,
+ bool marker, uint16_t seq, struct mbuf *mb)
+{
+ ogg_packet op;
+ bool ishdr;
+ int i, r, err = 0;
+ (void)seq;
+
+ if (!vds || !frame || !mb)
+ return EINVAL;
+
+ ++vds->stats.n_packet;
+ ++vds->stats.valid;
+
+ ishdr = daala_packet_isheader(mbuf_buf(mb), mbuf_get_left(mb));
+
+ if (ishdr)
+ ++vds->stats.n_header;
+ else if (daala_packet_iskeyframe(mbuf_buf(mb), mbuf_get_left(mb)) > 0)
+ ++vds->stats.n_keyframe;
+
+#if 0
+ re_printf("decode: [%s] %zu bytes\n",
+ ishdr ? "HEADER" : "DATA",
+ mbuf_get_left(mb));
+#endif
+
+ memset(&op, 0, sizeof(op));
+
+ op.packet = mbuf_buf(mb);
+ op.bytes = mbuf_get_left(mb);
+ op.b_o_s = marker;
+
+ if (daala_packet_isheader(mbuf_buf(mb), mbuf_get_left(mb))) {
+
+ r = daala_decode_header_in(&vds->di, &vds->dc, &vds->ds,
+ &op);
+ if (r < 0) {
+ warning("daala: decoder: decode_header_in failed"
+ " (ret = %d)\n",
+ r);
+ return EPROTO;
+ }
+ else if (r == 0) {
+ vds->got_headers = true;
+ info("daala: all headers received\n");
+
+ vds->dec = daala_decode_alloc(&vds->di, vds->ds);
+ if (!vds->dec) {
+ warning("daala: decoder: alloc failed\n");
+ return ENOMEM;
+ }
+ }
+ else {
+ /* waiting for more headers */
+ }
+ }
+ else {
+ od_img img;
+
+ if (!vds->got_headers) {
+ warning("daala: decode: still waiting for headers\n");
+ return EPROTO;
+ }
+
+ r = daala_decode_packet_in(vds->dec, &img, &op);
+ if (r < 0) {
+ warning("daala: decode: packet_in error (%d)\n", r);
+ return EPROTO;
+ }
+
+ for (i=0; i<3; i++) {
+ frame->data[i] = img.planes[i].data;
+ frame->linesize[i] = img.planes[i].ystride;
+ }
+
+ frame->size.w = img.width;
+ frame->size.h = img.height;
+ frame->fmt = VID_FMT_YUV420P;
+
+ ++vds->stats.n_frame;
+ }
+
+ return err;
+}