forked from FFmpeg/FFmpeg
lavc/container_fifo: move to lavu and make public
This can be useful in other places, e.g. it can replace objpool in fftools. The API is modified in the following nontrivial ways: * opaque pointers can be passed through to all user callbacks * read and write were previously separate callbacks in order to accomodate the caller wishing to write a new reference to the FIFO and keep the original one; the two callbacks are now merged into one, and a flags argument is added that allows to request such behaviour on a per-call basis * new peek and drain functions
This commit is contained in:
parent
56ba57b672
commit
2e956d9c0f
9 changed files with 215 additions and 145 deletions
|
@ -2,10 +2,13 @@ The last version increases of all libraries were on 2024-03-07
|
||||||
|
|
||||||
API changes, most recent first:
|
API changes, most recent first:
|
||||||
|
|
||||||
2024-12-15 - xxxxxxxxxx - lavu 59.51.100 - refstruct.h
|
2024-12-15 - xxxxxxxxxx - lavu 59.51.100 - refstruct.h container_fifo.h
|
||||||
Add a new public header refstruct.h with new API for
|
Add a new public header refstruct.h with new API for
|
||||||
reference-counted objects.
|
reference-counted objects.
|
||||||
|
|
||||||
|
Add a new public header container_fifo.h with new API for
|
||||||
|
a FIFO of container objects (e.g. AVFrame or AVPacket).
|
||||||
|
|
||||||
2024-12-13 - xxxxxxxxxx - lavu 59.50.100 - channel_layout.h
|
2024-12-13 - xxxxxxxxxx - lavu 59.50.100 - channel_layout.h
|
||||||
Add AV_CH_LAYOUT_9POINT1POINT6 and AV_CHANNEL_LAYOUT_9POINT1POINT6.
|
Add AV_CH_LAYOUT_9POINT1POINT6 and AV_CHANNEL_LAYOUT_9POINT1POINT6.
|
||||||
|
|
||||||
|
|
|
@ -442,7 +442,7 @@ OBJS-$(CONFIG_HCA_DECODER) += hcadec.o
|
||||||
OBJS-$(CONFIG_HCOM_DECODER) += hcom.o
|
OBJS-$(CONFIG_HCOM_DECODER) += hcom.o
|
||||||
OBJS-$(CONFIG_HDR_DECODER) += hdrdec.o
|
OBJS-$(CONFIG_HDR_DECODER) += hdrdec.o
|
||||||
OBJS-$(CONFIG_HDR_ENCODER) += hdrenc.o
|
OBJS-$(CONFIG_HDR_ENCODER) += hdrenc.o
|
||||||
OBJS-$(CONFIG_HEVC_DECODER) += aom_film_grain.o h274.o container_fifo.o
|
OBJS-$(CONFIG_HEVC_DECODER) += aom_film_grain.o h274.o
|
||||||
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
|
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
|
||||||
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
|
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
|
||||||
OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER) += d3d12va_encode_hevc.o h265_profile_level.o \
|
OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER) += d3d12va_encode_hevc.o h265_profile_level.o \
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of FFmpeg.
|
|
||||||
*
|
|
||||||
* FFmpeg 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.
|
|
||||||
*
|
|
||||||
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVCODEC_CONTAINER_FIFO_H
|
|
||||||
#define AVCODEC_CONTAINER_FIFO_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ContainerFifo is a FIFO for "containers" - dynamically allocated reusable
|
|
||||||
* structs (e.g. AVFrame or AVPacket). ContainerFifo uses an internal pool of
|
|
||||||
* such containers to avoid allocating and freeing them repeatedly.
|
|
||||||
*/
|
|
||||||
typedef struct ContainerFifo ContainerFifo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate a new ContainerFifo for the container type defined by provided
|
|
||||||
* callbacks.
|
|
||||||
*
|
|
||||||
* @param container_alloc allocate a new container instance and return a pointer
|
|
||||||
* to it, or NULL on failure
|
|
||||||
* @param container_reset reset the provided container instance to a clean state
|
|
||||||
* @param container_free free the provided container instance
|
|
||||||
* @param fifo_write transfer the contents of src to dst, where src is a
|
|
||||||
* container instance provided to ff_container_fifo_write()
|
|
||||||
* @param fifo_read transfer the contents of src to dst in other cases
|
|
||||||
*
|
|
||||||
* @note fifo_read() and fifo_write() are different parameters in order to allow
|
|
||||||
* fifo_write() implementations that make a new reference in dst, leaving
|
|
||||||
* src untouched (see e.g. ff_container_fifo_alloc_avframe())
|
|
||||||
*/
|
|
||||||
ContainerFifo*
|
|
||||||
ff_container_fifo_alloc(void* (*container_alloc)(void),
|
|
||||||
void (*container_reset)(void *obj),
|
|
||||||
void (*container_free) (void *obj),
|
|
||||||
int (*fifo_write) (void *dst, void *src),
|
|
||||||
int (*fifo_read) (void *dst, void *src));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate a ContainerFifo instance for AVFrames.
|
|
||||||
* Note that ff_container_fifo_write() will call av_frame_ref() on src, making a
|
|
||||||
* new reference in dst and leaving src untouched.
|
|
||||||
*
|
|
||||||
* @param flags unused currently
|
|
||||||
*/
|
|
||||||
ContainerFifo *ff_container_fifo_alloc_avframe(unsigned flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free a ContainerFifo and everything in it.
|
|
||||||
*/
|
|
||||||
void ff_container_fifo_free(ContainerFifo **pf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the contents of obj to the FIFO.
|
|
||||||
*
|
|
||||||
* The fifo_write() callback previously provided to ff_container_fifo_alloc()
|
|
||||||
* will be called with obj as src in order to perform the actual transfer.
|
|
||||||
*/
|
|
||||||
int ff_container_fifo_write(ContainerFifo *pf, void *obj);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the next available object from the FIFO into obj.
|
|
||||||
*
|
|
||||||
* The fifo_read() callback previously provided to ff_container_fifo_alloc()
|
|
||||||
* will be called with obj as dst in order to perform the actual transfer.
|
|
||||||
*/
|
|
||||||
int ff_container_fifo_read(ContainerFifo *pf, void *obj);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return number of objects available for reading
|
|
||||||
*/
|
|
||||||
size_t ff_container_fifo_can_read(ContainerFifo *pf);
|
|
||||||
|
|
||||||
#endif // AVCODEC_CONTAINER_FIFO_H
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "libavutil/attributes.h"
|
#include "libavutil/attributes.h"
|
||||||
#include "libavutil/avstring.h"
|
#include "libavutil/avstring.h"
|
||||||
#include "libavutil/common.h"
|
#include "libavutil/common.h"
|
||||||
|
#include "libavutil/container_fifo.h"
|
||||||
#include "libavutil/film_grain_params.h"
|
#include "libavutil/film_grain_params.h"
|
||||||
#include "libavutil/internal.h"
|
#include "libavutil/internal.h"
|
||||||
#include "libavutil/md5.h"
|
#include "libavutil/md5.h"
|
||||||
|
@ -41,7 +42,6 @@
|
||||||
#include "bswapdsp.h"
|
#include "bswapdsp.h"
|
||||||
#include "cabac_functions.h"
|
#include "cabac_functions.h"
|
||||||
#include "codec_internal.h"
|
#include "codec_internal.h"
|
||||||
#include "container_fifo.h"
|
|
||||||
#include "decode.h"
|
#include "decode.h"
|
||||||
#include "golomb.h"
|
#include "golomb.h"
|
||||||
#include "hevc.h"
|
#include "hevc.h"
|
||||||
|
@ -3748,7 +3748,7 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
|
||||||
|
|
||||||
s->pkt_dts = AV_NOPTS_VALUE;
|
s->pkt_dts = AV_NOPTS_VALUE;
|
||||||
|
|
||||||
if (ff_container_fifo_can_read(s->output_fifo))
|
if (av_container_fifo_can_read(s->output_fifo))
|
||||||
goto do_output;
|
goto do_output;
|
||||||
|
|
||||||
av_packet_unref(avpkt);
|
av_packet_unref(avpkt);
|
||||||
|
@ -3786,7 +3786,7 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
do_output:
|
do_output:
|
||||||
if (ff_container_fifo_read(s->output_fifo, frame) >= 0) {
|
if (av_container_fifo_read(s->output_fifo, frame, 0) >= 0) {
|
||||||
if (!(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))
|
if (!(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))
|
||||||
av_frame_remove_side_data(frame, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
|
av_frame_remove_side_data(frame, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
|
||||||
|
|
||||||
|
@ -3846,7 +3846,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
|
||||||
|
|
||||||
av_freep(&s->md5_ctx);
|
av_freep(&s->md5_ctx);
|
||||||
|
|
||||||
ff_container_fifo_free(&s->output_fifo);
|
av_container_fifo_free(&s->output_fifo);
|
||||||
|
|
||||||
for (int layer = 0; layer < FF_ARRAY_ELEMS(s->layers); layer++) {
|
for (int layer = 0; layer < FF_ARRAY_ELEMS(s->layers); layer++) {
|
||||||
HEVCLayerContext *l = &s->layers[layer];
|
HEVCLayerContext *l = &s->layers[layer];
|
||||||
|
@ -3890,7 +3890,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx)
|
||||||
s->local_ctx[0].logctx = avctx;
|
s->local_ctx[0].logctx = avctx;
|
||||||
s->local_ctx[0].common_cabac_state = &s->cabac;
|
s->local_ctx[0].common_cabac_state = &s->cabac;
|
||||||
|
|
||||||
s->output_fifo = ff_container_fifo_alloc_avframe(0);
|
s->output_fifo = av_container_fifo_alloc_avframe(0);
|
||||||
if (!s->output_fifo)
|
if (!s->output_fifo)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
|
|
@ -502,7 +502,7 @@ typedef struct HEVCContext {
|
||||||
/** 1 if the independent slice segment header was successfully parsed */
|
/** 1 if the independent slice segment header was successfully parsed */
|
||||||
uint8_t slice_initialized;
|
uint8_t slice_initialized;
|
||||||
|
|
||||||
struct ContainerFifo *output_fifo;
|
struct AVContainerFifo *output_fifo;
|
||||||
|
|
||||||
HEVCParamSets ps;
|
HEVCParamSets ps;
|
||||||
HEVCSEI sei;
|
HEVCSEI sei;
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/container_fifo.h"
|
||||||
#include "libavutil/mem.h"
|
#include "libavutil/mem.h"
|
||||||
#include "libavutil/stereo3d.h"
|
#include "libavutil/stereo3d.h"
|
||||||
|
|
||||||
#include "container_fifo.h"
|
|
||||||
#include "decode.h"
|
#include "decode.h"
|
||||||
#include "hevc.h"
|
#include "hevc.h"
|
||||||
#include "hevcdec.h"
|
#include "hevcdec.h"
|
||||||
|
@ -267,7 +267,7 @@ int ff_hevc_output_frames(HEVCContext *s,
|
||||||
|
|
||||||
if (output) {
|
if (output) {
|
||||||
f->pkt_dts = s->pkt_dts;
|
f->pkt_dts = s->pkt_dts;
|
||||||
ret = ff_container_fifo_write(s->output_fifo, f);
|
ret = av_container_fifo_write(s->output_fifo, f, AV_CONTAINER_FIFO_FLAG_REF);
|
||||||
}
|
}
|
||||||
ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT);
|
ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -19,6 +19,7 @@ HEADERS = adler32.h \
|
||||||
camellia.h \
|
camellia.h \
|
||||||
channel_layout.h \
|
channel_layout.h \
|
||||||
common.h \
|
common.h \
|
||||||
|
container_fifo.h \
|
||||||
cpu.h \
|
cpu.h \
|
||||||
crc.h \
|
crc.h \
|
||||||
csp.h \
|
csp.h \
|
||||||
|
@ -119,6 +120,7 @@ OBJS = adler32.o \
|
||||||
cast5.o \
|
cast5.o \
|
||||||
camellia.o \
|
camellia.o \
|
||||||
channel_layout.o \
|
channel_layout.o \
|
||||||
|
container_fifo.o \
|
||||||
cpu.o \
|
cpu.o \
|
||||||
crc.o \
|
crc.o \
|
||||||
csp.o \
|
csp.o \
|
||||||
|
|
|
@ -16,32 +16,32 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libavutil/error.h"
|
#include "avassert.h"
|
||||||
#include "libavutil/fifo.h"
|
|
||||||
#include "libavutil/frame.h"
|
|
||||||
#include "libavutil/mem.h"
|
|
||||||
|
|
||||||
#include "container_fifo.h"
|
#include "container_fifo.h"
|
||||||
#include "libavutil/refstruct.h"
|
#include "error.h"
|
||||||
|
#include "fifo.h"
|
||||||
|
#include "frame.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "refstruct.h"
|
||||||
|
|
||||||
struct ContainerFifo {
|
struct AVContainerFifo {
|
||||||
AVFifo *fifo;
|
AVFifo *fifo;
|
||||||
AVRefStructPool *pool;
|
AVRefStructPool *pool;
|
||||||
|
|
||||||
void* (*container_alloc)(void);
|
void *opaque;
|
||||||
void (*container_reset)(void *obj);
|
void* (*container_alloc)(void *opaque);
|
||||||
void (*container_free) (void *obj);
|
void (*container_reset)(void *opaque, void *obj);
|
||||||
int (*fifo_write) (void *dst, void *src);
|
void (*container_free) (void *opaque, void *obj);
|
||||||
int (*fifo_read) (void *dst, void *src);
|
int (*fifo_transfer) (void *opaque, void *dst, void *src, unsigned flags);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int container_fifo_init_entry(AVRefStructOpaque opaque, void *obj)
|
static int container_fifo_init_entry(AVRefStructOpaque opaque, void *obj)
|
||||||
{
|
{
|
||||||
ContainerFifo *cf = opaque.nc;
|
AVContainerFifo *cf = opaque.nc;
|
||||||
void **pobj = obj;
|
void **pobj = obj;
|
||||||
|
|
||||||
*pobj = cf->container_alloc();
|
*pobj = cf->container_alloc(cf->opaque);
|
||||||
if (!*pobj)
|
if (!*pobj)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
@ -50,34 +50,35 @@ static int container_fifo_init_entry(AVRefStructOpaque opaque, void *obj)
|
||||||
|
|
||||||
static void container_fifo_reset_entry(AVRefStructOpaque opaque, void *obj)
|
static void container_fifo_reset_entry(AVRefStructOpaque opaque, void *obj)
|
||||||
{
|
{
|
||||||
ContainerFifo *cf = opaque.nc;
|
AVContainerFifo *cf = opaque.nc;
|
||||||
cf->container_reset(*(void**)obj);
|
cf->container_reset(cf->opaque, *(void**)obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void container_fifo_free_entry(AVRefStructOpaque opaque, void *obj)
|
static void container_fifo_free_entry(AVRefStructOpaque opaque, void *obj)
|
||||||
{
|
{
|
||||||
ContainerFifo *cf = opaque.nc;
|
AVContainerFifo *cf = opaque.nc;
|
||||||
cf->container_free(*(void**)obj);
|
cf->container_free(cf->opaque, *(void**)obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContainerFifo*
|
AVContainerFifo*
|
||||||
ff_container_fifo_alloc(void* (*container_alloc)(void),
|
av_container_fifo_alloc(void *opaque,
|
||||||
void (*container_reset)(void *obj),
|
void* (*container_alloc)(void *opaque),
|
||||||
void (*container_free) (void *obj),
|
void (*container_reset)(void *opaque, void *obj),
|
||||||
int (*fifo_write) (void *dst, void *src),
|
void (*container_free) (void *opaque, void *obj),
|
||||||
int (*fifo_read) (void *dst, void *src))
|
int (*fifo_transfer) (void *opaque, void *dst, void *src, unsigned flags),
|
||||||
|
unsigned flags)
|
||||||
{
|
{
|
||||||
ContainerFifo *cf;
|
AVContainerFifo *cf;
|
||||||
|
|
||||||
cf = av_mallocz(sizeof(*cf));
|
cf = av_mallocz(sizeof(*cf));
|
||||||
if (!cf)
|
if (!cf)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
cf->opaque = opaque;
|
||||||
cf->container_alloc = container_alloc;
|
cf->container_alloc = container_alloc;
|
||||||
cf->container_reset = container_reset;
|
cf->container_reset = container_reset;
|
||||||
cf->container_free = container_free;
|
cf->container_free = container_free;
|
||||||
cf->fifo_write = fifo_write;
|
cf->fifo_transfer = fifo_transfer;
|
||||||
cf->fifo_read = fifo_read;
|
|
||||||
|
|
||||||
cf->fifo = av_fifo_alloc2(1, sizeof(void*), AV_FIFO_FLAG_AUTO_GROW);
|
cf->fifo = av_fifo_alloc2(1, sizeof(void*), AV_FIFO_FLAG_AUTO_GROW);
|
||||||
if (!cf->fifo)
|
if (!cf->fifo)
|
||||||
|
@ -93,13 +94,13 @@ ff_container_fifo_alloc(void* (*container_alloc)(void),
|
||||||
|
|
||||||
return cf;
|
return cf;
|
||||||
fail:
|
fail:
|
||||||
ff_container_fifo_free(&cf);
|
av_container_fifo_free(&cf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ff_container_fifo_free(ContainerFifo **pcf)
|
void av_container_fifo_free(AVContainerFifo **pcf)
|
||||||
{
|
{
|
||||||
ContainerFifo *cf;
|
AVContainerFifo *cf;
|
||||||
|
|
||||||
if (!*pcf)
|
if (!*pcf)
|
||||||
return;
|
return;
|
||||||
|
@ -118,7 +119,7 @@ void ff_container_fifo_free(ContainerFifo **pcf)
|
||||||
av_freep(pcf);
|
av_freep(pcf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_container_fifo_read(ContainerFifo *cf, void *obj)
|
int av_container_fifo_read(AVContainerFifo *cf, void *obj, unsigned flags)
|
||||||
{
|
{
|
||||||
void **psrc;
|
void **psrc;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -127,13 +128,38 @@ int ff_container_fifo_read(ContainerFifo *cf, void *obj)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = cf->fifo_read(obj, *psrc);
|
ret = cf->fifo_transfer(cf->opaque, obj, *psrc, flags);
|
||||||
av_refstruct_unref(&psrc);
|
av_refstruct_unref(&psrc);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_container_fifo_write(ContainerFifo *cf, void *obj)
|
int av_container_fifo_peek(AVContainerFifo *cf, void **pdst, size_t offset)
|
||||||
|
{
|
||||||
|
void **pobj;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = av_fifo_peek(cf->fifo, &pobj, 1, offset);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*pdst = *pobj;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void av_container_fifo_drain(AVContainerFifo *cf, size_t nb_elems)
|
||||||
|
{
|
||||||
|
av_assert0(nb_elems <= av_fifo_can_read(cf->fifo));
|
||||||
|
while (nb_elems--) {
|
||||||
|
void **pobj;
|
||||||
|
int ret = av_fifo_read(cf->fifo, &pobj, 1);
|
||||||
|
av_assert0(ret >= 0);
|
||||||
|
av_refstruct_unref(&pobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int av_container_fifo_write(AVContainerFifo *cf, void *obj, unsigned flags)
|
||||||
{
|
{
|
||||||
void **pdst;
|
void **pdst;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -142,7 +168,7 @@ int ff_container_fifo_write(ContainerFifo *cf, void *obj)
|
||||||
if (!pdst)
|
if (!pdst)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
ret = cf->fifo_write(*pdst, obj);
|
ret = cf->fifo_transfer(cf->opaque, *pdst, obj, flags);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
@ -156,40 +182,38 @@ fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ff_container_fifo_can_read(ContainerFifo *cf)
|
size_t av_container_fifo_can_read(const AVContainerFifo *cf)
|
||||||
{
|
{
|
||||||
return av_fifo_can_read(cf->fifo);
|
return av_fifo_can_read(cf->fifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *frame_alloc(void)
|
static void *frame_alloc(void *opaque)
|
||||||
{
|
{
|
||||||
return av_frame_alloc();
|
return av_frame_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frame_reset(void *obj)
|
static void frame_reset(void *opaque, void *obj)
|
||||||
{
|
{
|
||||||
av_frame_unref(obj);
|
av_frame_unref(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frame_free(void *obj)
|
static void frame_free(void *opaque, void *obj)
|
||||||
{
|
{
|
||||||
AVFrame *frame = obj;
|
AVFrame *frame = obj;
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int frame_ref(void *dst, void *src)
|
static int frame_transfer(void *opaque, void *dst, void *src, unsigned flags)
|
||||||
{
|
{
|
||||||
return av_frame_ref(dst, src);
|
if (flags & AV_CONTAINER_FIFO_FLAG_REF)
|
||||||
}
|
return av_frame_ref(dst, src);
|
||||||
|
|
||||||
static int frame_move_ref(void *dst, void *src)
|
|
||||||
{
|
|
||||||
av_frame_move_ref(dst, src);
|
av_frame_move_ref(dst, src);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContainerFifo *ff_container_fifo_alloc_avframe(unsigned flags)
|
AVContainerFifo *av_container_fifo_alloc_avframe(unsigned flags)
|
||||||
{
|
{
|
||||||
return ff_container_fifo_alloc(frame_alloc, frame_reset, frame_free,
|
return av_container_fifo_alloc(NULL, frame_alloc, frame_reset, frame_free,
|
||||||
frame_ref, frame_move_ref);
|
frame_transfer, 0);
|
||||||
}
|
}
|
130
libavutil/container_fifo.h
Normal file
130
libavutil/container_fifo.h
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_CONTAINER_FIFO_H
|
||||||
|
#define AVUTIL_CONTAINER_FIFO_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AVContainerFifo is a FIFO for "containers" - dynamically allocated reusable
|
||||||
|
* structs (e.g. AVFrame or AVPacket). AVContainerFifo uses an internal pool of
|
||||||
|
* such containers to avoid allocating and freeing them repeatedly.
|
||||||
|
*/
|
||||||
|
typedef struct AVContainerFifo AVContainerFifo;
|
||||||
|
|
||||||
|
enum AVContainerFifoFlags {
|
||||||
|
/**
|
||||||
|
* Signal to av_container_fifo_write() that it should make a new reference
|
||||||
|
* to data in src rather than consume its contents.
|
||||||
|
*
|
||||||
|
* @note you must handle this flag manually in your own fifo_transfer()
|
||||||
|
* callback
|
||||||
|
*/
|
||||||
|
AV_CONTAINER_FIFO_FLAG_REF = (1 << 0),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This and all higher bits in flags may be set to any value by the caller
|
||||||
|
* and are guaranteed to be passed through to the fifo_transfer() callback
|
||||||
|
* and not be interpreted by AVContainerFifo code.
|
||||||
|
*/
|
||||||
|
AV_CONTAINER_FIFO_FLAG_USER = (1 << 16),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new AVContainerFifo for the container type defined by provided
|
||||||
|
* callbacks.
|
||||||
|
*
|
||||||
|
* @param opaque user data that will be passed to the callbacks provided to this
|
||||||
|
* function
|
||||||
|
* @param container_alloc allocate a new container instance and return a pointer
|
||||||
|
* to it, or NULL on failure
|
||||||
|
* @param container_reset reset the provided container instance to a clean state
|
||||||
|
* @param container_free free the provided container instance
|
||||||
|
* @param fifo_transfer Transfer the contents of container src to dst.
|
||||||
|
* @param flags currently unused
|
||||||
|
*
|
||||||
|
* @return newly allocated AVContainerFifo, or NULL on failure
|
||||||
|
*/
|
||||||
|
AVContainerFifo*
|
||||||
|
av_container_fifo_alloc(void *opaque,
|
||||||
|
void* (*container_alloc)(void *opaque),
|
||||||
|
void (*container_reset)(void *opaque, void *obj),
|
||||||
|
void (*container_free) (void *opaque, void *obj),
|
||||||
|
int (*fifo_transfer) (void *opaque, void *dst, void *src, unsigned flags),
|
||||||
|
unsigned flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an AVContainerFifo instance for AVFrames.
|
||||||
|
*
|
||||||
|
* @param flags currently unused
|
||||||
|
*/
|
||||||
|
AVContainerFifo *av_container_fifo_alloc_avframe(unsigned flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a AVContainerFifo and everything in it.
|
||||||
|
*/
|
||||||
|
void av_container_fifo_free(AVContainerFifo **cf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the contents of obj to the FIFO.
|
||||||
|
*
|
||||||
|
* The fifo_transfer() callback previously provided to av_container_fifo_alloc()
|
||||||
|
* will be called with obj as src in order to perform the actual transfer.
|
||||||
|
*/
|
||||||
|
int av_container_fifo_write(AVContainerFifo *cf, void *obj, unsigned flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the next available object from the FIFO into obj.
|
||||||
|
*
|
||||||
|
* The fifo_read() callback previously provided to av_container_fifo_alloc()
|
||||||
|
* will be called with obj as dst in order to perform the actual transfer.
|
||||||
|
*/
|
||||||
|
int av_container_fifo_read(AVContainerFifo *cf, void *obj, unsigned flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access objects stored in the FIFO without retrieving them. The
|
||||||
|
* fifo_transfer() callback will NOT be invoked and the FIFO state will not be
|
||||||
|
* modified.
|
||||||
|
*
|
||||||
|
* @param pobj Pointer to the object stored in the FIFO will be written here on
|
||||||
|
* success. The object remains owned by the FIFO and the caller may
|
||||||
|
* only access it as long as the FIFO is not modified.
|
||||||
|
* @param offset Position of the object to retrieve - 0 is the next item that
|
||||||
|
* would be read, 1 the one after, etc. Must be smaller than
|
||||||
|
* av_container_fifo_can_read().
|
||||||
|
*
|
||||||
|
* @retval 0 success, a pointer was written into pobj
|
||||||
|
* @retval AVERROR(EINVAL) invalid offset value
|
||||||
|
*/
|
||||||
|
int av_container_fifo_peek(AVContainerFifo *cf, void **pobj, size_t offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discard the specified number of elements from the FIFO.
|
||||||
|
*
|
||||||
|
* @param nb_elems number of elements to discard, MUST NOT be larger than
|
||||||
|
* av_fifo_can_read(f)
|
||||||
|
*/
|
||||||
|
void av_container_fifo_drain(AVContainerFifo *cf, size_t nb_elems);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return number of objects available for reading
|
||||||
|
*/
|
||||||
|
size_t av_container_fifo_can_read(const AVContainerFifo *cf);
|
||||||
|
|
||||||
|
#endif // AVCODEC_CONTAINER_FIFO_H
|
Loading…
Add table
Reference in a new issue