[FFmpeg-devel] [PATCH 6/7 v5] avcodec/decode: add AVFrameSideData helper wrappers that don't depend on frames
James Almer
jamrial at gmail.com
Thu Mar 28 18:52:49 EET 2024
They will be useful to fill arrays stored in other structs.
Signed-off-by: James Almer <jamrial at gmail.com>
---
libavcodec/decode.c | 106 ++++++++++++++++++++++++++++++++++++--------
libavcodec/decode.h | 24 ++++++++++
2 files changed, 112 insertions(+), 18 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 34bcb7cc64..1f6c2a8dde 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -1799,16 +1799,16 @@ int ff_decode_preinit(AVCodecContext *avctx)
* @retval 0 side data of this type can be added to frame
* @retval 1 side data of this type should not be added to frame
*/
-static int side_data_pref(const AVCodecContext *avctx, AVFrame *frame,
- enum AVFrameSideDataType type)
+static int side_data_pref(const AVCodecContext *avctx, AVFrameSideData ***sd,
+ int *nb_sd, enum AVFrameSideDataType type)
{
DecodeContext *dc = decode_ctx(avctx->internal);
// Note: could be skipped for `type` without corresponding packet sd
- if (av_frame_get_side_data(frame, type)) {
+ if (av_frame_side_data_get(*sd, *nb_sd, type)) {
if (dc->side_data_pref_mask & (1ULL << type))
return 1;
- av_frame_remove_side_data(frame, type);
+ av_frame_side_data_remove(sd, nb_sd, type);
}
return 0;
@@ -1821,7 +1821,7 @@ int ff_frame_new_side_data(const AVCodecContext *avctx, AVFrame *frame,
{
AVFrameSideData *sd;
- if (side_data_pref(avctx, frame, type)) {
+ if (side_data_pref(avctx, &frame->side_data, &frame->nb_side_data, type)) {
if (psd)
*psd = NULL;
return 0;
@@ -1834,34 +1834,71 @@ int ff_frame_new_side_data(const AVCodecContext *avctx, AVFrame *frame,
return sd ? 0 : AVERROR(ENOMEM);
}
-int ff_frame_new_side_data_from_buf(const AVCodecContext *avctx,
- AVFrame *frame, enum AVFrameSideDataType type,
- AVBufferRef **buf, AVFrameSideData **psd)
+int ff_frame_new_side_data_from_buf_ext(const AVCodecContext *avctx,
+ AVFrameSideData ***sd, int *nb_sd,
+ enum AVFrameSideDataType type,
+ AVBufferRef **buf)
{
- AVFrameSideData *sd = NULL;
int ret = 0;
- if (side_data_pref(avctx, frame, type))
+ if (side_data_pref(avctx, sd, nb_sd, type))
goto finish;
- sd = av_frame_new_side_data_from_buf(frame, type, *buf);
- if (sd)
- *buf = NULL;
- else
+ if (!av_frame_side_data_add(sd, nb_sd, type, buf, 0))
ret = AVERROR(ENOMEM);
finish:
av_buffer_unref(buf);
- if (psd)
- *psd = sd;
return ret;
}
+int ff_frame_new_side_data_from_buf(const AVCodecContext *avctx,
+ AVFrame *frame, enum AVFrameSideDataType type,
+ AVBufferRef **buf, AVFrameSideData **psd)
+{
+ return ff_frame_new_side_data_from_buf_ext(avctx,
+ &frame->side_data, &frame->nb_side_data,
+ type, buf);
+}
+
+int ff_decode_mastering_display_new_ext(const AVCodecContext *avctx,
+ AVFrameSideData ***sd, int *nb_sd,
+ struct AVMasteringDisplayMetadata **mdm)
+{
+ AVBufferRef *buf;
+ size_t size;
+
+ if (side_data_pref(avctx, sd, nb_sd, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA)) {
+ *mdm = NULL;
+ return 0;
+ }
+
+ *mdm = av_mastering_display_metadata_alloc_size(&size);
+ if (!*mdm)
+ return AVERROR(ENOMEM);
+
+ buf = av_buffer_create((uint8_t *)*mdm, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(mdm);
+ return AVERROR(ENOMEM);
+ }
+
+ if (!av_frame_side_data_add(sd, nb_sd, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA,
+ &buf, 0)) {
+ *mdm = NULL;
+ av_buffer_unref(&buf);
+ return AVERROR(ENOMEM);
+ }
+
+ return 0;
+}
+
int ff_decode_mastering_display_new(const AVCodecContext *avctx, AVFrame *frame,
AVMasteringDisplayMetadata **mdm)
{
- if (side_data_pref(avctx, frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA)) {
+ if (side_data_pref(avctx, &frame->side_data, &frame->nb_side_data,
+ AV_FRAME_DATA_MASTERING_DISPLAY_METADATA)) {
*mdm = NULL;
return 0;
}
@@ -1870,10 +1907,43 @@ int ff_decode_mastering_display_new(const AVCodecContext *avctx, AVFrame *frame,
return *mdm ? 0 : AVERROR(ENOMEM);
}
+int ff_decode_content_light_new_ext(const AVCodecContext *avctx,
+ AVFrameSideData ***sd, int *nb_sd,
+ AVContentLightMetadata **clm)
+{
+ AVBufferRef *buf;
+ size_t size;
+
+ if (side_data_pref(avctx, sd, nb_sd, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL)) {
+ *clm = NULL;
+ return 0;
+ }
+
+ *clm = av_content_light_metadata_alloc(&size);
+ if (!*clm)
+ return AVERROR(ENOMEM);
+
+ buf = av_buffer_create((uint8_t *)*clm, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(clm);
+ return AVERROR(ENOMEM);
+ }
+
+ if (!av_frame_side_data_add(sd, nb_sd, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
+ &buf, 0)) {
+ *clm = NULL;
+ av_buffer_unref(&buf);
+ return AVERROR(ENOMEM);
+ }
+
+ return 0;
+}
+
int ff_decode_content_light_new(const AVCodecContext *avctx, AVFrame *frame,
AVContentLightMetadata **clm)
{
- if (side_data_pref(avctx, frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL)) {
+ if (side_data_pref(avctx, &frame->side_data, &frame->nb_side_data,
+ AV_FRAME_DATA_CONTENT_LIGHT_LEVEL)) {
*clm = NULL;
return 0;
}
diff --git a/libavcodec/decode.h b/libavcodec/decode.h
index 4ffbd9db8e..72a775ff9d 100644
--- a/libavcodec/decode.h
+++ b/libavcodec/decode.h
@@ -175,6 +175,15 @@ int ff_frame_new_side_data_from_buf(const AVCodecContext *avctx,
AVFrame *frame, enum AVFrameSideDataType type,
AVBufferRef **buf, AVFrameSideData **sd);
+/**
+ * Same as `ff_frame_new_side_data_from_buf`, but taking a AVFrameSideData
+ * array directly instead of an AVFrame.
+ */
+int ff_frame_new_side_data_from_buf_ext(const AVCodecContext *avctx,
+ AVFrameSideData ***sd, int *nb_sd,
+ enum AVFrameSideDataType type,
+ AVBufferRef **buf);
+
struct AVMasteringDisplayMetadata;
struct AVContentLightMetadata;
@@ -187,6 +196,14 @@ struct AVContentLightMetadata;
int ff_decode_mastering_display_new(const AVCodecContext *avctx, AVFrame *frame,
struct AVMasteringDisplayMetadata **mdm);
+/**
+ * Same as `ff_decode_mastering_display_new`, but taking a AVFrameSideData
+ * array directly instead of an AVFrame.
+ */
+int ff_decode_mastering_display_new_ext(const AVCodecContext *avctx,
+ AVFrameSideData ***sd, int *nb_sd,
+ struct AVMasteringDisplayMetadata **mdm);
+
/**
* Wrapper around av_content_light_metadata_create_side_data(), which
* rejects side data overridden by the demuxer. Returns 0 on success, and a
@@ -196,4 +213,11 @@ int ff_decode_mastering_display_new(const AVCodecContext *avctx, AVFrame *frame,
int ff_decode_content_light_new(const AVCodecContext *avctx, AVFrame *frame,
struct AVContentLightMetadata **clm);
+/**
+ * Same as `ff_decode_content_light_new`, but taking a AVFrameSideData
+ * array directly instead of an AVFrame.
+ */
+int ff_decode_content_light_new_ext(const AVCodecContext *avctx,
+ AVFrameSideData ***sd, int *nb_sd,
+ struct AVContentLightMetadata **clm);
#endif /* AVCODEC_DECODE_H */
--
2.44.0
More information about the ffmpeg-devel
mailing list