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_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; }
int h265_encode(struct videnc_state *st, bool update, const struct vidframe *frame, uint64_t timestamp) { AVFrame *pict = NULL; AVPacket *pkt = NULL; uint64_t rtp_ts; int i, ret, got_packet = 0, err = 0; if (!st || !frame) return EINVAL; if (!st->ctx || !vidsz_cmp(&st->size, &frame->size) || st->fmt != frame->fmt) { enum AVPixelFormat pix_fmt; pix_fmt = vidfmt_to_avpixfmt(frame->fmt); if (pix_fmt == AV_PIX_FMT_NONE) { warning("h265: encode: pixel format not supported" " (%s)\n", vidfmt_name(frame->fmt)); return ENOTSUP; } debug("h265: encoder: reset %u x %u (%s)\n", frame->size.w, frame->size.h, vidfmt_name(frame->fmt)); err = open_encoder(st, &frame->size, pix_fmt); if (err) return err; st->size = frame->size; st->fmt = frame->fmt; } pict = av_frame_alloc(); if (!pict) { err = ENOMEM; goto out; } pict->format = st->ctx->pix_fmt; pict->width = frame->size.w; pict->height = frame->size.h; pict->pts = timestamp; for (i=0; i<4; i++) { pict->data[i] = frame->data[i]; pict->linesize[i] = frame->linesize[i]; } if (update) { debug("h265: encoder picture update\n"); pict->key_frame = 1; pict->pict_type = AV_PICTURE_TYPE_I; } #if LIBAVUTIL_VERSION_MAJOR >= 55 pict->color_range = AVCOL_RANGE_MPEG; #endif #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100) pkt = av_packet_alloc(); if (!pkt) { err = ENOMEM; goto out; } ret = avcodec_send_frame(st->ctx, pict); if (ret < 0) { err = EBADMSG; goto out; } /* NOTE: packet contains 4-byte startcode */ ret = avcodec_receive_packet(st->ctx, pkt); if (ret < 0) { info("h265: no packet yet ..\n"); err = 0; goto out; } got_packet = 1; #else pkt = av_malloc(sizeof(*pkt)); if (!pkt) { err = ENOMEM; goto out; } av_init_packet(pkt); av_new_packet(pkt, 65536); ret = avcodec_encode_video2(st->ctx, pkt, pict, &got_packet); if (ret < 0) { err = EBADMSG; goto out; } #endif if (!got_packet) goto out; rtp_ts = video_calc_rtp_timestamp_fix(pkt->dts); err = packetize_annexb(rtp_ts, pkt->data, pkt->size, st->pktsize, st->pkth, st->arg); if (err) goto out; out: if (pict) av_free(pict); if (pkt) av_packet_free(&pkt); return err; }
int daala_encode(struct videnc_state *ves, bool update, const struct vidframe *frame) { int r, err = 0; daala_image img; unsigned i; (void)update; /* XXX: how to force a KEY-frame? */ if (!ves || !frame || frame->fmt != VID_FMT_YUV420P) return EINVAL; ++ves->stats.n_frame; if (!ves->enc || !vidsz_cmp(&ves->size, &frame->size)) { err = open_encoder(ves, &frame->size); if (err) return err; ves->size = frame->size; } img.planes[0].data = frame->data[0]; img.planes[0].xdec = 0; img.planes[0].ydec = 0; img.planes[0].xstride = 1; img.planes[0].ystride = frame->linesize[0]; img.planes[1].data = frame->data[1]; img.planes[1].xdec = 1; img.planes[1].ydec = 1; img.planes[1].xstride = 1; img.planes[1].ystride = frame->linesize[1]; img.planes[2].data = frame->data[2]; img.planes[2].xdec = 1; img.planes[2].ydec = 1; img.planes[2].xstride = 1; img.planes[2].ystride = frame->linesize[2]; for (i=0; i<3; i++) img.planes[i].bitdepth = 8; img.nplanes = 3; img.width = frame->size.w; img.height = frame->size.h; r = daala_encode_img_in(ves->enc, &img, 0); if (r != 0) { warning("daala: encoder: encode_img_in failed (ret = %d)\n", r); return EPROTO; } for (;;) { daala_packet dp; r = daala_encode_packet_out(ves->enc, 0, &dp); if (r < 0) { warning("daala: encoder: packet_out ret=%d\n", r); break; } else if (r == 0) { break; } err = send_packet(ves, dp.b_o_s, dp.packet, dp.bytes); if (err) break; } return 0; }