Message ID | 20230327200956.2138-1-jamrial@gmail.com |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel,1/2] avcodec/libx264: add a flush callback | expand |
Context | Check | Description |
---|---|---|
andriy/make_x86 | success | Make finished |
andriy/make_fate_x86 | success | Make fate finished |
James Almer: > Signed-off-by: James Almer <jamrial@gmail.com> > --- > libavcodec/libx264.c | 24 ++++++++++++++++++++++-- > 1 file changed, 22 insertions(+), 2 deletions(-) > > diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c > index 92828fabc3..72c3b6cedc 100644 > --- a/libavcodec/libx264.c > +++ b/libavcodec/libx264.c > @@ -178,8 +178,8 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, > memcpy(p, x4->sei, x4->sei_size); > p += x4->sei_size; > size -= x4->sei_size; > - x4->sei_size = 0; > - av_freep(&x4->sei); > + /* Keep the value around in case of flush */ > + x4->sei_size = -x4->sei_size; > } > > /* x264 guarantees the payloads of the NALs > @@ -648,6 +648,24 @@ FF_ENABLE_DEPRECATION_WARNINGS > return 0; > } > > +static void X264_flush(AVCodecContext *avctx) > +{ > + X264Context *x4 = avctx->priv_data; > + x264_nal_t *nal; > + int nnal, ret; > + x264_picture_t pic_out = {0}; > + > + do { > + ret = x264_encoder_encode(x4->enc, &nal, &nnal, NULL, &pic_out); > + } while (ret > 0 && x264_encoder_delayed_frames(x4->enc)); > + > + for (int i = 0; i < x4->nb_reordered_opaque; i++) > + opaque_uninit(&x4->reordered_opaque[i]); > + > + if (x4->sei_size < 0) > + x4->sei_size = -x4->sei_size; > +} > + > static av_cold int X264_close(AVCodecContext *avctx) > { > X264Context *x4 = avctx->priv_data; > @@ -1335,12 +1353,14 @@ FFCodec ff_libx264_encoder = { > .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | > AV_CODEC_CAP_OTHER_THREADS | > AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE | > + AV_CODEC_CAP_ENCODER_FLUSH | > AV_CODEC_CAP_ENCODER_RECON_FRAME, > .p.priv_class = &x264_class, > .p.wrapper_name = "libx264", > .priv_data_size = sizeof(X264Context), > .init = X264_init, > FF_CODEC_ENCODE_CB(X264_frame), > + .flush = X264_flush, > .close = X264_close, > .defaults = x264_defaults, > #if X264_BUILD < 153 Wasn't AV_CODEC_CAP_ENCODER_FLUSH supposed to be only implemented for hardware encoders where closing and reopening an encoder is costly? - Andreas
On 3/27/2023 5:33 PM, Andreas Rheinhardt wrote: > James Almer: >> Signed-off-by: James Almer <jamrial@gmail.com> >> --- >> libavcodec/libx264.c | 24 ++++++++++++++++++++++-- >> 1 file changed, 22 insertions(+), 2 deletions(-) >> >> diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c >> index 92828fabc3..72c3b6cedc 100644 >> --- a/libavcodec/libx264.c >> +++ b/libavcodec/libx264.c >> @@ -178,8 +178,8 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, >> memcpy(p, x4->sei, x4->sei_size); >> p += x4->sei_size; >> size -= x4->sei_size; >> - x4->sei_size = 0; >> - av_freep(&x4->sei); >> + /* Keep the value around in case of flush */ >> + x4->sei_size = -x4->sei_size; >> } >> >> /* x264 guarantees the payloads of the NALs >> @@ -648,6 +648,24 @@ FF_ENABLE_DEPRECATION_WARNINGS >> return 0; >> } >> >> +static void X264_flush(AVCodecContext *avctx) >> +{ >> + X264Context *x4 = avctx->priv_data; >> + x264_nal_t *nal; >> + int nnal, ret; >> + x264_picture_t pic_out = {0}; >> + >> + do { >> + ret = x264_encoder_encode(x4->enc, &nal, &nnal, NULL, &pic_out); >> + } while (ret > 0 && x264_encoder_delayed_frames(x4->enc)); >> + >> + for (int i = 0; i < x4->nb_reordered_opaque; i++) >> + opaque_uninit(&x4->reordered_opaque[i]); >> + >> + if (x4->sei_size < 0) >> + x4->sei_size = -x4->sei_size; >> +} >> + >> static av_cold int X264_close(AVCodecContext *avctx) >> { >> X264Context *x4 = avctx->priv_data; >> @@ -1335,12 +1353,14 @@ FFCodec ff_libx264_encoder = { >> .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | >> AV_CODEC_CAP_OTHER_THREADS | >> AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE | >> + AV_CODEC_CAP_ENCODER_FLUSH | >> AV_CODEC_CAP_ENCODER_RECON_FRAME, >> .p.priv_class = &x264_class, >> .p.wrapper_name = "libx264", >> .priv_data_size = sizeof(X264Context), >> .init = X264_init, >> FF_CODEC_ENCODE_CB(X264_frame), >> + .flush = X264_flush, >> .close = X264_close, >> .defaults = x264_defaults, >> #if X264_BUILD < 153 > > Wasn't AV_CODEC_CAP_ENCODER_FLUSH supposed to be only implemented for > hardware encoders where closing and reopening an encoder is costly? > > - Andreas It was introduced thinking on those for the reason you mentioned, but there's nothing limiting its usage for other codecs.
On Mon, Mar 27, 2023 at 05:09:55PM -0300, James Almer wrote: > Signed-off-by: James Almer <jamrial@gmail.com> > --- > libavcodec/libx264.c | 24 ++++++++++++++++++++++-- > 1 file changed, 22 insertions(+), 2 deletions(-) breaks: ./ffmpeg -i mm-short.mpg -vcodec libx264 -x264-params level=30:bframes=0:weightp=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:subq=6:8x8dct=0:trellis=0 -vframes 15 -an -bitexact -y x264p1.nut [vost#0:0/libx264 @ 0x55c290b11680] video encoding failed thx [...]
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 92828fabc3..72c3b6cedc 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -178,8 +178,8 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, memcpy(p, x4->sei, x4->sei_size); p += x4->sei_size; size -= x4->sei_size; - x4->sei_size = 0; - av_freep(&x4->sei); + /* Keep the value around in case of flush */ + x4->sei_size = -x4->sei_size; } /* x264 guarantees the payloads of the NALs @@ -648,6 +648,24 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } +static void X264_flush(AVCodecContext *avctx) +{ + X264Context *x4 = avctx->priv_data; + x264_nal_t *nal; + int nnal, ret; + x264_picture_t pic_out = {0}; + + do { + ret = x264_encoder_encode(x4->enc, &nal, &nnal, NULL, &pic_out); + } while (ret > 0 && x264_encoder_delayed_frames(x4->enc)); + + for (int i = 0; i < x4->nb_reordered_opaque; i++) + opaque_uninit(&x4->reordered_opaque[i]); + + if (x4->sei_size < 0) + x4->sei_size = -x4->sei_size; +} + static av_cold int X264_close(AVCodecContext *avctx) { X264Context *x4 = avctx->priv_data; @@ -1335,12 +1353,14 @@ FFCodec ff_libx264_encoder = { .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE | + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_ENCODER_RECON_FRAME, .p.priv_class = &x264_class, .p.wrapper_name = "libx264", .priv_data_size = sizeof(X264Context), .init = X264_init, FF_CODEC_ENCODE_CB(X264_frame), + .flush = X264_flush, .close = X264_close, .defaults = x264_defaults, #if X264_BUILD < 153
Signed-off-by: James Almer <jamrial@gmail.com> --- libavcodec/libx264.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-)