/** * @file mock/mock_vidcodec.c Mock video codec * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include "../test.h" #define HDR_SIZE 12 struct hdr { enum vidfmt fmt; unsigned width; unsigned height; }; struct videnc_state { int64_t pts; double fps; videnc_packet_h *pkth; void *arg; }; struct viddec_state { struct vidframe *frame; }; static int hdr_decode(struct hdr *hdr, struct mbuf *mb) { if (mbuf_get_left(mb) < HDR_SIZE) return EBADMSG; hdr->fmt = ntohl(mbuf_read_u32(mb)); hdr->width = ntohl(mbuf_read_u32(mb)); hdr->height = ntohl(mbuf_read_u32(mb)); return 0; } static void decode_destructor(void *arg) { struct viddec_state *vds = arg; mem_deref(vds->frame); } static int mock_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg) { struct videnc_state *ves; (void)fmtp; if (!vesp || !vc || !prm || prm->pktsize < (HDR_SIZE + 1)) return EINVAL; ves = *vesp; if (!ves) { ves = mem_zalloc(sizeof(*ves), NULL); if (!ves) return ENOMEM; *vesp = ves; } ves->fps = prm->fps; ves->pkth = pkth; ves->arg = arg; return 0; } static int mock_encode(struct videnc_state *ves, bool update, const struct vidframe *frame) { struct mbuf *hdr; uint8_t payload[2] = {0,0}; uint64_t rtp_ts; int err; (void)update; if (!ves || !frame) return EINVAL; hdr = mbuf_alloc(16); err = mbuf_write_u32(hdr, htonl(frame->fmt)); err |= mbuf_write_u32(hdr, htonl(frame->size.w)); err |= mbuf_write_u32(hdr, htonl(frame->size.h)); if (err) goto out; rtp_ts = video_calc_rtp_timestamp(++ves->pts, ves->fps); err = ves->pkth(true, rtp_ts, hdr->buf, hdr->end, payload, sizeof(payload), ves->arg); if (err) goto out; out: mem_deref(hdr); return err; } static int mock_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), decode_destructor); if (!vds) return ENOMEM; if (err) mem_deref(vds); else *vdsp = vds; return err; } static int mock_decode(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb) { struct vidsz size; struct hdr hdr; int err, i; (void)marker; (void)seq; if (!vds || !frame || !intra || !mb) return EINVAL; *intra = false; err = hdr_decode(&hdr, mb); if (err) { warning("mock_vidcodec: could not decode header (%m)\n", err); return err; } size.w = hdr.width; size.h = hdr.height; if (!vds->frame) { err = vidframe_alloc(&vds->frame, hdr.fmt, &size); if (err) goto out; } for (i=0; i<4; i++) { frame->data[i] = vds->frame->data[i]; frame->linesize[i] = vds->frame->linesize[i]; } frame->size.w = vds->frame->size.w; frame->size.h = vds->frame->size.h; frame->fmt = vds->frame->fmt; out: return err; } static struct vidcodec vc_dummy = { .name = "H266", .encupdh = mock_encode_update, .ench = mock_encode, .decupdh = mock_decode_update, .dech = mock_decode, }; void mock_vidcodec_register(void) { vidcodec_register(baresip_vidcodecl(), &vc_dummy); } void mock_vidcodec_unregister(void) { vidcodec_unregister(&vc_dummy); }