static int decode_frame(struct aucodec_st *st, struct mbuf *dst, struct mbuf *src, uint16_t src_len) { int ret, err; if (mbuf_get_left(src) < src_len) { DEBUG_WARNING("dec: corrupt frame %u < %u\n", mbuf_get_left(src), src_len); return EPROTO; } /* Make sure there is enough space in the buffer */ if (mbuf_get_space(dst) < st->fsize) { err = mbuf_resize(dst, dst->size + st->fsize); if (err) return err; } ret = celt_decode(st->dec, mbuf_buf(src), src_len, (short *)mbuf_buf(dst), st->frame_size); if (CELT_OK != ret) { DEBUG_WARNING("celt_decode: ret=%d\n", ret); } DEBUG_INFO("decode: %u -> %u\n", src_len, st->fsize); if (src) mbuf_advance(src, src_len); dst->end += st->fsize; return 0; }
static int general_packetize(struct vidcodec_st *st, struct mbuf *mb) { int err = 0; /* Assemble frame into smaller packets */ while (!err) { size_t sz, left = mbuf_get_left(mb); bool last = (left < MAX_RTP_SIZE); if (!left) break; sz = last ? left : MAX_RTP_SIZE; st->mb_frag->pos = st->mb_frag->end = RTP_PRESZ; err = mbuf_write_mem(st->mb_frag, mbuf_buf(mb), sz); if (err) break; st->mb_frag->pos = RTP_PRESZ; err = st->sendh(last, st->mb_frag, st->arg); mbuf_advance(mb, sz); } return err; }
/** * Send an RTP packet to a peer * * @param rs RTP Socket * @param dst Destination address * @param ext Extension bit * @param marker Marker bit * @param pt Payload type * @param ts Timestamp * @param mb Payload buffer * * @return 0 for success, otherwise errorcode */ int rtp_send(struct rtp_sock *rs, const struct sa *dst, bool ext, bool marker, uint8_t pt, uint32_t ts, struct mbuf *mb) { size_t pos; int err; if (!rs || !mb) return EINVAL; if (mb->pos < RTP_HEADER_SIZE) { DEBUG_WARNING("rtp_send: buffer must have space for" " rtp header (pos=%u, end=%u)\n", mb->pos, mb->end); return EBADMSG; } mbuf_advance(mb, -RTP_HEADER_SIZE); pos = mb->pos; err = rtp_encode(rs, ext, marker, pt, ts, mb); if (err) return err; if (rs->rtcp) rtcp_sess_tx_rtp(rs->rtcp, ts, mbuf_get_left(mb)); mb->pos = pos; return udp_send(rs->sock_rtp, dst, mb); }
int rtp_un(srtp_t srtp, struct mbuf *mb) { int err, len; if(srtp) { mbuf_advance(mb, -RTP_HEADER_SIZE); len = (int)mbuf_get_left(mb); err = srtp_unprotect(srtp, mbuf_buf(mb), &len); if(err) { printf("srtp unprotect fail %d\n", err); return -1; } mbuf_advance(mb, RTP_HEADER_SIZE); len -= RTP_HEADER_SIZE; } else { len = (int)mbuf_get_left(mb); } return len; }
/** * Decode an RTCP Payload-Specific Feedback Message * * @param mb Buffer to decode * @param msg RTCP Message to decode into * * @return 0 for success, otherwise errorcode */ int rtcp_psfb_decode(struct mbuf *mb, struct rtcp_msg *msg) { size_t i, sz; if (!msg) return EINVAL; switch (msg->hdr.count) { case RTCP_PSFB_PLI: /* no params */ break; case RTCP_PSFB_SLI: sz = msg->r.fb.n * sizeof(*msg->r.fb.fci.sliv); msg->r.fb.fci.sliv = mem_alloc(sz, NULL); if (!msg->r.fb.fci.sliv) return ENOMEM; if (mbuf_get_left(mb) < msg->r.fb.n * SLI_SIZE) return EBADMSG; for (i=0; i<msg->r.fb.n; i++) { const uint32_t v = ntohl(mbuf_read_u32(mb)); msg->r.fb.fci.sliv[i].first = v>>19 & 0x1fff; msg->r.fb.fci.sliv[i].number = v>> 6 & 0x1fff; msg->r.fb.fci.sliv[i].picid = v>> 0 & 0x003f; } break; case RTCP_PSFB_AFB: sz = msg->r.fb.n * 4; if (mbuf_get_left(mb) < sz) return EBADMSG; msg->r.fb.fci.afb = mbuf_alloc_ref(mb); if (!msg->r.fb.fci.afb) return ENOMEM; msg->r.fb.fci.afb->end = msg->r.fb.fci.afb->pos + sz; mbuf_advance(mb, sz); break; default: DEBUG_NOTICE("unknown PSFB fmt %d\n", msg->hdr.count); break; } return 0; }
static int h263_packetize(struct videnc_state *st, struct mbuf *mb, videnc_packet_h *pkth, void *arg) { struct h263_strm h263_strm; struct h263_hdr h263_hdr; size_t pos; int err; /* Decode bit-stream header, used by packetizer */ err = h263_strm_decode(&h263_strm, mb); if (err) return err; h263_hdr_copy_strm(&h263_hdr, &h263_strm); st->mb_frag->pos = st->mb_frag->end = 0; err = h263_hdr_encode(&h263_hdr, st->mb_frag); pos = st->mb_frag->pos; /* Assemble frame into smaller packets */ while (!err) { size_t sz, left = mbuf_get_left(mb); bool last = (left < st->encprm.pktsize); if (!left) break; sz = last ? left : st->encprm.pktsize; st->mb_frag->pos = st->mb_frag->end = pos; err = mbuf_write_mem(st->mb_frag, mbuf_buf(mb), sz); if (err) break; st->mb_frag->pos = 0; err = pkth(last, NULL, 0, mbuf_buf(st->mb_frag), mbuf_get_left(st->mb_frag), arg); mbuf_advance(mb, sz); } return err; }
static int encode_frame(struct aucodec_st *st, uint16_t *size, uint8_t *buf, struct mbuf *src) { int len; /* NOTE: PCM audio in signed 16-bit format (native endian) */ len = celt_encode(st->enc, (short *)mbuf_buf(src), st->frame_size, buf, st->bytes_per_packet); if (len < 0) { DEBUG_WARNING("celt_encode: returned %d\n", len); return EINVAL; } DEBUG_INFO("encode: %u -> %d\n", mbuf_get_left(src), len); *size = len; mbuf_advance(src, st->fsize); return 0; }
static int general_packetize(struct mbuf *mb, size_t pktsize, videnc_packet_h *pkth, void *arg) { int err = 0; /* Assemble frame into smaller packets */ while (!err) { size_t sz, left = mbuf_get_left(mb); bool last = (left < pktsize); if (!left) break; sz = last ? left : pktsize; err = pkth(last, NULL, 0, mbuf_buf(mb), sz, arg); mbuf_advance(mb, sz); } return err; }
int h265_decode(struct viddec_state *vds, struct vidframe *frame, bool marker, uint16_t seq, struct mbuf *mb) { static const uint8_t nal_seq[3] = {0, 0, 1}; int err, ret, got_picture, i; struct h265_nal hdr; AVPacket avpkt; enum vidfmt fmt; if (!vds || !frame || !mb) return EINVAL; err = h265_nal_decode(&hdr, mbuf_buf(mb)); if (err) return err; mbuf_advance(mb, H265_HDR_SIZE); #if 1 debug("h265: decode: %s type=%2d %s\n", h265_is_keyframe(hdr.nal_unit_type) ? "<KEY>" : " ", hdr.nal_unit_type, h265_nalunit_name(hdr.nal_unit_type)); #endif if (vds->frag && hdr.nal_unit_type != H265_NAL_FU) { debug("h265: lost fragments; discarding previous NAL\n"); fragment_rewind(vds); vds->frag = false; } /* handle NAL types */ if (0 <= hdr.nal_unit_type && hdr.nal_unit_type <= 40) { mb->pos -= H265_HDR_SIZE; err = mbuf_write_mem(vds->mb, nal_seq, 3); err |= mbuf_write_mem(vds->mb, mbuf_buf(mb),mbuf_get_left(mb)); if (err) goto out; } else if (H265_NAL_FU == hdr.nal_unit_type) { struct fu fu; err = fu_decode(&fu, mb); if (err) return err; if (fu.s) { if (vds->frag) { debug("h265: lost fragments; ignoring NAL\n"); fragment_rewind(vds); } vds->frag_start = vds->mb->pos; vds->frag = true; hdr.nal_unit_type = fu.type; err = mbuf_write_mem(vds->mb, nal_seq, 3); err = h265_nal_encode_mbuf(vds->mb, &hdr); if (err) goto out; } else { if (!vds->frag) { debug("h265: ignoring fragment\n"); return 0; } if (seq_diff(vds->frag_seq, seq) != 1) { debug("h265: lost fragments detected\n"); fragment_rewind(vds); vds->frag = false; return 0; } } err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb)); if (err) goto out; if (fu.e) vds->frag = false; vds->frag_seq = seq; } else { warning("h265: unknown NAL type %u\n", hdr.nal_unit_type); return ENOSYS; } if (!marker) { if (vds->mb->end > DECODE_MAXSZ) { warning("h265: decode buffer size exceeded\n"); err = ENOMEM; goto out; } return 0; } if (vds->frag) { err = EPROTO; goto out; } av_init_packet(&avpkt); avpkt.data = vds->mb->buf; avpkt.size = (int)vds->mb->end; ret = avcodec_decode_video2(vds->ctx, vds->pict, &got_picture, &avpkt); if (ret < 0) { debug("h265: decode error\n"); err = EPROTO; goto out; } if (!got_picture) { /* debug("h265: no picture\n"); */ goto out; } switch (vds->pict->format) { case PIX_FMT_YUV420P: fmt = VID_FMT_YUV420P; break; #if 0 case PIX_FMT_YUV444P: fmt = VID_FMT_YUV444; break; #endif default: warning("h265: decode: bad pixel format (%i) (%s)\n", vds->pict->format, av_get_pix_fmt_name(vds->pict->format)); goto out; } for (i=0; i<4; i++) { frame->data[i] = vds->pict->data[i]; frame->linesize[i] = vds->pict->linesize[i]; } frame->size.w = vds->ctx->width; frame->size.h = vds->ctx->height; frame->fmt = fmt; out: mbuf_rewind(vds->mb); vds->frag = false; return err; }
/** * Decode one RTCP message from a buffer * * @param msgp Pointer to allocated RTCP Message * @param mb Buffer to decode from * * @return 0 for success, otherwise errorcode */ int rtcp_decode(struct rtcp_msg **msgp, struct mbuf *mb) { struct rtcp_msg *msg = NULL; size_t start, i, sz, count, rem; int err; if (!msgp) return EINVAL; if (mbuf_get_left(mb) < RTCP_HDR_SIZE) return EBADMSG; msg = mem_zalloc(sizeof(*msg), rtcp_destructor); if (!msg) return ENOMEM; start = mb->pos; /* decode and check header */ err = rtcp_hdr_decode(mb, &msg->hdr); if (err) goto out; if (msg->hdr.version != RTCP_VERSION) goto badmsg; /* check length and remaining */ rem = msg->hdr.length * sizeof(uint32_t); if (mbuf_get_left(mb) < rem) goto badmsg; count = msg->hdr.count; switch (msg->hdr.pt) { case RTCP_SR: if (mbuf_get_left(mb) < (RTCP_SRC_SIZE + RTCP_SR_SIZE)) goto badmsg; msg->r.sr.ssrc = ntohl(mbuf_read_u32(mb)); msg->r.sr.ntp_sec = ntohl(mbuf_read_u32(mb)); msg->r.sr.ntp_frac = ntohl(mbuf_read_u32(mb)); msg->r.sr.rtp_ts = ntohl(mbuf_read_u32(mb)); msg->r.sr.psent = ntohl(mbuf_read_u32(mb)); msg->r.sr.osent = ntohl(mbuf_read_u32(mb)); err = rtcp_rr_alloc(&msg->r.sr.rrv, count); if (err) goto out; for (i=0; i<count && !err; i++) err = rtcp_rr_decode(mb, &msg->r.sr.rrv[i]); break; case RTCP_RR: if (mbuf_get_left(mb) < RTCP_SRC_SIZE) goto badmsg; msg->r.rr.ssrc = ntohl(mbuf_read_u32(mb)); err = rtcp_rr_alloc(&msg->r.rr.rrv, count); if (err) goto out; for (i=0; i<count && !err; i++) err = rtcp_rr_decode(mb, &msg->r.rr.rrv[i]); break; case RTCP_SDES: if (count == 0) break; sz = count * sizeof(*msg->r.sdesv); msg->r.sdesv = mem_zalloc(sz, NULL); if (!msg->r.sdesv) { err = ENOMEM; goto out; } for (i=0; i<msg->hdr.count && !err; i++) err = rtcp_sdes_decode(mb, &msg->r.sdesv[i]); break; case RTCP_BYE: sz = count * sizeof(*msg->r.bye.srcv); msg->r.bye.srcv = mem_alloc(sz, NULL); if (!msg->r.bye.srcv) { err = ENOMEM; goto out; } if (mbuf_get_left(mb) < sz) goto badmsg; for (i=0; i<count; i++) msg->r.bye.srcv[i] = ntohl(mbuf_read_u32(mb)); /* decode reason (optional) */ if (rem > count*sizeof(uint32_t)) { const size_t len = mbuf_read_u8(mb); if (mbuf_get_left(mb) < len) goto badmsg; err = mbuf_strdup(mb, &msg->r.bye.reason, len); } break; case RTCP_APP: if (mbuf_get_left(mb) < RTCP_APP_SIZE) goto badmsg; msg->r.app.src = ntohl(mbuf_read_u32(mb)); (void)mbuf_read_mem(mb, (uint8_t *)msg->r.app.name, sizeof(msg->r.app.name)); if (rem > RTCP_APP_SIZE) { msg->r.app.data_len = rem - RTCP_APP_SIZE; msg->r.app.data = mem_alloc(msg->r.app.data_len, NULL); if (!msg->r.app.data) { err = ENOMEM; goto out; } if (mbuf_get_left(mb) < msg->r.app.data_len) goto badmsg; (void)mbuf_read_mem(mb, msg->r.app.data, msg->r.app.data_len); } break; case RTCP_FIR: if (mbuf_get_left(mb) < RTCP_FIR_SIZE) goto badmsg; msg->r.fir.ssrc = ntohl(mbuf_read_u32(mb)); break; case RTCP_NACK: if (mbuf_get_left(mb) < RTCP_NACK_SIZE) goto badmsg; msg->r.nack.ssrc = ntohl(mbuf_read_u32(mb)); msg->r.nack.fsn = ntohs(mbuf_read_u16(mb)); msg->r.nack.blp = ntohs(mbuf_read_u16(mb)); break; case RTCP_RTPFB: if (mbuf_get_left(mb) < RTCP_FB_SIZE) goto badmsg; msg->r.fb.ssrc_packet = ntohl(mbuf_read_u32(mb)); msg->r.fb.ssrc_media = ntohl(mbuf_read_u32(mb)); msg->r.fb.n = msg->hdr.length - 2; err = rtcp_rtpfb_decode(mb, msg); break; case RTCP_PSFB: if (mbuf_get_left(mb) < RTCP_FB_SIZE) goto badmsg; msg->r.fb.ssrc_packet = ntohl(mbuf_read_u32(mb)); msg->r.fb.ssrc_media = ntohl(mbuf_read_u32(mb)); msg->r.fb.n = msg->hdr.length - 2; err = rtcp_psfb_decode(mb, msg); break; default: /* unknown message type */ mbuf_advance(mb, rem); break; } if (err) goto out; /* slurp padding */ while ((mb->pos - start) & 0x3 && mbuf_get_left(mb)) ++mb->pos; out: if (err) mem_deref(msg); else *msgp = msg; return err; badmsg: mem_deref(msg); return EBADMSG; }