On Sat, 2 Sep 2017 21:27:03 +0200 Timo Rothenpieler <t...@rothenpieler.org> wrote:
> Signed-off-by: Timo Rothenpieler <t...@rothenpieler.org> > --- > libavcodec/nvenc.c | 65 > ++++++++++++++++++++++++++++++++++++++++--------- > libavcodec/nvenc.h | 6 +++++ libavcodec/nvenc_h264.c | 6 +++++ > libavcodec/nvenc_hevc.c | 4 +++ > 4 files changed, 70 insertions(+), 11 deletions(-) > > diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c > index 744e5e0e01..b54cb1275b 100644 > --- a/libavcodec/nvenc.c > +++ b/libavcodec/nvenc.c > @@ -1807,8 +1807,7 @@ static int output_ready(AVCodecContext *avctx, > int flush) return (nb_ready > 0) && (nb_ready + nb_pending >= > ctx->async_depth); } > > -int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, > - const AVFrame *frame, int *got_packet) > +int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) > { > NVENCSTATUS nv_status; > CUresult cu_res; > @@ -1823,12 +1822,16 @@ int ff_nvenc_encode_frame(AVCodecContext > *avctx, AVPacket *pkt, NV_ENC_PIC_PARAMS pic_params = { 0 }; > pic_params.version = NV_ENC_PIC_PARAMS_VER; > > + if (!ctx->cu_context || !ctx->nvencoder) > + return AVERROR(EINVAL); > + > + if (ctx->encoder_flushing) > + return AVERROR_EOF; > + > if (frame) { > inSurf = get_free_frame(ctx); > - if (!inSurf) { > - av_log(avctx, AV_LOG_ERROR, "No free surfaces\n"); > - return AVERROR_BUG; > - } > + if (!inSurf) > + return AVERROR(EAGAIN); > > cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); > if (cu_res != CUDA_SUCCESS) { > @@ -1876,6 +1878,7 @@ int ff_nvenc_encode_frame(AVCodecContext > *avctx, AVPacket *pkt, nvenc_codec_specific_pic_params(avctx, > &pic_params); } else { > pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS; > + ctx->encoder_flushing = 1; > } > > cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); > @@ -1914,7 +1917,23 @@ int ff_nvenc_encode_frame(AVCodecContext > *avctx, AVPacket *pkt, } > } > > - if (output_ready(avctx, !frame)) { > + return 0; > +} > + > +int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt) > +{ > + CUresult cu_res; > + CUcontext dummy; > + NvencSurface *tmpoutsurf; You can remove tmpoutsurf in ff_nvenc_send_frame > + int res; > + > + NvencContext *ctx = avctx->priv_data; > + NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; > + > + if (!ctx->cu_context || !ctx->nvencoder) > + return AVERROR(EINVAL); > + > + if (output_ready(avctx, ctx->encoder_flushing)) { > av_fifo_generic_read(ctx->output_surface_ready_queue, > &tmpoutsurf, sizeof(tmpoutsurf), NULL); > cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); > @@ -1935,10 +1954,34 @@ int ff_nvenc_encode_frame(AVCodecContext > *avctx, AVPacket *pkt, return res; > > av_fifo_generic_write(ctx->unused_surface_queue, > &tmpoutsurf, sizeof(tmpoutsurf), NULL); - > - *got_packet = 1; > + } else if (ctx->encoder_flushing) { > + return AVERROR_EOF; > } else { > + return AVERROR(EAGAIN); > + } > + > + return 0; > +} > + > +int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, > + const AVFrame *frame, int *got_packet) > +{ > + NvencContext *ctx = avctx->priv_data; > + int res; > + > + if (!ctx->encoder_flushing) { > + res = ff_nvenc_send_frame(avctx, frame); > + if (res < 0) > + return res; > + } > + > + res = ff_nvenc_receive_packet(avctx, pkt); > + if (res == AVERROR(EAGAIN) || res == AVERROR_EOF) { > *got_packet = 0; > + } else if (res < 0) { > + return res; > + } else { > + *got_packet = 1; > } > > return 0; > diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h > index 2c682275da..afb93cc22c 100644 > --- a/libavcodec/nvenc.h > +++ b/libavcodec/nvenc.h > @@ -116,6 +116,8 @@ typedef struct NvencContext > AVFifoBuffer *output_surface_ready_queue; > AVFifoBuffer *timestamp_list; > > + int encoder_flushing; > + > struct { > CUdeviceptr ptr; > NV_ENC_REGISTERED_PTR regptr; > @@ -169,6 +171,10 @@ int ff_nvenc_encode_init(AVCodecContext *avctx); > > int ff_nvenc_encode_close(AVCodecContext *avctx); > > +int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame); > + > +int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt); > + > int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, > const AVFrame *frame, int *got_packet); > > diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c > index 9adbe9f909..c3b4bac749 100644 > --- a/libavcodec/nvenc_h264.c > +++ b/libavcodec/nvenc_h264.c > @@ -164,6 +164,8 @@ AVCodec ff_nvenc_encoder = { > .type = AVMEDIA_TYPE_VIDEO, > .id = AV_CODEC_ID_H264, > .init = nvenc_old_init, > + .send_frame = ff_nvenc_send_frame, > + .receive_packet = ff_nvenc_receive_packet, > .encode2 = ff_nvenc_encode_frame, > .close = ff_nvenc_encode_close, > .priv_data_size = sizeof(NvencContext), > @@ -190,6 +192,8 @@ AVCodec ff_nvenc_h264_encoder = { > .type = AVMEDIA_TYPE_VIDEO, > .id = AV_CODEC_ID_H264, > .init = nvenc_old_init, > + .send_frame = ff_nvenc_send_frame, > + .receive_packet = ff_nvenc_receive_packet, > .encode2 = ff_nvenc_encode_frame, > .close = ff_nvenc_encode_close, > .priv_data_size = sizeof(NvencContext), > @@ -216,6 +220,8 @@ AVCodec ff_h264_nvenc_encoder = { > .type = AVMEDIA_TYPE_VIDEO, > .id = AV_CODEC_ID_H264, > .init = ff_nvenc_encode_init, > + .send_frame = ff_nvenc_send_frame, > + .receive_packet = ff_nvenc_receive_packet, > .encode2 = ff_nvenc_encode_frame, > .close = ff_nvenc_encode_close, > .priv_data_size = sizeof(NvencContext), > diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c > index 81da9d222d..89e8c3e53a 100644 > --- a/libavcodec/nvenc_hevc.c > +++ b/libavcodec/nvenc_hevc.c > @@ -153,6 +153,8 @@ AVCodec ff_nvenc_hevc_encoder = { > .type = AVMEDIA_TYPE_VIDEO, > .id = AV_CODEC_ID_HEVC, > .init = nvenc_old_init, > + .send_frame = ff_nvenc_send_frame, > + .receive_packet = ff_nvenc_receive_packet, > .encode2 = ff_nvenc_encode_frame, > .close = ff_nvenc_encode_close, > .priv_data_size = sizeof(NvencContext), > @@ -178,6 +180,8 @@ AVCodec ff_hevc_nvenc_encoder = { > .type = AVMEDIA_TYPE_VIDEO, > .id = AV_CODEC_ID_HEVC, > .init = ff_nvenc_encode_init, > + .send_frame = ff_nvenc_send_frame, > + .receive_packet = ff_nvenc_receive_packet, > .encode2 = ff_nvenc_encode_frame, > .close = ff_nvenc_encode_close, > .priv_data_size = sizeof(NvencContext), Otherwise looks good. --phil _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel