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; }