summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2023-01-31 11:07:50 +0100
committerAnton Khirnov <anton@khirnov.net>2023-02-04 13:14:20 +0100
commitd02340b9e3e72f401cddbeb3bcc3cb584902b886 (patch)
tree8110386a956be87c091e31a6e23bf773c2b3e5ac /libavcodec
parent82da22066c0818b606812d479674929a229386e2 (diff)
lavc/decode: allow using AV_CODEC_FLAG_COPY_OPAQUE for decoding
Use it to propagate AVPacket.opaque[_ref] to corresponding AVFrame fields. This is a more convenient alternative to reordered_opaque.
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/avcodec.h9
-rw-r--r--libavcodec/decode.c12
-rw-r--r--libavcodec/decode.h3
-rw-r--r--libavcodec/libdav1d.c31
-rw-r--r--libavcodec/version.h2
5 files changed, 45 insertions, 12 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 90b437ccbe..eba9ea73d7 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -242,9 +242,15 @@ typedef struct RcOverride{
*/
#define AV_CODEC_FLAG_RECON_FRAME (1 << 6)
/**
+ * @par decoding
+ * Request the decoder to propagate each packets AVPacket.opaque and
+ * AVPacket.opaque_ref to its corresponding output AVFrame.
+ *
+ * @par encoding:
* Request the encoder to propagate each frame's AVFrame.opaque and
* AVFrame.opaque_ref values to its corresponding output AVPacket.
*
+ * @par
* May only be set on encoders that have the
* @ref AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability flag.
*
@@ -265,6 +271,9 @@ typedef struct RcOverride{
* .
* When an output packet contains multiple frames, the opaque values will be
* taken from the first of those.
+ *
+ * @note
+ * The converse holds for decoders, with frames and packets switched.
*/
#define AV_CODEC_FLAG_COPY_OPAQUE (1 << 7)
/**
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 0abc88737b..17b398e933 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -1291,7 +1291,8 @@ static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame)
return av_packet_unpack_dictionary(side_metadata, size, frame_md);
}
-int ff_decode_frame_props_from_pkt(AVFrame *frame, const AVPacket *pkt)
+int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx,
+ AVFrame *frame, const AVPacket *pkt)
{
static const struct {
enum AVPacketSideDataType packet;
@@ -1336,6 +1337,13 @@ int ff_decode_frame_props_from_pkt(AVFrame *frame, const AVPacket *pkt)
frame->flags = (frame->flags & ~AV_FRAME_FLAG_DISCARD);
}
+ if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+ int ret = av_buffer_replace(&frame->opaque_ref, pkt->opaque_ref);
+ if (ret < 0)
+ return ret;
+ frame->opaque = pkt->opaque;
+ }
+
return 0;
}
@@ -1344,7 +1352,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
const AVPacket *pkt = avctx->internal->last_pkt_props;
if (!(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) {
- int ret = ff_decode_frame_props_from_pkt(frame, pkt);
+ int ret = ff_decode_frame_props_from_pkt(avctx, frame, pkt);
if (ret < 0)
return ret;
frame->pkt_size = (int)(intptr_t)pkt->opaque;
diff --git a/libavcodec/decode.h b/libavcodec/decode.h
index 906122b4a7..8430ffbd66 100644
--- a/libavcodec/decode.h
+++ b/libavcodec/decode.h
@@ -72,7 +72,8 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt);
/**
* Set various frame properties from the provided packet.
*/
-int ff_decode_frame_props_from_pkt(AVFrame *frame, const AVPacket *pkt);
+int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx,
+ AVFrame *frame, const AVPacket *pkt);
/**
* Set various frame properties from the codec context / packet data.
diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
index b43af03732..f7d75f9439 100644
--- a/libavcodec/libdav1d.c
+++ b/libavcodec/libdav1d.c
@@ -288,6 +288,11 @@ static void libdav1d_flush(AVCodecContext *c)
dav1d_flush(dav1d->c);
}
+typedef struct OpaqueData {
+ void *pkt_orig_opaque;
+ int64_t reordered_opaque;
+} OpaqueData;
+
static void libdav1d_data_free(const uint8_t *data, void *opaque) {
AVBufferRef *buf = opaque;
@@ -307,6 +312,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame)
Dav1dData *data = &dav1d->data;
Dav1dPicture pic = { 0 }, *p = &pic;
AVPacket *pkt;
+ OpaqueData *od = NULL;
#if FF_DAV1D_VERSION_AT_LEAST(5,1)
enum Dav1dEventFlags event_flags = 0;
#endif
@@ -333,17 +339,19 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame)
}
pkt->buf = NULL;
- pkt->opaque = NULL;
- if (c->reordered_opaque != AV_NOPTS_VALUE) {
- pkt->opaque = av_memdup(&c->reordered_opaque,
- sizeof(c->reordered_opaque));
- if (!pkt->opaque) {
+ if (c->reordered_opaque != AV_NOPTS_VALUE ||
+ (pkt->opaque && (c->flags & AV_CODEC_FLAG_COPY_OPAQUE))) {
+ od = av_mallocz(sizeof(*od));
+ if (!od) {
av_packet_free(&pkt);
dav1d_data_unref(data);
return AVERROR(ENOMEM);
}
+ od->pkt_orig_opaque = pkt->opaque;
+ od->reordered_opaque = c->reordered_opaque;
}
+ pkt->opaque = od;
res = dav1d_data_wrap_user_data(data, (const uint8_t *)pkt,
libdav1d_user_data_free, pkt);
@@ -423,13 +431,20 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame)
ff_set_sar(c, frame->sample_aspect_ratio);
pkt = (AVPacket *)p->m.user_data.data;
- if (pkt->opaque)
- memcpy(&frame->reordered_opaque, pkt->opaque, sizeof(frame->reordered_opaque));
+ od = pkt->opaque;
+ if (od && od->reordered_opaque != AV_NOPTS_VALUE)
+ frame->reordered_opaque = od->reordered_opaque;
else
frame->reordered_opaque = AV_NOPTS_VALUE;
+ // restore the original user opaque value for
+ // ff_decode_frame_props_from_pkt()
+ pkt->opaque = od ? od->pkt_orig_opaque : NULL;
+ av_freep(&od);
+
// match timestamps and packet size
- res = ff_decode_frame_props_from_pkt(frame, pkt);
+ res = ff_decode_frame_props_from_pkt(c, frame, pkt);
+ pkt->opaque = NULL;
if (res < 0)
goto fail;
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 310c80eeef..a80dc4776d 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
#include "version_major.h"
-#define LIBAVCODEC_VERSION_MINOR 62
+#define LIBAVCODEC_VERSION_MINOR 63
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \