/* * TODO: check input/output size */ static int ffdecode(struct viddec_state *st, struct vidframe *frame, bool eof, struct mbuf *src) { int i, got_picture, ret, err; /* assemble packets in "mbuf" */ err = mbuf_write_mem(st->mb, mbuf_buf(src), mbuf_get_left(src)); if (err) return err; if (!eof) return 0; st->mb->pos = 0; if (!st->got_keyframe) { err = EPROTO; goto out; } #if LIBAVCODEC_VERSION_INT <= ((52<<16)+(23<<8)+0) ret = avcodec_decode_video(st->ctx, st->pict, &got_picture, st->mb->buf, (int)mbuf_get_left(st->mb)); #else do { AVPacket avpkt; av_init_packet(&avpkt); avpkt.data = st->mb->buf; avpkt.size = (int)mbuf_get_left(st->mb); ret = avcodec_decode_video2(st->ctx, st->pict, &got_picture, &avpkt); } while (0); #endif if (ret < 0) { err = EBADMSG; goto out; } mbuf_skip_to_end(src); if (got_picture) { for (i=0; i<4; i++) { frame->data[i] = st->pict->data[i]; frame->linesize[i] = st->pict->linesize[i]; } frame->size.w = st->ctx->width; frame->size.h = st->ctx->height; frame->fmt = VID_FMT_YUV420P; } out: if (eof) mbuf_rewind(st->mb); return err; }
/** * Test parsing of various SDP messages from various vendors */ int test_sdp_parse(void) { struct sdp_session *sess = NULL; struct sdp_media *audio; struct mbuf *mb; struct sa laddr; uint32_t i; int err; mb = mbuf_alloc(2048); if (!mb) return ENOMEM; sa_init(&laddr, AF_INET); for (i=0; i<ARRAY_SIZE(msgs); i++) { sess = mem_deref(sess); err = sdp_session_alloc(&sess, &laddr); if (err) goto out; err = sdp_media_add(&audio, sess, sdp_media_audio, 5004, sdp_proto_rtpavp); if (err) goto out; err = sdp_format_add(NULL, audio, false, ref_pt, ref_cname, ref_srate, 1, NULL, NULL, NULL, false, NULL); if (err) goto out; err = sdp_format_add(NULL, audio, false, "8", "PCMA", 8000, 1, NULL, NULL, NULL, false, NULL); if (err) goto out; mbuf_rewind(mb); (void)mbuf_write_str(mb, msgs[i]); mb->pos = 0; err = sdp_decode(sess, mb, true); if (err) goto out; } out: mem_deref(sess); mem_deref(mb); return err; }
int encode(struct videnc_state *st, bool update, const struct vidframe *frame) { int i, err, ret; int pix_fmt; if (!st || !frame) return EINVAL; switch (frame->fmt) { case VID_FMT_YUV420P: pix_fmt = AV_PIX_FMT_YUV420P; break; case VID_FMT_NV12: pix_fmt = AV_PIX_FMT_NV12; break; default: warning("avcodec: pixel format not supported (%s)\n", vidfmt_name(frame->fmt)); return ENOTSUP; } if (!st->ctx || !vidsz_cmp(&st->encsize, &frame->size)) { err = open_encoder(st, &st->encprm, &frame->size, pix_fmt); if (err) { warning("avcodec: open_encoder: %m\n", err); return err; } } for (i=0; i<4; i++) { st->pict->data[i] = frame->data[i]; st->pict->linesize[i] = frame->linesize[i]; } st->pict->pts = st->pts++; if (update) { debug("avcodec: encoder picture update\n"); st->pict->key_frame = 1; #ifdef FF_I_TYPE st->pict->pict_type = FF_I_TYPE; /* Infra Frame */ #else st->pict->pict_type = AV_PICTURE_TYPE_I; #endif } else { st->pict->key_frame = 0; st->pict->pict_type = 0; } mbuf_rewind(st->mb); #if LIBAVCODEC_VERSION_INT >= ((54<<16)+(1<<8)+0) do { AVPacket avpkt; int got_packet; av_init_packet(&avpkt); avpkt.data = st->mb->buf; avpkt.size = (int)st->mb->size; ret = avcodec_encode_video2(st->ctx, &avpkt, st->pict, &got_packet); if (ret < 0) return EBADMSG; if (!got_packet) return 0; mbuf_set_end(st->mb, avpkt.size); } while (0); #else ret = avcodec_encode_video(st->ctx, st->mb->buf, (int)st->mb->size, st->pict); if (ret < 0 ) return EBADMSG; /* todo: figure out proper buffer size */ if (ret > (int)st->sz_max) { debug("avcodec: grow encode buffer %u --> %d\n", st->sz_max, ret); st->sz_max = ret; } mbuf_set_end(st->mb, ret); #endif switch (st->codec_id) { case AV_CODEC_ID_H263: err = h263_packetize(st, st->mb, st->pkth, st->arg); break; case AV_CODEC_ID_H264: err = h264_packetize(st->mb->buf, st->mb->end, st->encprm.pktsize, st->pkth, st->arg); break; case AV_CODEC_ID_MPEG4: err = general_packetize(st->mb, st->encprm.pktsize, st->pkth, st->arg); break; default: err = EPROTO; break; } return err; }
static int enc(struct vidcodec_st *st, bool update, const struct vidframe *frame) { int i, err, ret; if (!st->enc.ctx || !vidsz_cmp(&st->encsize, &frame->size)) { err = open_encoder(st, &st->encprm, &frame->size); if (err) { DEBUG_WARNING("open_encoder: %m\n", err); return err; } } for (i=0; i<4; i++) { st->enc.pict->data[i] = frame->data[i]; st->enc.pict->linesize[i] = frame->linesize[i]; } st->enc.pict->pts = st->pts++; if (update) { re_printf("avcodec encoder picture update\n"); st->enc.pict->key_frame = 1; #ifdef FF_I_TYPE st->enc.pict->pict_type = FF_I_TYPE; /* Infra Frame */ #else st->enc.pict->pict_type = AV_PICTURE_TYPE_I; #endif } else { st->enc.pict->key_frame = 0; st->enc.pict->pict_type = 0; } mbuf_rewind(st->enc.mb); #if LIBAVCODEC_VERSION_INT >= ((54<<16)+(1<<8)+0) do { AVPacket avpkt; int got_packet; avpkt.data = st->enc.mb->buf; avpkt.size = (int)st->enc.mb->size; ret = avcodec_encode_video2(st->enc.ctx, &avpkt, st->enc.pict, &got_packet); if (ret < 0) return EBADMSG; if (!got_packet) return 0; mbuf_set_end(st->enc.mb, avpkt.size); } while (0); #else ret = avcodec_encode_video(st->enc.ctx, st->enc.mb->buf, (int)st->enc.mb->size, st->enc.pict); if (ret < 0 ) return EBADMSG; /* todo: figure out proper buffer size */ if (ret > (int)st->enc.sz_max) { re_printf("note: grow encode buffer %u --> %d\n", st->enc.sz_max, ret); st->enc.sz_max = ret; } mbuf_set_end(st->enc.mb, ret); #endif switch (st->codec_id) { case CODEC_ID_H263: err = h263_packetize(st, st->enc.mb); break; case CODEC_ID_H264: err = h264_packetize(st, st->enc.mb); break; case CODEC_ID_MPEG4: err = general_packetize(st, st->enc.mb); break; default: err = EPROTO; break; } 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; }
uint8_t dns_get_seeds(struct context * ctx, struct mbuf *seeds_buf) { static int _env_checked = 0; if (!_env_checked) { _env_checked = 1; txtName = getenv("DYNOMITE_DNS_TXT_NAME"); if (txtName == NULL) txtName = DNS_TXT_NAME; } log_debug(LOG_VVERB, "checking for %s", txtName); if (!seeds_check()) { return DN_NOOPS; } unsigned char buf[BUFSIZ]; int r = res_query(txtName, C_IN, T_TXT, buf, sizeof(buf)); if (r == -1) { log_debug(LOG_DEBUG, "DNS response for %s: %s", txtName, hstrerror(h_errno)); return DN_NOOPS; } if (r >= sizeof(buf)) { log_debug(LOG_DEBUG, "DNS reply is too large for %s: %d, bufsize: %d", txtName, r, sizeof(buf)); return DN_NOOPS; } HEADER *hdr = (HEADER*)buf; if (hdr->rcode != NOERROR) { log_debug(LOG_DEBUG, "DNS reply code for %s: %d", txtName, hdr->rcode); return DN_NOOPS; } int na = ntohs(hdr->ancount); ns_msg m; int k = ns_initparse(buf, r, &m); if (k == -1) { log_debug(LOG_DEBUG, "ns_initparse error for %s: %s", txtName, strerror(errno)); return DN_NOOPS; } int i; ns_rr rr; for (i = 0; i < na; ++i) { int k = ns_parserr(&m, ns_s_an, i, &rr); if (k == -1) { log_debug(LOG_DEBUG, "ns_parserr for %s: %s", txtName, strerror (errno)); return DN_NOOPS; } mbuf_rewind(seeds_buf); unsigned char *r = ns_rr_rdata(rr); if (r[0] >= ns_rr_rdlen(rr)) { log_debug(LOG_DEBUG, "invalid TXT length for %s: %d < %d", txtName, r[0], ns_rr_rdlen(rr)); return DN_NOOPS; } log_debug(LOG_VERB, "seeds for %s: %.*s", txtName, r[0], r +1); mbuf_copy(seeds_buf, r + 1, r[0]); } uint32_t seeds_hash = hash_seeds(seeds_buf->pos, mbuf_length(seeds_buf)); if (last_seeds_hash != seeds_hash) { last_seeds_hash = seeds_hash; } else { return DN_NOOPS; } return DN_OK; }