From 346aaad2b057f823b7181e7b6711badd2554e5c2 Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Sat, 4 Jun 2016 22:15:30 +0200 Subject: vp8: rename vpx.so module to vp8.so --- docs/README | 2 +- mk/modules.mk | 2 +- modules/vp8/decode.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++ modules/vp8/encode.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++ modules/vp8/module.mk | 14 +++ modules/vp8/sdp.c | 39 ++++++++ modules/vp8/vp8.c | 62 ++++++++++++ modules/vp8/vp8.h | 30 ++++++ modules/vpx/decode.c | 273 -------------------------------------------------- modules/vpx/encode.c | 257 ----------------------------------------------- modules/vpx/module.mk | 14 --- modules/vpx/sdp.c | 39 -------- modules/vpx/vp8.h | 30 ------ modules/vpx/vpx.c | 67 ------------- src/config.c | 2 +- 15 files changed, 678 insertions(+), 683 deletions(-) create mode 100644 modules/vp8/decode.c create mode 100644 modules/vp8/encode.c create mode 100644 modules/vp8/module.mk create mode 100644 modules/vp8/sdp.c create mode 100644 modules/vp8/vp8.c create mode 100644 modules/vp8/vp8.h delete mode 100644 modules/vpx/decode.c delete mode 100644 modules/vpx/encode.c delete mode 100644 modules/vpx/module.mk delete mode 100644 modules/vpx/sdp.c delete mode 100644 modules/vpx/vp8.h delete mode 100644 modules/vpx/vpx.c diff --git a/docs/README b/docs/README index 0108677..df5d779 100644 --- a/docs/README +++ b/docs/README @@ -216,7 +216,7 @@ v4l2_codec Video4Linux2 video codec module (H264 hardware encoding) vidbridge Video bridge module vidinfo Video info overlay module vidloop Video-loop test module -vpx VP8/VPX video codec +vp8 VP8 video codec vumeter Display audio levels in console wincons Console input driver for Windows winwave Audio driver for Windows diff --git a/mk/modules.mk b/mk/modules.mk index b674a92..305617d 100644 --- a/mk/modules.mk +++ b/mk/modules.mk @@ -414,7 +414,7 @@ ifneq ($(USE_V4L2),) MODULES += v4l2 v4l2_codec endif ifneq ($(USE_VPX),) -MODULES += vpx +MODULES += vp8 endif ifneq ($(USE_WINWAVE),) MODULES += winwave diff --git a/modules/vp8/decode.c b/modules/vp8/decode.c new file mode 100644 index 0000000..1722eb6 --- /dev/null +++ b/modules/vp8/decode.c @@ -0,0 +1,273 @@ +/** + * @file vp8/decode.c VP8 Decode + * + * Copyright (C) 2010 Creytiv.com + */ + +#include +#include +#include +#include +#include +#include +#include "vp8.h" + + +enum { + DECODE_MAXSZ = 524288, +}; + + +struct hdr { + unsigned x:1; + unsigned noref:1; + unsigned start:1; + unsigned partid:4; + /* extension fields */ + unsigned i:1; + unsigned l:1; + unsigned t:1; + unsigned k:1; + uint16_t picid; + uint8_t tl0picidx; + unsigned tid:2; + unsigned y:1; + unsigned keyidx:5; +}; + +struct viddec_state { + vpx_codec_ctx_t ctx; + struct mbuf *mb; + bool ctxup; + bool started; + uint16_t seq; +}; + + +static void destructor(void *arg) +{ + struct viddec_state *vds = arg; + + if (vds->ctxup) + vpx_codec_destroy(&vds->ctx); + + mem_deref(vds->mb); +} + + +int vp8_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, + const char *fmtp) +{ + struct viddec_state *vds; + vpx_codec_err_t res; + 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; + + vds->mb = mbuf_alloc(1024); + if (!vds->mb) { + err = ENOMEM; + goto out; + } + + res = vpx_codec_dec_init(&vds->ctx, &vpx_codec_vp8_dx_algo, NULL, 0); + if (res) { + err = ENOMEM; + goto out; + } + + vds->ctxup = true; + + out: + if (err) + mem_deref(vds); + else + *vdsp = vds; + + return err; +} + + +static inline int hdr_decode(struct hdr *hdr, struct mbuf *mb) +{ + uint8_t v; + + memset(hdr, 0, sizeof(*hdr)); + + if (mbuf_get_left(mb) < 1) + return EBADMSG; + + v = mbuf_read_u8(mb); + + hdr->x = v>>7 & 0x1; + hdr->noref = v>>5 & 0x1; + hdr->start = v>>4 & 0x1; + hdr->partid = v & 0x07; + + if (hdr->x) { + + if (mbuf_get_left(mb) < 1) + return EBADMSG; + + v = mbuf_read_u8(mb); + + hdr->i = v>>7 & 0x1; + hdr->l = v>>6 & 0x1; + hdr->t = v>>5 & 0x1; + hdr->k = v>>4 & 0x1; + } + + if (hdr->i) { + + if (mbuf_get_left(mb) < 1) + return EBADMSG; + + v = mbuf_read_u8(mb); + + if (v>>7 & 0x1) { + + if (mbuf_get_left(mb) < 1) + return EBADMSG; + + hdr->picid = (v & 0x7f)<<8; + hdr->picid += mbuf_read_u8(mb); + } + else { + hdr->picid = v & 0x7f; + } + } + + if (hdr->l) { + + if (mbuf_get_left(mb) < 1) + return EBADMSG; + + hdr->tl0picidx = mbuf_read_u8(mb); + } + + if (hdr->t || hdr->k) { + + if (mbuf_get_left(mb) < 1) + return EBADMSG; + + v = mbuf_read_u8(mb); + + hdr->tid = v>>6 & 0x3; + hdr->y = v>>5 & 0x1; + hdr->keyidx = v & 0x1f; + } + + return 0; +} + + +static inline int16_t seq_diff(uint16_t x, uint16_t y) +{ + return (int16_t)(y - x); +} + + +int vp8_decode(struct viddec_state *vds, struct vidframe *frame, + bool marker, uint16_t seq, struct mbuf *mb) +{ + vpx_codec_iter_t iter = NULL; + vpx_codec_err_t res; + vpx_image_t *img; + struct hdr hdr; + int err, i; + + if (!vds || !frame || !mb) + return EINVAL; + + err = hdr_decode(&hdr, mb); + if (err) + return err; + +#if 0 + debug("vp8: header: x=%u noref=%u start=%u partid=%u " + "i=%u l=%u t=%u k=%u " + "picid=%u tl0picidx=%u tid=%u y=%u keyidx=%u\n", + hdr.x, hdr.noref, hdr.start, hdr.partid, + hdr.i, hdr.l, hdr.t, hdr.k, + hdr.picid, hdr.tl0picidx, hdr.tid, hdr.y, hdr.keyidx); +#endif + + if (hdr.start && hdr.partid == 0) { + + mbuf_rewind(vds->mb); + vds->started = true; + } + else { + if (!vds->started) + return 0; + + if (seq_diff(vds->seq, seq) != 1) { + mbuf_rewind(vds->mb); + vds->started = false; + return 0; + } + } + + vds->seq = seq; + + err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb)); + if (err) + goto out; + + if (!marker) { + + if (vds->mb->end > DECODE_MAXSZ) { + warning("vp8: decode buffer size exceeded\n"); + err = ENOMEM; + goto out; + } + + return 0; + } + + res = vpx_codec_decode(&vds->ctx, vds->mb->buf, + (unsigned int)vds->mb->end, NULL, 1); + if (res) { + debug("vp8: decode error: %s\n", vpx_codec_err_to_string(res)); + err = EPROTO; + goto out; + } + + img = vpx_codec_get_frame(&vds->ctx, &iter); + if (!img) { + debug("vp8: no picture\n"); + goto out; + } + + if (img->fmt != VPX_IMG_FMT_I420) { + warning("vp8: bad pixel format (%i)\n", img->fmt); + goto out; + } + + for (i=0; i<4; i++) { + frame->data[i] = img->planes[i]; + frame->linesize[i] = img->stride[i]; + } + + frame->size.w = img->d_w; + frame->size.h = img->d_h; + frame->fmt = VID_FMT_YUV420P; + + out: + mbuf_rewind(vds->mb); + vds->started = false; + + return err; +} diff --git a/modules/vp8/encode.c b/modules/vp8/encode.c new file mode 100644 index 0000000..8b9e91b --- /dev/null +++ b/modules/vp8/encode.c @@ -0,0 +1,257 @@ +/** + * @file vp8/encode.c VP8 Encode + * + * Copyright (C) 2010 Creytiv.com + */ + +#include +#include +#include +#include +#include +#include +#include "vp8.h" + + +enum { + HDR_SIZE = 4, +}; + + +struct videnc_state { + vpx_codec_ctx_t ctx; + struct vidsz size; + vpx_codec_pts_t pts; + unsigned fps; + unsigned bitrate; + unsigned pktsize; + bool ctxup; + uint16_t picid; + videnc_packet_h *pkth; + void *arg; +}; + + +static void destructor(void *arg) +{ + struct videnc_state *ves = arg; + + if (ves->ctxup) + vpx_codec_destroy(&ves->ctx); +} + + +int vp8_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, + struct videnc_param *prm, const char *fmtp, + videnc_packet_h *pkth, void *arg) +{ + const struct vp8_vidcodec *vp8 = (struct vp8_vidcodec *)vc; + struct videnc_state *ves; + uint32_t max_fs; + (void)vp8; + + if (!vesp || !vc || !prm || prm->pktsize < (HDR_SIZE + 1)) + return EINVAL; + + ves = *vesp; + + if (!ves) { + + ves = mem_zalloc(sizeof(*ves), destructor); + if (!ves) + return ENOMEM; + + ves->picid = rand_u16(); + + *vesp = ves; + } + else { + if (ves->ctxup && (ves->bitrate != prm->bitrate || + ves->fps != prm->fps)) { + + vpx_codec_destroy(&ves->ctx); + ves->ctxup = false; + } + } + + ves->bitrate = prm->bitrate; + ves->pktsize = prm->pktsize; + ves->fps = prm->fps; + ves->pkth = pkth; + ves->arg = arg; + + max_fs = vp8_max_fs(fmtp); + if (max_fs > 0) + prm->max_fs = max_fs * 256; + + return 0; +} + + +static int open_encoder(struct videnc_state *ves, const struct vidsz *size) +{ + vpx_codec_enc_cfg_t cfg; + vpx_codec_err_t res; + + res = vpx_codec_enc_config_default(&vpx_codec_vp8_cx_algo, &cfg, 0); + if (res) + return EPROTO; + + cfg.g_profile = 2; + cfg.g_w = size->w; + cfg.g_h = size->h; + cfg.g_timebase.num = 1; + cfg.g_timebase.den = ves->fps; + cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; + cfg.g_pass = VPX_RC_ONE_PASS; + cfg.g_lag_in_frames = 0; + cfg.rc_end_usage = VPX_VBR; + cfg.rc_target_bitrate = ves->bitrate; + cfg.kf_mode = VPX_KF_AUTO; + + if (ves->ctxup) { + debug("vp8: re-opening encoder\n"); + vpx_codec_destroy(&ves->ctx); + ves->ctxup = false; + } + + res = vpx_codec_enc_init(&ves->ctx, &vpx_codec_vp8_cx_algo, &cfg, + VPX_CODEC_USE_OUTPUT_PARTITION); + if (res) { + warning("vp8: enc init: %s\n", vpx_codec_err_to_string(res)); + return EPROTO; + } + + ves->ctxup = true; + + res = vpx_codec_control(&ves->ctx, VP8E_SET_CPUUSED, 16); + if (res) { + warning("vp8: codec ctrl: %s\n", vpx_codec_err_to_string(res)); + } + + res = vpx_codec_control(&ves->ctx, VP8E_SET_NOISE_SENSITIVITY, 0); + if (res) { + warning("vp8: codec ctrl: %s\n", vpx_codec_err_to_string(res)); + } + + return 0; +} + + +static inline void hdr_encode(uint8_t hdr[HDR_SIZE], bool noref, bool start, + uint8_t partid, uint16_t picid) +{ + hdr[0] = 1<<7 | noref<<5 | start<<4 | (partid & 0x7); + hdr[1] = 1<<7; + hdr[2] = 1<<7 | (picid>>8 & 0x7f); + hdr[3] = picid & 0xff; +} + + +static inline int packetize(bool marker, const uint8_t *buf, size_t len, + size_t maxlen, bool noref, uint8_t partid, + uint16_t picid, videnc_packet_h *pkth, void *arg) +{ + uint8_t hdr[HDR_SIZE]; + bool start = true; + int err = 0; + + maxlen -= sizeof(hdr); + + while (len > maxlen) { + + hdr_encode(hdr, noref, start, partid, picid); + + err |= pkth(false, hdr, sizeof(hdr), buf, maxlen, arg); + + buf += maxlen; + len -= maxlen; + start = false; + } + + hdr_encode(hdr, noref, start, partid, picid); + + err |= pkth(marker, hdr, sizeof(hdr), buf, len, arg); + + return err; +} + + +int vp8_encode(struct videnc_state *ves, bool update, + const struct vidframe *frame) +{ + vpx_enc_frame_flags_t flags = 0; + vpx_codec_iter_t iter = NULL; + vpx_codec_err_t res; + vpx_image_t img; + int err, i; + + if (!ves || !frame || frame->fmt != VID_FMT_YUV420P) + return EINVAL; + + if (!ves->ctxup || !vidsz_cmp(&ves->size, &frame->size)) { + + err = open_encoder(ves, &frame->size); + if (err) + return err; + + ves->size = frame->size; + } + + if (update) { + /* debug("vp8: picture update\n"); */ + flags |= VPX_EFLAG_FORCE_KF; + } + + memset(&img, 0, sizeof(img)); + + img.fmt = VPX_IMG_FMT_I420; + img.w = img.d_w = frame->size.w; + img.h = img.d_h = frame->size.h; + + for (i=0; i<4; i++) { + img.stride[i] = frame->linesize[i]; + img.planes[i] = frame->data[i]; + } + + res = vpx_codec_encode(&ves->ctx, &img, ves->pts++, 1, + flags, VPX_DL_REALTIME); + if (res) { + warning("vp8: enc error: %s\n", vpx_codec_err_to_string(res)); + return ENOMEM; + } + + ++ves->picid; + + for (;;) { + bool keyframe = false, marker = true; + const vpx_codec_cx_pkt_t *pkt; + uint8_t partid = 0; + + pkt = vpx_codec_get_cx_data(&ves->ctx, &iter); + if (!pkt) + break; + + if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) + continue; + + if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) + keyframe = true; + + if (pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) + marker = false; + + if (pkt->data.frame.partition_id >= 0) + partid = pkt->data.frame.partition_id; + + err = packetize(marker, + pkt->data.frame.buf, + pkt->data.frame.sz, + ves->pktsize, !keyframe, partid, ves->picid, + ves->pkth, ves->arg); + if (err) + return err; + } + + return 0; +} diff --git a/modules/vp8/module.mk b/modules/vp8/module.mk new file mode 100644 index 0000000..4142af5 --- /dev/null +++ b/modules/vp8/module.mk @@ -0,0 +1,14 @@ +# +# module.mk +# +# Copyright (C) 2010 Creytiv.com +# + +MOD := vp8 +$(MOD)_SRCS += decode.c +$(MOD)_SRCS += encode.c +$(MOD)_SRCS += vp8.c +$(MOD)_SRCS += sdp.c +$(MOD)_LFLAGS += -lvpx + +include mk/mod.mk diff --git a/modules/vp8/sdp.c b/modules/vp8/sdp.c new file mode 100644 index 0000000..8d2ecca --- /dev/null +++ b/modules/vp8/sdp.c @@ -0,0 +1,39 @@ +/** + * @file vp8/sdp.c VP8 SDP Functions + * + * Copyright (C) 2010 Creytiv.com + */ + +#include +#include +#include "vp8.h" + + +uint32_t vp8_max_fs(const char *fmtp) +{ + struct pl pl, max_fs; + + if (!fmtp) + return 0; + + pl_set_str(&pl, fmtp); + + if (fmt_param_get(&pl, "max-fs", &max_fs)) + return pl_u32(&max_fs); + + return 0; +} + + +int vp8_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, + bool offer, void *arg) +{ + const struct vp8_vidcodec *vp8 = arg; + (void)offer; + + if (!mb || !fmt || !vp8 || !vp8->max_fs) + return 0; + + return mbuf_printf(mb, "a=fmtp:%s max-fs=%u\r\n", + fmt->id, vp8->max_fs); +} diff --git a/modules/vp8/vp8.c b/modules/vp8/vp8.c new file mode 100644 index 0000000..acaad12 --- /dev/null +++ b/modules/vp8/vp8.c @@ -0,0 +1,62 @@ +/** + * @file vp8.c VP8 Video Codec + * + * Copyright (C) 2010 Creytiv.com + */ +#include +#include +#include +#include "vp8.h" + + +/** + * @defgroup vp8 vp8 + * + * The VP8 video codec + * + * This module implements the VP8 video codec that is compatible + * with the WebRTC standard. + * + * References: + * + * http://www.webmproject.org/ + * + * https://tools.ietf.org/html/rfc7741 + */ + + +static struct vp8_vidcodec vp8 = { + .vc = { + .name = "VP8", + .encupdh = vp8_encode_update, + .ench = vp8_encode, + .decupdh = vp8_decode_update, + .dech = vp8_decode, + .fmtp_ench = vp8_fmtp_enc, + }, + .max_fs = 3600, +}; + + +static int module_init(void) +{ + vidcodec_register((struct vidcodec *)&vp8); + + return 0; +} + + +static int module_close(void) +{ + vidcodec_unregister((struct vidcodec *)&vp8); + + return 0; +} + + +EXPORT_SYM const struct mod_export DECL_EXPORTS(vp8) = { + "vp8", + "codec", + module_init, + module_close +}; diff --git a/modules/vp8/vp8.h b/modules/vp8/vp8.h new file mode 100644 index 0000000..934e3ee --- /dev/null +++ b/modules/vp8/vp8.h @@ -0,0 +1,30 @@ +/** + * @file vp8.h Private VP8 Interface + * + * Copyright (C) 2010 Creytiv.com + */ + +struct vp8_vidcodec { + struct vidcodec vc; + uint32_t max_fs; +}; + +/* Encode */ +int vp8_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, + struct videnc_param *prm, const char *fmtp, + videnc_packet_h *pkth, void *arg); +int vp8_encode(struct videnc_state *ves, bool update, + const struct vidframe *frame); + + +/* Decode */ +int vp8_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, + const char *fmtp); +int vp8_decode(struct viddec_state *vds, struct vidframe *frame, + bool marker, uint16_t seq, struct mbuf *mb); + + +/* SDP */ +uint32_t vp8_max_fs(const char *fmtp); +int vp8_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, + bool offer, void *arg); diff --git a/modules/vpx/decode.c b/modules/vpx/decode.c deleted file mode 100644 index f441619..0000000 --- a/modules/vpx/decode.c +++ /dev/null @@ -1,273 +0,0 @@ -/** - * @file vpx/decode.c VP8 Decode - * - * Copyright (C) 2010 Creytiv.com - */ - -#include -#include -#include -#include -#include -#include -#include "vp8.h" - - -enum { - DECODE_MAXSZ = 524288, -}; - - -struct hdr { - unsigned x:1; - unsigned noref:1; - unsigned start:1; - unsigned partid:4; - /* extension fields */ - unsigned i:1; - unsigned l:1; - unsigned t:1; - unsigned k:1; - uint16_t picid; - uint8_t tl0picidx; - unsigned tid:2; - unsigned y:1; - unsigned keyidx:5; -}; - -struct viddec_state { - vpx_codec_ctx_t ctx; - struct mbuf *mb; - bool ctxup; - bool started; - uint16_t seq; -}; - - -static void destructor(void *arg) -{ - struct viddec_state *vds = arg; - - if (vds->ctxup) - vpx_codec_destroy(&vds->ctx); - - mem_deref(vds->mb); -} - - -int vp8_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, - const char *fmtp) -{ - struct viddec_state *vds; - vpx_codec_err_t res; - 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; - - vds->mb = mbuf_alloc(1024); - if (!vds->mb) { - err = ENOMEM; - goto out; - } - - res = vpx_codec_dec_init(&vds->ctx, &vpx_codec_vp8_dx_algo, NULL, 0); - if (res) { - err = ENOMEM; - goto out; - } - - vds->ctxup = true; - - out: - if (err) - mem_deref(vds); - else - *vdsp = vds; - - return err; -} - - -static inline int hdr_decode(struct hdr *hdr, struct mbuf *mb) -{ - uint8_t v; - - memset(hdr, 0, sizeof(*hdr)); - - if (mbuf_get_left(mb) < 1) - return EBADMSG; - - v = mbuf_read_u8(mb); - - hdr->x = v>>7 & 0x1; - hdr->noref = v>>5 & 0x1; - hdr->start = v>>4 & 0x1; - hdr->partid = v & 0x07; - - if (hdr->x) { - - if (mbuf_get_left(mb) < 1) - return EBADMSG; - - v = mbuf_read_u8(mb); - - hdr->i = v>>7 & 0x1; - hdr->l = v>>6 & 0x1; - hdr->t = v>>5 & 0x1; - hdr->k = v>>4 & 0x1; - } - - if (hdr->i) { - - if (mbuf_get_left(mb) < 1) - return EBADMSG; - - v = mbuf_read_u8(mb); - - if (v>>7 & 0x1) { - - if (mbuf_get_left(mb) < 1) - return EBADMSG; - - hdr->picid = (v & 0x7f)<<8; - hdr->picid += mbuf_read_u8(mb); - } - else { - hdr->picid = v & 0x7f; - } - } - - if (hdr->l) { - - if (mbuf_get_left(mb) < 1) - return EBADMSG; - - hdr->tl0picidx = mbuf_read_u8(mb); - } - - if (hdr->t || hdr->k) { - - if (mbuf_get_left(mb) < 1) - return EBADMSG; - - v = mbuf_read_u8(mb); - - hdr->tid = v>>6 & 0x3; - hdr->y = v>>5 & 0x1; - hdr->keyidx = v & 0x1f; - } - - return 0; -} - - -static inline int16_t seq_diff(uint16_t x, uint16_t y) -{ - return (int16_t)(y - x); -} - - -int vp8_decode(struct viddec_state *vds, struct vidframe *frame, - bool marker, uint16_t seq, struct mbuf *mb) -{ - vpx_codec_iter_t iter = NULL; - vpx_codec_err_t res; - vpx_image_t *img; - struct hdr hdr; - int err, i; - - if (!vds || !frame || !mb) - return EINVAL; - - err = hdr_decode(&hdr, mb); - if (err) - return err; - -#if 0 - debug("vp8: header: x=%u noref=%u start=%u partid=%u " - "i=%u l=%u t=%u k=%u " - "picid=%u tl0picidx=%u tid=%u y=%u keyidx=%u\n", - hdr.x, hdr.noref, hdr.start, hdr.partid, - hdr.i, hdr.l, hdr.t, hdr.k, - hdr.picid, hdr.tl0picidx, hdr.tid, hdr.y, hdr.keyidx); -#endif - - if (hdr.start && hdr.partid == 0) { - - mbuf_rewind(vds->mb); - vds->started = true; - } - else { - if (!vds->started) - return 0; - - if (seq_diff(vds->seq, seq) != 1) { - mbuf_rewind(vds->mb); - vds->started = false; - return 0; - } - } - - vds->seq = seq; - - err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb)); - if (err) - goto out; - - if (!marker) { - - if (vds->mb->end > DECODE_MAXSZ) { - warning("vp8: decode buffer size exceeded\n"); - err = ENOMEM; - goto out; - } - - return 0; - } - - res = vpx_codec_decode(&vds->ctx, vds->mb->buf, - (unsigned int)vds->mb->end, NULL, 1); - if (res) { - debug("vp8: decode error: %s\n", vpx_codec_err_to_string(res)); - err = EPROTO; - goto out; - } - - img = vpx_codec_get_frame(&vds->ctx, &iter); - if (!img) { - debug("vp8: no picture\n"); - goto out; - } - - if (img->fmt != VPX_IMG_FMT_I420) { - warning("vp8: bad pixel format (%i)\n", img->fmt); - goto out; - } - - for (i=0; i<4; i++) { - frame->data[i] = img->planes[i]; - frame->linesize[i] = img->stride[i]; - } - - frame->size.w = img->d_w; - frame->size.h = img->d_h; - frame->fmt = VID_FMT_YUV420P; - - out: - mbuf_rewind(vds->mb); - vds->started = false; - - return err; -} diff --git a/modules/vpx/encode.c b/modules/vpx/encode.c deleted file mode 100644 index 0106c0a..0000000 --- a/modules/vpx/encode.c +++ /dev/null @@ -1,257 +0,0 @@ -/** - * @file vpx/encode.c VP8 Encode - * - * Copyright (C) 2010 Creytiv.com - */ - -#include -#include -#include -#include -#include -#include -#include "vp8.h" - - -enum { - HDR_SIZE = 4, -}; - - -struct videnc_state { - vpx_codec_ctx_t ctx; - struct vidsz size; - vpx_codec_pts_t pts; - unsigned fps; - unsigned bitrate; - unsigned pktsize; - bool ctxup; - uint16_t picid; - videnc_packet_h *pkth; - void *arg; -}; - - -static void destructor(void *arg) -{ - struct videnc_state *ves = arg; - - if (ves->ctxup) - vpx_codec_destroy(&ves->ctx); -} - - -int vp8_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, - struct videnc_param *prm, const char *fmtp, - videnc_packet_h *pkth, void *arg) -{ - const struct vp8_vidcodec *vp8 = (struct vp8_vidcodec *)vc; - struct videnc_state *ves; - uint32_t max_fs; - (void)vp8; - - if (!vesp || !vc || !prm || prm->pktsize < (HDR_SIZE + 1)) - return EINVAL; - - ves = *vesp; - - if (!ves) { - - ves = mem_zalloc(sizeof(*ves), destructor); - if (!ves) - return ENOMEM; - - ves->picid = rand_u16(); - - *vesp = ves; - } - else { - if (ves->ctxup && (ves->bitrate != prm->bitrate || - ves->fps != prm->fps)) { - - vpx_codec_destroy(&ves->ctx); - ves->ctxup = false; - } - } - - ves->bitrate = prm->bitrate; - ves->pktsize = prm->pktsize; - ves->fps = prm->fps; - ves->pkth = pkth; - ves->arg = arg; - - max_fs = vp8_max_fs(fmtp); - if (max_fs > 0) - prm->max_fs = max_fs * 256; - - return 0; -} - - -static int open_encoder(struct videnc_state *ves, const struct vidsz *size) -{ - vpx_codec_enc_cfg_t cfg; - vpx_codec_err_t res; - - res = vpx_codec_enc_config_default(&vpx_codec_vp8_cx_algo, &cfg, 0); - if (res) - return EPROTO; - - cfg.g_profile = 2; - cfg.g_w = size->w; - cfg.g_h = size->h; - cfg.g_timebase.num = 1; - cfg.g_timebase.den = ves->fps; - cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; - cfg.g_pass = VPX_RC_ONE_PASS; - cfg.g_lag_in_frames = 0; - cfg.rc_end_usage = VPX_VBR; - cfg.rc_target_bitrate = ves->bitrate; - cfg.kf_mode = VPX_KF_AUTO; - - if (ves->ctxup) { - debug("vp8: re-opening encoder\n"); - vpx_codec_destroy(&ves->ctx); - ves->ctxup = false; - } - - res = vpx_codec_enc_init(&ves->ctx, &vpx_codec_vp8_cx_algo, &cfg, - VPX_CODEC_USE_OUTPUT_PARTITION); - if (res) { - warning("vp8: enc init: %s\n", vpx_codec_err_to_string(res)); - return EPROTO; - } - - ves->ctxup = true; - - res = vpx_codec_control(&ves->ctx, VP8E_SET_CPUUSED, 16); - if (res) { - warning("vp8: codec ctrl: %s\n", vpx_codec_err_to_string(res)); - } - - res = vpx_codec_control(&ves->ctx, VP8E_SET_NOISE_SENSITIVITY, 0); - if (res) { - warning("vp8: codec ctrl: %s\n", vpx_codec_err_to_string(res)); - } - - return 0; -} - - -static inline void hdr_encode(uint8_t hdr[HDR_SIZE], bool noref, bool start, - uint8_t partid, uint16_t picid) -{ - hdr[0] = 1<<7 | noref<<5 | start<<4 | (partid & 0x7); - hdr[1] = 1<<7; - hdr[2] = 1<<7 | (picid>>8 & 0x7f); - hdr[3] = picid & 0xff; -} - - -static inline int packetize(bool marker, const uint8_t *buf, size_t len, - size_t maxlen, bool noref, uint8_t partid, - uint16_t picid, videnc_packet_h *pkth, void *arg) -{ - uint8_t hdr[HDR_SIZE]; - bool start = true; - int err = 0; - - maxlen -= sizeof(hdr); - - while (len > maxlen) { - - hdr_encode(hdr, noref, start, partid, picid); - - err |= pkth(false, hdr, sizeof(hdr), buf, maxlen, arg); - - buf += maxlen; - len -= maxlen; - start = false; - } - - hdr_encode(hdr, noref, start, partid, picid); - - err |= pkth(marker, hdr, sizeof(hdr), buf, len, arg); - - return err; -} - - -int vp8_encode(struct videnc_state *ves, bool update, - const struct vidframe *frame) -{ - vpx_enc_frame_flags_t flags = 0; - vpx_codec_iter_t iter = NULL; - vpx_codec_err_t res; - vpx_image_t img; - int err, i; - - if (!ves || !frame || frame->fmt != VID_FMT_YUV420P) - return EINVAL; - - if (!ves->ctxup || !vidsz_cmp(&ves->size, &frame->size)) { - - err = open_encoder(ves, &frame->size); - if (err) - return err; - - ves->size = frame->size; - } - - if (update) { - /* debug("vp8: picture update\n"); */ - flags |= VPX_EFLAG_FORCE_KF; - } - - memset(&img, 0, sizeof(img)); - - img.fmt = VPX_IMG_FMT_I420; - img.w = img.d_w = frame->size.w; - img.h = img.d_h = frame->size.h; - - for (i=0; i<4; i++) { - img.stride[i] = frame->linesize[i]; - img.planes[i] = frame->data[i]; - } - - res = vpx_codec_encode(&ves->ctx, &img, ves->pts++, 1, - flags, VPX_DL_REALTIME); - if (res) { - warning("vp8: enc error: %s\n", vpx_codec_err_to_string(res)); - return ENOMEM; - } - - ++ves->picid; - - for (;;) { - bool keyframe = false, marker = true; - const vpx_codec_cx_pkt_t *pkt; - uint8_t partid = 0; - - pkt = vpx_codec_get_cx_data(&ves->ctx, &iter); - if (!pkt) - break; - - if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) - continue; - - if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) - keyframe = true; - - if (pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) - marker = false; - - if (pkt->data.frame.partition_id >= 0) - partid = pkt->data.frame.partition_id; - - err = packetize(marker, - pkt->data.frame.buf, - pkt->data.frame.sz, - ves->pktsize, !keyframe, partid, ves->picid, - ves->pkth, ves->arg); - if (err) - return err; - } - - return 0; -} diff --git a/modules/vpx/module.mk b/modules/vpx/module.mk deleted file mode 100644 index bcd8c9d..0000000 --- a/modules/vpx/module.mk +++ /dev/null @@ -1,14 +0,0 @@ -# -# module.mk -# -# Copyright (C) 2010 Creytiv.com -# - -MOD := vpx -$(MOD)_SRCS += decode.c -$(MOD)_SRCS += encode.c -$(MOD)_SRCS += vpx.c -$(MOD)_SRCS += sdp.c -$(MOD)_LFLAGS += -lvpx - -include mk/mod.mk diff --git a/modules/vpx/sdp.c b/modules/vpx/sdp.c deleted file mode 100644 index 21ed9d6..0000000 --- a/modules/vpx/sdp.c +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file vpx/sdp.c VP8 SDP Functions - * - * Copyright (C) 2010 Creytiv.com - */ - -#include -#include -#include "vp8.h" - - -uint32_t vp8_max_fs(const char *fmtp) -{ - struct pl pl, max_fs; - - if (!fmtp) - return 0; - - pl_set_str(&pl, fmtp); - - if (fmt_param_get(&pl, "max-fs", &max_fs)) - return pl_u32(&max_fs); - - return 0; -} - - -int vp8_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, - bool offer, void *arg) -{ - const struct vp8_vidcodec *vp8 = arg; - (void)offer; - - if (!mb || !fmt || !vp8 || !vp8->max_fs) - return 0; - - return mbuf_printf(mb, "a=fmtp:%s max-fs=%u\r\n", - fmt->id, vp8->max_fs); -} diff --git a/modules/vpx/vp8.h b/modules/vpx/vp8.h deleted file mode 100644 index 934e3ee..0000000 --- a/modules/vpx/vp8.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file vp8.h Private VP8 Interface - * - * Copyright (C) 2010 Creytiv.com - */ - -struct vp8_vidcodec { - struct vidcodec vc; - uint32_t max_fs; -}; - -/* Encode */ -int vp8_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, - struct videnc_param *prm, const char *fmtp, - videnc_packet_h *pkth, void *arg); -int vp8_encode(struct videnc_state *ves, bool update, - const struct vidframe *frame); - - -/* Decode */ -int vp8_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, - const char *fmtp); -int vp8_decode(struct viddec_state *vds, struct vidframe *frame, - bool marker, uint16_t seq, struct mbuf *mb); - - -/* SDP */ -uint32_t vp8_max_fs(const char *fmtp); -int vp8_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, - bool offer, void *arg); diff --git a/modules/vpx/vpx.c b/modules/vpx/vpx.c deleted file mode 100644 index 0c17caa..0000000 --- a/modules/vpx/vpx.c +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file vpx.c VP8 video codec - * - * Copyright (C) 2010 Creytiv.com - */ -#include -#include -#include -#include -#define VPX_CODEC_DISABLE_COMPAT 1 -#define VPX_DISABLE_CTRL_TYPECHECKS 1 -#include -#include -#include -#include -#include "vp8.h" - - -/** - * @defgroup vpx vpx - * - * The VP8 video codec - * - * This module implements the VP8 video codec that is compatible - * with the WebRTC standard. - * - * References: - * - * http://www.webmproject.org/ - * - * https://tools.ietf.org/html/rfc7741 - */ - - -static struct vp8_vidcodec vpx = { - .vc = { - .name = "VP8", - .encupdh = vp8_encode_update, - .ench = vp8_encode, - .decupdh = vp8_decode_update, - .dech = vp8_decode, - .fmtp_ench = vp8_fmtp_enc, - }, - .max_fs = 3600 -}; - - -static int module_init(void) -{ - vidcodec_register((struct vidcodec *)&vpx); - return 0; -} - - -static int module_close(void) -{ - vidcodec_unregister((struct vidcodec *)&vpx); - return 0; -} - - -EXPORT_SYM const struct mod_export DECL_EXPORTS(vpx) = { - "vpx", - "codec", - module_init, - module_close -}; diff --git a/src/config.c b/src/config.c index 344a7bd..3995e64 100644 --- a/src/config.c +++ b/src/config.c @@ -602,7 +602,7 @@ int config_write_template(const char *file, const struct config *cfg) #else (void)re_fprintf(f, "#module\t\t\t" MOD_PRE "avcodec" MOD_EXT "\n"); #endif - (void)re_fprintf(f, "#module\t\t\t" MOD_PRE "vpx" MOD_EXT "\n"); + (void)re_fprintf(f, "#module\t\t\t" MOD_PRE "vp8" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Video filter Modules (in encoding order)\n"); (void)re_fprintf(f, "#module\t\t\t" MOD_PRE "selfview" MOD_EXT "\n"); -- cgit v1.2.3