Esempio n. 1
0
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;
}
Esempio n. 2
0
int h265_encode(struct videnc_state *st, bool update,
		const struct vidframe *frame,
		videnc_packet_h *pkth, void *arg)
{
	x265_picture *pic_in = NULL, pic_out;
	x265_nal *nalv;
	uint32_t i, nalc = 0;
	int n, err = 0;

	if (!st || !frame || !pkth || frame->fmt != VID_FMT_YUV420P)
		return EINVAL;

	if (!st->x265 || !vidsz_cmp(&st->size, &frame->size)) {

		err = open_encoder(st, &frame->size);
		if (err)
			return err;

		st->size = frame->size;
	}

	if (update) {
		debug("h265: encode: picture update was requested\n");
	}

	pic_in = x265_picture_alloc();
	if (!pic_in) {
		warning("h265: x265_picture_alloc failed\n");
		return ENOMEM;
	}

	x265_picture_init(st->param, pic_in);

	pic_in->sliceType  = update ? X265_TYPE_IDR : X265_TYPE_AUTO;
	pic_in->pts        = ++st->pts;      /* XXX: add PTS to API */
	pic_in->colorSpace = X265_CSP_I420;

	for (i=0; i<3; i++) {
		pic_in->planes[i] = frame->data[i];
		pic_in->stride[i] = frame->linesize[i];
	}

	/* NOTE: important to get the PTS of the "out" picture */
	n = x265_encoder_encode(st->x265, &nalv, &nalc, pic_in, &pic_out);
	if (n <= 0)
		goto out;

	for (i=0; i<nalc; i++) {

		x265_nal *nal = &nalv[i];
		uint8_t *p = nal->payload;
		size_t len = nal->sizeBytes;
		bool marker;

#if 1
		debug("h265: encode: %s type=%2d  %s\n",
			  h265_is_keyframe(nal->type) ? "<KEY>" : "     ",
			  nal->type, h265_nalunit_name(nal->type));
#endif

		h265_skip_startcode(&p, &len);

		/* XXX: use pic_out.pts */

		marker = (i+1)==nalc;  /* last NAL */

		err = packetize(marker, p, len, st->pktsize, pkth, arg);
		if (err)
			goto out;
	}

 out:
	if (pic_in)
		x265_picture_free(pic_in);

	return err;
}