The branch, master has been updated
via df1fd43db4e20145f6c60b03a5bdeb02b3e8235a (commit)
from dd80ecb666f03d07cc8bca115bd5074cd63f59ed (commit)
- Log -----------------------------------------------------------------
commit df1fd43db4e20145f6c60b03a5bdeb02b3e8235a
Author: Michael Yang <[email protected]>
AuthorDate: Wed Oct 15 17:43:00 2025 +1100
Commit: Lynne <[email protected]>
CommitDate: Thu Nov 6 22:06:42 2025 +0000
libavcodec/vulkan_encode_av1: fix non-monotonic DTS
Combine P-frame with following B-frame into a single packet with the
latter's order. Emit a tail packet with a show_existing_frame header
to show it at the correct PTS.
diff --git a/libavcodec/vulkan_encode.c b/libavcodec/vulkan_encode.c
index e5c0496f1c..7b534ffa30 100644
--- a/libavcodec/vulkan_encode.c
+++ b/libavcodec/vulkan_encode.c
@@ -464,6 +464,9 @@ static int vulkan_encode_output(AVCodecContext *avctx,
VkResult ret;
FFVulkanEncodePicture *vp = base_pic->priv;
FFVulkanEncodeContext *ctx = avctx->priv_data;
+ FFHWBaseEncodeContext *base_ctx = &ctx->base;
+ AVPacket *pkt_ptr = pkt;
+
FFVkBuffer *sd_buf = (FFVkBuffer *)vp->pkt_buf->data;
uint32_t *query_data;
@@ -513,20 +516,56 @@ static int vulkan_encode_output(AVCodecContext *avctx,
vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &invalidate_buf);
}
- pkt->data = sd_buf->mapped_mem;
- pkt->size = vp->slices_offset + /* base offset */
- query_data[0] /* secondary offset */ +
- query_data[1] /* size */;
+ if (vp->non_independent_frame) {
+ av_assert0(!ctx->prev_buf_ref);
+ size_t prev_buf_size = vp->slices_offset + query_data[0] +
query_data[1];
+ ctx->prev_buf_ref = vp->pkt_buf;
+ ctx->prev_buf_size = prev_buf_size;
+ vp->pkt_buf = NULL;
+
+ if (vp->tail_size) {
+ if (base_ctx->tail_pkt->size)
+ return AVERROR_BUG;
+
+ ret = ff_get_encode_buffer(avctx, base_ctx->tail_pkt,
vp->tail_size, 0);
+ if (ret < 0)
+ return ret;
+
+ memcpy(base_ctx->tail_pkt->data, vp->tail_data, vp->tail_size);
+ pkt_ptr = base_ctx->tail_pkt;
+ }
+ } else {
+ if (ctx->prev_buf_ref) {
+ FFVkBuffer *prev_sd_buf = (FFVkBuffer *)ctx->prev_buf_ref->data;
+ size_t prev_size = ctx->prev_buf_size;
+ size_t size = (vp->slices_offset + query_data[0] + query_data[1]);
+
+ ret = ff_get_encode_buffer(avctx, pkt, prev_size + size, 0);
+ if (ret < 0)
+ return ret;
+
+ memcpy(pkt->data, prev_sd_buf->mapped_mem, prev_size);
+ memcpy(pkt->data + prev_size, sd_buf->mapped_mem, size);
- /* Move reference */
- pkt->buf = vp->pkt_buf;
- vp->pkt_buf = NULL;
+ av_buffer_unref(&ctx->prev_buf_ref);
+ av_buffer_unref(&vp->pkt_buf);
+ } else {
+ pkt->data = sd_buf->mapped_mem;
+ pkt->size = vp->slices_offset + /* base offset */
+ query_data[0] /* secondary offset */ +
+ query_data[1] /* size */;
+
+ /* Move reference */
+ pkt->buf = vp->pkt_buf;
+ vp->pkt_buf = NULL;
+ }
+ }
av_log(avctx, AV_LOG_DEBUG, "Frame %"PRId64"/%"PRId64 " encoded\n",
base_pic->display_order, base_pic->encode_order);
return ff_hw_base_encode_set_output_property(&ctx->base, avctx,
- base_pic, pkt,
+ base_pic, pkt_ptr,
ctx->codec->flags &
VK_ENC_FLAG_NO_DELAY);
}
diff --git a/libavcodec/vulkan_encode.h b/libavcodec/vulkan_encode.h
index 3df06e11d0..cf5f255628 100644
--- a/libavcodec/vulkan_encode.h
+++ b/libavcodec/vulkan_encode.h
@@ -57,6 +57,10 @@ typedef struct FFVulkanEncodePicture {
FFVkExecContext *exec;
AVBufferRef *pkt_buf;
int slices_offset;
+
+ int non_independent_frame;
+ char tail_data[16];
+ size_t tail_size;
} FFVulkanEncodePicture;
/**
@@ -192,6 +196,9 @@ typedef struct FFVulkanEncodeContext {
FFVkExecPool enc_pool;
FFHWBaseEncodePicture *slots[32];
+
+ AVBufferRef *prev_buf_ref;
+ size_t prev_buf_size;
} FFVulkanEncodeContext;
#define VULKAN_ENCODE_COMMON_OPTIONS \
diff --git a/libavcodec/vulkan_encode_av1.c b/libavcodec/vulkan_encode_av1.c
index 1f26b37316..42ba30b302 100644
--- a/libavcodec/vulkan_encode_av1.c
+++ b/libavcodec/vulkan_encode_av1.c
@@ -80,6 +80,8 @@ typedef struct VulkanEncodeAV1Context {
AV1RawOBU seq_hdr_obu;
AV1RawOBU meta_cll_obu;
AV1RawOBU meta_mastering_obu;
+ AV1RawOBU hidden_obu;
+ AV1RawOBU tail_obu;
VkVideoEncodeAV1ProfileInfoKHR profile;
@@ -172,7 +174,6 @@ static void set_name_slot(int slot, int *slot_indices,
uint32_t allowed_idx, int
av_assert0(0);
}
-
static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
VkVideoEncodeInfoKHR *encode_info)
{
@@ -542,6 +543,45 @@ static int init_pic_params(AVCodecContext *avctx,
FFHWBaseEncodePicture *pic,
}
}
+ FFVulkanEncodePicture *vp = pic->priv;
+ vp->tail_size = 0;
+ vp->non_independent_frame = pic->encode_order < pic->display_order;
+ if (vp->non_independent_frame) {
+ AV1RawOBU *obu = &enc->hidden_obu;
+ AV1RawFrameHeader *fh = &obu->obu.frame_header;
+
+ /** hidden frame header */
+ memset(obu, 0, sizeof(*obu));
+ obu->header.obu_type = AV1_OBU_FRAME_HEADER;
+ obu->header.obu_has_size_field = 1;
+
+ fh->frame_type = AV1_FRAME_INTER;
+ fh->refresh_frame_flags = 1 << ap->slot;
+ fh->frame_width_minus_1 = base_ctx->surface_width - 1;
+ fh->frame_height_minus_1 = base_ctx->surface_height - 1;
+ fh->render_width_minus_1 = fh->frame_width_minus_1;
+ fh->render_height_minus_1 = fh->frame_height_minus_1;
+
+ memcpy(fh->loop_filter_ref_deltas, default_loop_filter_ref_deltas,
+ AV1_TOTAL_REFS_PER_FRAME * sizeof(int8_t));
+
+ obu = &enc->tail_obu;
+ fh = &obu->obu.frame_header;
+
+ /** tail frame header */
+ memset(obu, 0, sizeof(*obu));
+ obu->header.obu_type = AV1_OBU_FRAME_HEADER;
+ obu->header.obu_has_size_field = 1;
+
+ fh->show_existing_frame = 1;
+ fh->frame_to_show_map_idx = ap->slot != 0;
+ fh->frame_type = AV1_FRAME_INTER;
+ fh->frame_width_minus_1 = base_ctx->surface_width - 1;
+ fh->frame_height_minus_1 = base_ctx->surface_height - 1;
+ fh->render_width_minus_1 = fh->frame_width_minus_1;
+ fh->render_height_minus_1 = fh->frame_height_minus_1;
+ }
+
return 0;
}
@@ -1079,8 +1119,31 @@ static int write_extra_headers(AVCodecContext *avctx,
int err;
VulkanEncodeAV1Context *enc = avctx->priv_data;
VulkanEncodeAV1Picture *ap = base_pic->codec_priv;
+ FFVulkanEncodePicture *vp = base_pic->priv;
CodedBitstreamFragment *obu = &enc->current_access_unit;
+ if (vp->non_independent_frame) {
+ err = vulkan_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER,
&enc->hidden_obu);
+ if (err < 0)
+ goto fail;
+
+ // Only for tracking ref frame in context, not to be output
+ err = ff_cbs_write_fragment_data(enc->cbs, obu);
+ if (err < 0)
+ goto fail;
+
+ ff_cbs_fragment_reset(obu);
+ ((CodedBitstreamAV1Context *)enc->cbs->priv_data)->seen_frame_header =
0;
+
+ err = vulkan_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER,
&enc->tail_obu);
+ if (err < 0)
+ goto fail;
+
+ err = vulkan_encode_av1_write_obu(avctx, vp->tail_data,
&vp->tail_size, obu);
+ if (err < 0)
+ goto fail;
+ }
+
if (ap->units_needed & UNIT_MASTERING_DISPLAY) {
err = vulkan_encode_av1_add_obu(avctx, obu,
AV1_OBU_METADATA,
-----------------------------------------------------------------------
Summary of changes:
libavcodec/vulkan_encode.c | 55 +++++++++++++++++++++++++++++------
libavcodec/vulkan_encode.h | 7 +++++
libavcodec/vulkan_encode_av1.c | 65 +++++++++++++++++++++++++++++++++++++++++-
3 files changed, 118 insertions(+), 9 deletions(-)
hooks/post-receive
--
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]