diff options
author | Philip Langdale <philipl@overt.org> | 2022-11-29 11:15:16 -0800 |
---|---|---|
committer | Philip Langdale <github.philipl@overt.org> | 2022-12-03 14:44:18 -0800 |
commit | 4574dd5dc6ff75b1fc693afceec59fbcd51ccd4c (patch) | |
tree | 680ea541592dea8e356809e5dbdd5265781d72fe /video/decode | |
parent | 77e7f5de2c01361a88c501fcd78b51c2fe2d9df0 (diff) | |
download | mpv-4574dd5dc6ff75b1fc693afceec59fbcd51ccd4c.tar.bz2 mpv-4574dd5dc6ff75b1fc693afceec59fbcd51ccd4c.tar.xz |
ffmpeg: update to handle deprecation of `av_init_packet`
This has been a long standing annoyance - ffmpeg is removing
sizeof(AVPacket) from the API which means you cannot stack-allocate
AVPacket anymore. However, that is something we take advantage of
because we use short-lived AVPackets to bridge from native mpv packets
in our main decoding paths.
We don't think that switching these to `av_packet_alloc` is desirable,
given the cost of heap allocation, so this change takes a different
approach - allocating a single packet in the relevant context and
reusing it over and over.
That's fairly straight-forward, with the main caveat being that
re-initialising the packet is unintuitive. There is no function that
does exactly what we need (what `av_init_packet` did). The closest is
`av_packet_unref`, which additionally frees buffers and side-data.
However, we don't copy those things - we just assign them in from our
own packet, so we have to explicitly clear the pointers before calling
`av_packet_unref`. But at least we can make a wrapper function for
that.
The weirdest part of the change is the handling of the vtt subtitle
conversion. This requires two packets, so I had to pre-allocate two in
the context struct. That sounds excessive, but if allocating the
primary packet is too expensive, then allocating the secondary one for
vtt subtitles must also be too expensive.
This change is not conditional as heap allocated AVPackets were
available for years and years before the deprecation.
Diffstat (limited to 'video/decode')
-rw-r--r-- | video/decode/vd_lavc.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index c65d9d708a..5e8bf40a66 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -173,6 +173,7 @@ typedef struct lavc_ctx { struct mp_codec_params *codec; AVCodecContext *avctx; AVFrame *pic; + AVPacket *avpkt; bool use_hwdec; struct hwdec_info hwdec; // valid only if use_hwdec==true AVRational codec_timebase; @@ -651,6 +652,10 @@ static void init_avctx(struct mp_filter *vd) if (!ctx->pic) goto error; + ctx->avpkt = av_packet_alloc(); + if (!ctx->avpkt) + goto error; + if (ctx->use_hwdec) { avctx->opaque = vd; avctx->thread_count = 1; @@ -752,9 +757,8 @@ static void init_avctx(struct mp_filter *vd) // x264 build number (encoded in a SEI element), needed to enable a // workaround for broken 4:4:4 streams produced by older x264 versions. if (lavc_codec->id == AV_CODEC_ID_H264 && c->first_packet) { - AVPacket avpkt; - mp_set_av_packet(&avpkt, c->first_packet, &ctx->codec_timebase); - avcodec_send_packet(avctx, &avpkt); + mp_set_av_packet(ctx->avpkt, c->first_packet, &ctx->codec_timebase); + avcodec_send_packet(avctx, ctx->avpkt); avcodec_receive_frame(avctx, ctx->pic); av_frame_unref(ctx->pic); avcodec_flush_buffers(ctx->avctx); @@ -802,6 +806,7 @@ static void uninit_avctx(struct mp_filter *vd) flush_all(vd); av_frame_free(&ctx->pic); + mp_free_av_packet(&ctx->avpkt); av_buffer_unref(&ctx->cached_hw_frames_ctx); avcodec_free_context(&ctx->avctx); @@ -1067,10 +1072,9 @@ static int send_packet(struct mp_filter *vd, struct demux_packet *pkt) if (avctx->skip_frame == AVDISCARD_ALL) return 0; - AVPacket avpkt; - mp_set_av_packet(&avpkt, pkt, &ctx->codec_timebase); + mp_set_av_packet(ctx->avpkt, pkt, &ctx->codec_timebase); - int ret = avcodec_send_packet(avctx, pkt ? &avpkt : NULL); + int ret = avcodec_send_packet(avctx, pkt ? ctx->avpkt : NULL); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return ret; |