[vlc-commits] [Git][videolan/vlc][master] 6 commits: frame: use vlc_frame_CopyProperties instead of BlockMetaCopy
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Fri Dec 24 08:17:45 UTC 2021
Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC
Commits:
5a1e47b0 by Thomas Guillem at 2021-12-24T08:00:32+01:00
frame: use vlc_frame_CopyProperties instead of BlockMetaCopy
- - - - -
20b6faa8 by Thomas Guillem at 2021-12-24T08:00:32+01:00
frame: move vlc_frame_CopyProperties to frame.c
Will be needed by the next commit.
No functional changes.
Refs #18762
- - - - -
9287173a by Thomas Guillem at 2021-12-24T08:03:44+01:00
core: add the vlc_ancillary API
Ancillaries can be attached to any vlc_frame_t or picture_t (in next
commits).
Ancillaries can be created from:
- packetized demuxer modules
- packetizer modules
- decoder modules
It can't be created from a non packetized demuxer module since the
attachement to the vlc_frame will be lost by the packetizer module that
will be automatically inserted.
Ancillaries are automatically forwarded from a vlc_frame_t to an other
vlc_frame_t and from a picture_t to an other picture_t. This allow to keep
ancillaries untouched when audio filters or video filters are used (these
filters don't have to know about the ancillary).
Ancillary readers can be either:
- A decoder module
- An audio output
- A video output
- Any filters
Refs #18762
- - - - -
d453e8f4 by Thomas Guillem at 2021-12-24T08:03:44+01:00
frame: add the ancillary API
Refs #18762
- - - - -
e0b6a09a by Thomas Guillem at 2021-12-24T08:03:44+01:00
picture: use the ancillary API
Fixes #18762
- - - - -
d0547192 by Thomas Guillem at 2021-12-24T08:03:44+01:00
test: test the ancillary API
- - - - -
12 changed files:
- + include/vlc_ancillary.h
- include/vlc_frame.h
- include/vlc_picture.h
- src/Makefile.am
- src/libvlccore.sym
- + src/misc/ancillary.c
- + src/misc/ancillary.h
- src/misc/frame.c
- src/misc/picture.c
- src/misc/picture.h
- test/Makefile.am
- + test/src/misc/ancillary.c
Changes:
=====================================
include/vlc_ancillary.h
=====================================
@@ -0,0 +1,121 @@
+/*****************************************************************************
+ * vlc_ancillary.h: ancillary management functions
+ *****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_ANCILLARY_H
+#define VLC_ANCILLARY_H 1
+
+/**
+ * \defgroup ancillary Ancillary
+ * \ingroup input
+ *
+ * Ancillary that can be attached to any vlc_frame_t or picture_t.
+ *
+ * Ancillaries can be created from:
+ * - packetized demuxer modules,
+ * - packetizer modules,
+ * - decoder modules.
+ *
+ * @warning Ancillaries should not be attached from a non packetized demuxer
+ * module since the attachment to the vlc_frame will be lost by the packetizer
+ * module that will be automatically inserted.
+ *
+ * Ancillaries are automatically forwarded from a vlc_frame_t to an other
+ * vlc_frame_t and from a picture_t to an other picture_t. This allow to keep
+ * ancillaries untouched when audio filters or video filters are used (these
+ * filters don't have to know about the ancillary).
+ *
+ * Ancillary readers can be either:
+ * - A decoder module,
+ * - An audio output,
+ * - A video output,
+ * - A video or audio filter.
+ *
+ * @{
+ * \file
+ * Ancillary definition and functions
+ */
+
+/**
+ * Ancillary opaque struct, refcounted struct that hold user data with a free
+ * callback.
+ */
+struct vlc_ancillary;
+
+/**
+ * ID of an ancillary. Each ancillary user can create its own unique ID via
+ * VLC_ANCILLARY_ID.
+ */
+typedef uint32_t vlc_ancillary_id;
+#define VLC_ANCILLARY_ID(a,b,c,d) VLC_FOURCC(a,b,c,d)
+
+/**
+ * Callback to free an ancillary data
+ */
+typedef void (*vlc_ancillary_free_cb)(void *data);
+
+/**
+ * Create an ancillary
+ *
+ * @param data an opaque ancillary, can't be NULL
+ * @param id id of ancillary
+ * @param free_cb callback to release the data, can be NULL
+ * @return a valid vlc_ancillary pointer or NULL in case of allocation error
+ */
+VLC_API struct vlc_ancillary *
+vlc_ancillary_CreateWithFreeCb(void *data, vlc_ancillary_id id,
+ vlc_ancillary_free_cb free_cb);
+
+/**
+ * Helper to create an ancillary holding an allocated data
+ */
+static inline struct vlc_ancillary *
+vlc_ancillary_Create(void *data, vlc_ancillary_id id)
+{
+ return vlc_ancillary_CreateWithFreeCb(data, id, free);
+}
+
+/**
+ * Release an ancillary
+ *
+ * If the refcount reachs 0, the free_cb provided by
+ * vlc_ancillary_CreateWithFreeCb() is called.
+ *
+ * @param ancillary ancillary to release
+ */
+VLC_API void
+vlc_ancillary_Release(struct vlc_ancillary *ancillary);
+
+/**
+ * Hold an ancillary
+ *
+ * @param ancillary ancillary to hold
+ * @return the same ancillary
+ */
+VLC_API struct vlc_ancillary *
+vlc_ancillary_Hold(struct vlc_ancillary *ancillary);
+
+VLC_API void *
+vlc_ancillary_GetData(const struct vlc_ancillary *ancillary);
+
+/** @} */
+
+/** @} */
+
+#endif /* VLC_ANCILLARY_H */
=====================================
include/vlc_frame.h
=====================================
@@ -23,6 +23,9 @@
#ifndef VLC_FRAME_H
#define VLC_FRAME_H 1
+struct vlc_ancillary;
+typedef uint32_t vlc_ancillary_id;
+
/**
* \defgroup frame Frames
* \ingroup input
@@ -131,6 +134,10 @@ struct vlc_frame_t
vlc_tick_t i_dts;
vlc_tick_t i_length;
+ /** Private ancillary struct. Don't use it directly, but use it via
+ * vlc_frame_AttachAncillary() and vlc_frame_GetAncillary(). */
+ struct vlc_ancillary **priv_ancillaries;
+
const struct vlc_frame_callbacks *cbs;
};
@@ -204,14 +211,44 @@ VLC_API vlc_frame_t *vlc_frame_Realloc(vlc_frame_t *, ssize_t pre, size_t body)
*/
VLC_API void vlc_frame_Release(vlc_frame_t *frame);
-static inline void vlc_frame_CopyProperties( vlc_frame_t *dst, const vlc_frame_t *src )
-{
- dst->i_flags = src->i_flags;
- dst->i_nb_samples = src->i_nb_samples;
- dst->i_dts = src->i_dts;
- dst->i_pts = src->i_pts;
- dst->i_length = src->i_length;
-}
+/**
+ * Attach an ancillary to the frame
+ *
+ * @warning the ancillary will be released only if the frame is allocated from
+ * a vlc_frame Alloc function (vlc_frame_Alloc(), vlc_frame_mmap_Alloc()...).
+ *
+ * @note Several ancillaries can be attached to a frame, but if two ancillaries
+ * are identified by the same ID, only the last one take precedence.
+ *
+ * @param frame the frame to attach an ancillary
+ * @param ancillary ancillary that will be held by the frame, can't be NULL
+ * @return VLC_SUCCESS in case of success, VLC_ENOMEM in case of alloc error
+ */
+VLC_API int
+vlc_frame_AttachAncillary(vlc_frame_t *frame, struct vlc_ancillary *ancillary);
+
+/**
+ * Return the ancillary identified by an ID
+ *
+ * @param id id of ancillary to request
+ * @return the ancillary or NULL if the ancillary for that particular id is
+ * not present
+ */
+VLC_API struct vlc_ancillary *
+vlc_frame_GetAncillary(vlc_frame_t *frame, vlc_ancillary_id id);
+
+/**
+ * Copy frame properties from src to dst
+ *
+ * Copy i_flags, i_nb_samples, i_dts, i_pts, and i_length.
+ *
+ * @note if src has an ancillary, the ancillary will be copied and refcounted
+ * to dst.
+ *
+ * @param dst the frame to copy properties into
+ * @param src the frame to copy properties from
+ */
+VLC_API void vlc_frame_CopyProperties( vlc_frame_t *dst, const vlc_frame_t *src );
/**
* Duplicates a frame.
=====================================
include/vlc_picture.h
=====================================
@@ -28,6 +28,9 @@
#include <assert.h>
#include <vlc_atomic.h>
+struct vlc_ancillary;
+typedef uint32_t vlc_ancillary_id;
+
/**
* \defgroup picture Generic picture API
* \ingroup output
@@ -411,6 +414,33 @@ VLC_API void picture_Copy( picture_t *p_dst, const picture_t *p_src );
*/
VLC_API picture_t *picture_Clone(picture_t *pic);
+/**
+ * Attach an ancillary to the picture
+ *
+ * @warning the ancillary will be released only if the picture is created from
+ * picture_New(), and picture_Clone().
+ *
+ * @note Several ancillaries can be attached to a picture, but if two
+ * ancillaries are identified by the same ID, only the last one take
+ * precedence.
+ *
+ * @param pic the picture to attach an ancillary
+ * @param ancillary ancillary that will be held by the frame, can't be NULL
+ * @return VLC_SUCCESS in case of success, VLC_ENOMEM in case of alloc error
+ */
+VLC_API int
+picture_AttachAncillary(picture_t *pic, struct vlc_ancillary *ancillary);
+
+/**
+ * Return the ancillary identified by an ID
+ *
+ * @param id id of ancillary to request
+ * @return the ancillary or NULL if the ancillary for that particular id is
+ * not present
+ */
+VLC_API struct vlc_ancillary *
+picture_GetAncillary(picture_t *pic, vlc_ancillary_id id);
+
/**
* This function will export a picture to an encoded bitstream.
*
=====================================
src/Makefile.am
=====================================
@@ -25,6 +25,7 @@ pluginsinclude_HEADERS = \
../include/vlc_access.h \
../include/vlc_actions.h \
../include/vlc_addons.h \
+ ../include/vlc_ancillary.h \
../include/vlc_aout.h \
../include/vlc_aout_volume.h \
../include/vlc_arrays.h \
@@ -359,6 +360,8 @@ libvlccore_la_SOURCES = \
text/iso_lang.c \
text/iso-639_def.h \
misc/actions.c \
+ misc/ancillary.h \
+ misc/ancillary.c \
misc/executor.c \
misc/md5.c \
misc/probe.c \
=====================================
src/libvlccore.sym
=====================================
@@ -29,6 +29,10 @@ aout_FiltersPlay
aout_FiltersAdjustResampling
aout_Hold
aout_Release
+vlc_ancillary_CreateWithFreeCb
+vlc_ancillary_Release
+vlc_ancillary_Hold
+vlc_ancillary_GetData
vlc_audio_meter_Init
vlc_audio_meter_Destroy
vlc_audio_meter_Reset
@@ -41,8 +45,11 @@ vlc_fifo_New
vlc_fifo_Release
vlc_fifo_Show
vlc_frame_Alloc
+vlc_frame_AttachAncillary
+vlc_frame_CopyProperties
vlc_frame_File
vlc_frame_FilePath
+vlc_frame_GetAncillary
vlc_frame_heap_Alloc
vlc_frame_Init
vlc_frame_mmap_Alloc
@@ -301,6 +308,7 @@ net_Read
net_SetCSCov
net_Write
NTPtime64
+picture_AttachAncillary
picture_BlendSubpicture
picture_Clone
picture_CopyPixels
@@ -314,6 +322,7 @@ picture_fifo_New
picture_fifo_IsEmpty
picture_fifo_Pop
picture_fifo_Push
+picture_GetAncillary
picture_New
picture_NewFromFormat
picture_NewFromResource
=====================================
src/misc/ancillary.c
=====================================
@@ -0,0 +1,201 @@
+/*****************************************************************************
+ * ancillary.c: ancillary management functions
+ *****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_atomic.h>
+
+#include "ancillary.h"
+
+struct vlc_ancillary
+{
+ vlc_atomic_rc_t rc;
+
+ vlc_ancillary_id id;
+ void *data;
+ vlc_ancillary_free_cb free_cb;
+};
+
+struct vlc_ancillary *
+vlc_ancillary_CreateWithFreeCb(void *data,
+ vlc_ancillary_id id,
+ vlc_ancillary_free_cb free_cb)
+{
+ struct vlc_ancillary *ancillary = malloc(sizeof(*ancillary));
+
+ if (ancillary == NULL)
+ return NULL;
+
+ vlc_atomic_rc_init(&ancillary->rc);
+ ancillary->id = id;
+ ancillary->data = data;
+ ancillary->free_cb = free_cb;
+
+ return ancillary;
+}
+
+void
+vlc_ancillary_Release(struct vlc_ancillary *ancillary)
+{
+ if (vlc_atomic_rc_dec(&ancillary->rc))
+ {
+ if (ancillary->free_cb != NULL)
+ ancillary->free_cb(ancillary->data);
+ free(ancillary);
+ }
+}
+
+struct vlc_ancillary *
+vlc_ancillary_Hold(struct vlc_ancillary *ancillary)
+{
+ vlc_atomic_rc_inc(&ancillary->rc);
+ return ancillary;
+}
+
+void *
+vlc_ancillary_GetData(const struct vlc_ancillary *ancillary)
+{
+ return ancillary->data;
+}
+
+void
+vlc_ancillary_array_Clear(struct vlc_ancillary ***array)
+{
+ if (*array != NULL)
+ {
+ for (struct vlc_ancillary **ancillary = *array;
+ *ancillary != NULL; ancillary++)
+ {
+ vlc_ancillary_Release(*ancillary);
+ }
+
+ free(*array);
+ *array = NULL;
+ }
+}
+
+static size_t
+vlc_ancillary_array_Count(struct vlc_ancillary **array)
+{
+ size_t count = 0;
+ for (struct vlc_ancillary **ancillary = array;
+ *ancillary != NULL; ancillary++)
+ {
+ count++;
+ }
+
+ return count;
+}
+
+int
+vlc_ancillary_array_Dup(struct vlc_ancillary ***dst_arrayp,
+ struct vlc_ancillary ** const*src_arrayp)
+{
+ if (unlikely(*dst_arrayp != NULL))
+ vlc_ancillary_array_Clear(dst_arrayp);
+
+ if (*src_arrayp == NULL)
+ return VLC_SUCCESS;
+
+ struct vlc_ancillary **src_array = *src_arrayp;
+ size_t count = vlc_ancillary_array_Count(src_array);
+
+ struct vlc_ancillary **dst_array =
+ vlc_alloc(count + 1, sizeof(struct vlc_ancillary *));
+ if (dst_array == NULL)
+ return VLC_ENOMEM;
+
+ for (size_t i = 0; i < count; ++i)
+ {
+ dst_array[i] = vlc_ancillary_Hold(src_array[i]);
+ assert(dst_array[i] != NULL);
+ }
+ dst_array[count] = NULL;
+ *dst_arrayp = dst_array;
+
+ return VLC_SUCCESS;
+}
+
+int
+vlc_ancillary_array_Insert(struct vlc_ancillary ***arrayp,
+ struct vlc_ancillary *ancillary)
+{
+ /* First case: the array is empty */
+ if (*arrayp == NULL)
+ {
+ struct vlc_ancillary **array = vlc_alloc(2, sizeof(struct vlc_ancillary *));
+ if (array == NULL)
+ return VLC_ENOMEM;
+
+ array[0] = vlc_ancillary_Hold(ancillary);
+ array[1] = NULL;
+
+ *arrayp = array;
+
+ return VLC_SUCCESS;
+ }
+
+ struct vlc_ancillary **array = *arrayp;
+ size_t count = vlc_ancillary_array_Count(array);
+
+ /* Second case: the array has already an ancillary of the same id (very
+ * unlikely) */
+ for (size_t i = 0; i < count; ++i)
+ {
+ if (array[i]->id == ancillary->id)
+ {
+ vlc_ancillary_Release(array[i]);
+ array[i] = vlc_ancillary_Hold(ancillary);
+ return VLC_SUCCESS;
+ }
+ }
+
+ /* Third case: realloc the array to add the new ancillary */
+ array = vlc_reallocarray(array, count + 2, sizeof(struct vlc_ancillary *));
+ if (array == NULL)
+ return VLC_ENOMEM;
+
+ array[count] = vlc_ancillary_Hold(ancillary);
+ array[count + 1] = NULL;
+
+ *arrayp = array;
+
+ return VLC_SUCCESS;
+}
+
+struct vlc_ancillary *
+vlc_ancillary_array_Get(struct vlc_ancillary ** const*arrayp,
+ vlc_ancillary_id id)
+{
+ if (*arrayp == NULL)
+ return NULL;
+
+ struct vlc_ancillary **array = *arrayp;
+ for (struct vlc_ancillary **ancillary = array;
+ *ancillary != NULL; ancillary++)
+ {
+ if ((*ancillary)->id == id)
+ return *ancillary;
+ }
+ return NULL;
+}
=====================================
src/misc/ancillary.h
=====================================
@@ -0,0 +1,55 @@
+/*****************************************************************************
+ * ancillary.h: helpers to manage ancillaries from a frame or a picture
+ *****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_ANCILLARY_INTERNAL_H
+#define VLC_ANCILLARY_INTERNAL_H 1
+
+#include <vlc_ancillary.h>
+
+/*
+ * A NULL terminated array of struct vlc_ancillary *. We don't use a
+ * vlc_vector here in orer to gain few bytes (2 * size_t) for each
+ * ancillary users (each vlc_frame_t/picture_t). Users will likely have one
+ * or zero ancillary so the optimisations of the vlc_vector are not
+ * important here.
+ */
+
+static inline void
+vlc_ancillary_array_Init(struct vlc_ancillary ***array)
+{
+ *array = NULL;
+}
+
+void
+vlc_ancillary_array_Clear(struct vlc_ancillary ***array);
+
+int
+vlc_ancillary_array_Dup(struct vlc_ancillary ***dst_array,
+ struct vlc_ancillary ** const*src_array);
+
+int
+vlc_ancillary_array_Insert(struct vlc_ancillary ***array,
+ struct vlc_ancillary *ancillary);
+
+struct vlc_ancillary *
+vlc_ancillary_array_Get(struct vlc_ancillary ** const*array,
+ vlc_ancillary_id id);
+
+#endif /* VLC_ANCILLARY_INTERNAL_H */
=====================================
src/misc/frame.c
=====================================
@@ -32,9 +32,12 @@
#include <fcntl.h>
#include <vlc_common.h>
+#include <vlc_atomic.h>
#include <vlc_frame.h>
#include <vlc_fs.h>
+#include "ancillary.h"
+
#ifndef NDEBUG
static void vlc_frame_Check (vlc_frame_t *frame)
{
@@ -57,6 +60,18 @@ static void vlc_frame_Check (vlc_frame_t *frame)
# define vlc_frame_Check(b) ((void)(b))
#endif
+void vlc_frame_CopyProperties(vlc_frame_t *restrict dst, const vlc_frame_t *src)
+{
+ vlc_ancillary_array_Dup(&dst->priv_ancillaries,
+ &src->priv_ancillaries);
+
+ dst->i_flags = src->i_flags;
+ dst->i_nb_samples = src->i_nb_samples;
+ dst->i_dts = src->i_dts;
+ dst->i_pts = src->i_pts;
+ dst->i_length = src->i_length;
+}
+
vlc_frame_t *vlc_frame_Init(vlc_frame_t *restrict f, const struct vlc_frame_callbacks *cbs,
void *buf, size_t size)
{
@@ -71,6 +86,7 @@ vlc_frame_t *vlc_frame_Init(vlc_frame_t *restrict f, const struct vlc_frame_call
f->i_pts =
f->i_dts = VLC_TICK_INVALID;
f->i_length = 0;
+ vlc_ancillary_array_Init(&f->priv_ancillaries);
f->cbs = cbs;
return f;
}
@@ -87,16 +103,6 @@ static const struct vlc_frame_callbacks vlc_frame_generic_cbs =
vlc_frame_generic_Release,
};
-static void BlockMetaCopy( vlc_frame_t *restrict out, const vlc_frame_t *in )
-{
- out->p_next = in->p_next;
- out->i_nb_samples = in->i_nb_samples;
- out->i_dts = in->i_dts;
- out->i_pts = in->i_pts;
- out->i_flags = in->i_flags;
- out->i_length = in->i_length;
-}
-
/** Initial memory alignment of data frame.
* @note This must be a multiple of sizeof(void*) and a power of two.
* libavcodec AVX optimizations require at least 32-bytes. */
@@ -138,6 +144,8 @@ void vlc_frame_Release(vlc_frame_t *frame)
frame->p_next = NULL;
vlc_frame_Check (frame);
#endif
+ vlc_ancillary_array_Clear(&frame->priv_ancillaries);
+
frame->cbs->free(frame);
}
@@ -149,7 +157,10 @@ static vlc_frame_t *vlc_frame_ReallocDup( vlc_frame_t *frame, ssize_t i_prebody,
if( frame->i_buffer > 0 )
memcpy( p_rea->p_buffer + i_prebody, frame->p_buffer, frame->i_buffer );
- BlockMetaCopy( p_rea, frame );
+
+ p_rea->p_next = frame->p_next;
+ vlc_frame_CopyProperties( p_rea, frame );
+
vlc_frame_Release( frame );
return p_rea;
}
@@ -502,3 +513,15 @@ vlc_frame_t *vlc_frame_FilePath(const char *path, bool write)
vlc_close (fd);
return frame;
}
+
+int
+vlc_frame_AttachAncillary(vlc_frame_t *frame, struct vlc_ancillary *ancillary)
+{
+ return vlc_ancillary_array_Insert(&frame->priv_ancillaries, ancillary);
+}
+
+struct vlc_ancillary *
+vlc_frame_GetAncillary(vlc_frame_t *frame, vlc_ancillary_id id)
+{
+ return vlc_ancillary_array_Get(&frame->priv_ancillaries, id);
+}
=====================================
src/misc/picture.c
=====================================
@@ -38,6 +38,8 @@
#include <vlc_image.h>
#include <vlc_block.h>
+#include "ancillary.h"
+
static void PictureDestroyContext( picture_t *p_picture )
{
picture_context_t *ctx = p_picture->context;
@@ -98,6 +100,9 @@ void picture_Reset( picture_t *p_picture )
p_picture->i_nb_fields = 2;
p_picture->b_top_field_first = false;
PictureDestroyContext( p_picture );
+
+ picture_priv_t *priv = container_of(p_picture, picture_priv_t, picture);
+ vlc_ancillary_array_Clear(&priv->ancillaries);
}
/*****************************************************************************
@@ -220,6 +225,8 @@ static bool picture_InitPrivate(const video_format_t *restrict p_fmt,
else
priv->gc.destroy = picture_DestroyDummy;
+ vlc_ancillary_array_Init(&priv->ancillaries);
+
return true;
}
@@ -344,6 +351,7 @@ void picture_Destroy(picture_t *picture)
picture_priv_t *priv = container_of(picture, picture_priv_t, picture);
assert(priv->gc.destroy != NULL);
priv->gc.destroy(picture);
+ vlc_ancillary_array_Clear(&priv->ancillaries);
free(priv);
}
@@ -395,6 +403,10 @@ void picture_CopyProperties( picture_t *p_dst, const picture_t *p_src )
p_dst->b_progressive = p_src->b_progressive;
p_dst->i_nb_fields = p_src->i_nb_fields;
p_dst->b_top_field_first = p_src->b_top_field_first;
+
+ const picture_priv_t *src_priv = container_of(p_src, picture_priv_t, picture);
+ picture_priv_t *dst_priv = container_of(p_dst, picture_priv_t, picture);
+ vlc_ancillary_array_Dup(&dst_priv->ancillaries, &src_priv->ancillaries);
}
void picture_CopyPixels( picture_t *p_dst, const picture_t *p_src )
@@ -453,9 +465,27 @@ picture_t *picture_InternalClone(picture_t *picture,
picture_t *picture_Clone(picture_t *picture)
{
picture_t *clone = picture_InternalClone(picture, picture_DestroyClone, picture);
+
+ const picture_priv_t *priv = container_of(picture, picture_priv_t, picture);
+ picture_priv_t *clone_priv = container_of(clone, picture_priv_t, picture);
+ vlc_ancillary_array_Dup(&clone_priv->ancillaries, &priv->ancillaries);
return clone;
}
+int
+picture_AttachAncillary(picture_t *pic, struct vlc_ancillary *ancillary)
+{
+ picture_priv_t *priv = container_of(pic, picture_priv_t, picture);
+ return vlc_ancillary_array_Insert(&priv->ancillaries, ancillary);
+}
+
+struct vlc_ancillary *
+picture_GetAncillary(picture_t *pic, vlc_ancillary_id id)
+{
+ picture_priv_t *priv = container_of(pic, picture_priv_t, picture);
+ return vlc_ancillary_array_Get(&priv->ancillaries, id);
+}
+
/*****************************************************************************
*
*****************************************************************************/
=====================================
src/misc/picture.h
=====================================
@@ -22,6 +22,7 @@
#include <stddef.h>
#include <vlc_picture.h>
+struct vlc_ancillary;
typedef struct
{
@@ -31,6 +32,10 @@ typedef struct
void (*destroy)(picture_t *);
void *opaque;
} gc;
+
+ /** Private ancillary struct. Don't use it directly, but use it via
+ * picture_AttachAncillary() and picture_GetAncillary(). */
+ struct vlc_ancillary **ancillaries;
} picture_priv_t;
void *picture_Allocate(int *, size_t);
=====================================
test/Makefile.am
=====================================
@@ -23,6 +23,7 @@ check_PROGRAMS = \
test_libvlc_renderer_discoverer \
test_libvlc_slaves \
test_src_config_chain \
+ test_src_misc_ancillary \
test_src_misc_variables \
test_src_input_stream \
test_src_input_stream_fifo \
@@ -103,6 +104,8 @@ test_libvlc_slaves_SOURCES = libvlc/slaves.c
test_libvlc_slaves_LDADD = $(LIBVLCCORE) $(LIBVLC)
test_libvlc_meta_SOURCES = libvlc/meta.c
test_libvlc_meta_LDADD = $(LIBVLCCORE) $(LIBVLC)
+test_src_misc_ancillary_SOURCES = src/misc/ancillary.c
+test_src_misc_ancillary_LDADD = $(LIBVLCCORE) $(LIBVLC)
test_src_misc_variables_SOURCES = src/misc/variables.c
test_src_misc_variables_LDADD = $(LIBVLCCORE) $(LIBVLC)
test_src_config_chain_SOURCES = src/config/chain.c
=====================================
test/src/misc/ancillary.c
=====================================
@@ -0,0 +1,118 @@
+/*****************************************************************************
+ * ancillary.c: test for ancillary
+ *****************************************************************************
+ * Copyright (C) 2021 the VideoLAN team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_frame.h>
+#include <vlc_picture.h>
+#include <vlc_ancillary.h>
+
+#include <assert.h>
+
+static void
+ancillary_free(void *data)
+{
+ assert(strncmp(data, "test", 4) == 0);
+ free(data);
+}
+
+int main( void )
+{
+ vlc_frame_t *frame = vlc_frame_Alloc(1);
+ assert(frame);
+
+ int ret;
+ struct vlc_ancillary *ancillary;
+
+ /* Create and try to attach 3 ancillaries to the frame, only 2 will be
+ * attached. */
+ for (size_t i = 0; i < 3; ++i)
+ {
+ char *data;
+ ret = asprintf(&data, "test%zu", i);
+ assert(ret > 0);
+
+ vlc_ancillary_id id;
+ switch (i)
+ {
+ case 0:
+ /* Check that only one ancillary of the same id is added (the
+ * last one take precedence). */
+ case 1: id = VLC_ANCILLARY_ID('t','s','t','1'); break;
+ case 2: id = VLC_ANCILLARY_ID('t','s','t','2'); break;
+ default: vlc_assert_unreachable();
+ }
+
+ ancillary = vlc_ancillary_CreateWithFreeCb(data, id, ancillary_free);
+ assert(ancillary);
+
+ ret = vlc_frame_AttachAncillary(frame, ancillary);
+ assert(ret == VLC_SUCCESS);
+ vlc_ancillary_Release(ancillary);
+ }
+
+ /* Check that ancillaries are copied via a vlc_frame_CopyProperties() (done
+ * by vlc_frame_Duplicate()). */
+ vlc_frame_t *copy_frame = vlc_frame_Duplicate(frame);
+ assert(copy_frame);
+ vlc_frame_Release(frame);
+ frame = copy_frame;
+
+ picture_t *picture = picture_New(VLC_CODEC_NV12, 1, 1, 1, 1);
+ assert(picture);
+
+ /* Manually attach both ancillaries to a newly allocated picture. */
+ ancillary = vlc_frame_GetAncillary(frame, VLC_ANCILLARY_ID('t','s','t','1'));
+ assert(ancillary);
+ picture_AttachAncillary(picture, ancillary);
+
+ ancillary = vlc_frame_GetAncillary(frame, VLC_ANCILLARY_ID('t','s','t','2'));
+ assert(ancillary);
+ picture_AttachAncillary(picture, ancillary);
+
+ vlc_frame_Release(frame);
+
+ /* Check that ancillaries are copied via a picture_Clone(). */
+ picture_t *clone = picture_Clone(picture);
+ assert(clone);
+ picture_Release(picture);
+
+ /* Check that ancillaries are copied via a picture_Copy(). */
+ picture_t *copy = picture_New(VLC_CODEC_I420, 1, 1, 1, 1);
+ assert(copy);
+ picture_Copy(copy, clone);
+ picture_Release(clone);
+
+ /* Check that ancillaries are still valid. */
+ ancillary = picture_GetAncillary(copy, VLC_ANCILLARY_ID('t','s','t','1'));
+ assert(ancillary);
+ assert(strcmp("test1", vlc_ancillary_GetData(ancillary)) == 0);
+
+ ancillary = picture_GetAncillary(copy, VLC_ANCILLARY_ID('t','s','t','2'));
+ assert(ancillary);
+ assert(strcmp("test2", vlc_ancillary_GetData(ancillary)) == 0);
+
+ picture_Release(copy);
+
+ return 0;
+}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/543d402ecbf078f3cdd5293ef80b5f14a6c9665c...d0547192a7f7433f9afc64a81dd7264536558f9e
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/543d402ecbf078f3cdd5293ef80b5f14a6c9665c...d0547192a7f7433f9afc64a81dd7264536558f9e
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list