tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

container_fifo.c (5592B)


      1 /*
      2 * This file is part of FFmpeg.
      3 *
      4 * FFmpeg is free software; you can redistribute it and/or
      5 * modify it under the terms of the GNU Lesser General Public
      6 * License as published by the Free Software Foundation; either
      7 * version 2.1 of the License, or (at your option) any later version.
      8 *
      9 * FFmpeg is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12 * Lesser General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU Lesser General Public
     15 * License along with FFmpeg; if not, write to the Free Software
     16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     17 */
     18 
     19 #include "avassert.h"
     20 #include "container_fifo.h"
     21 #include "error.h"
     22 #include "fifo.h"
     23 #include "frame.h"
     24 #include "mem.h"
     25 #include "refstruct.h"
     26 
     27 struct AVContainerFifo {
     28    AVFifo             *fifo;
     29    AVRefStructPool    *pool;
     30 
     31    void               *opaque;
     32    void*             (*container_alloc)(void *opaque);
     33    void              (*container_reset)(void *opaque, void *obj);
     34    void              (*container_free) (void *opaque, void *obj);
     35    int               (*fifo_transfer)  (void *opaque, void *dst, void *src, unsigned flags);
     36 
     37 };
     38 
     39 static int container_fifo_init_entry(AVRefStructOpaque opaque, void *obj)
     40 {
     41    AVContainerFifo *cf = opaque.nc;
     42    void **pobj = obj;
     43 
     44    *pobj = cf->container_alloc(cf->opaque);
     45    if (!*pobj)
     46        return AVERROR(ENOMEM);
     47 
     48    return 0;
     49 }
     50 
     51 static void container_fifo_reset_entry(AVRefStructOpaque opaque, void *obj)
     52 {
     53    AVContainerFifo *cf = opaque.nc;
     54    cf->container_reset(cf->opaque, *(void**)obj);
     55 }
     56 
     57 static void container_fifo_free_entry(AVRefStructOpaque opaque, void *obj)
     58 {
     59    AVContainerFifo *cf = opaque.nc;
     60    cf->container_free(cf->opaque, *(void**)obj);
     61 }
     62 
     63 AVContainerFifo*
     64 av_container_fifo_alloc(void *opaque,
     65                        void* (*container_alloc)(void *opaque),
     66                        void  (*container_reset)(void *opaque, void *obj),
     67                        void  (*container_free) (void *opaque, void *obj),
     68                        int   (*fifo_transfer)  (void *opaque, void *dst, void *src, unsigned flags),
     69                        unsigned flags)
     70 {
     71    AVContainerFifo *cf;
     72 
     73    cf = av_mallocz(sizeof(*cf));
     74    if (!cf)
     75        return NULL;
     76 
     77    cf->opaque          = opaque;
     78    cf->container_alloc = container_alloc;
     79    cf->container_reset = container_reset;
     80    cf->container_free  = container_free;
     81    cf->fifo_transfer   = fifo_transfer;
     82 
     83    cf->fifo = av_fifo_alloc2(1, sizeof(void*), AV_FIFO_FLAG_AUTO_GROW);
     84    if (!cf->fifo)
     85        goto fail;
     86 
     87    cf->pool = av_refstruct_pool_alloc_ext(sizeof(void*), 0, cf,
     88                                           container_fifo_init_entry,
     89                                           container_fifo_reset_entry,
     90                                           container_fifo_free_entry,
     91                                           NULL);
     92    if (!cf->pool)
     93        goto fail;
     94 
     95    return cf;
     96 fail:
     97    av_container_fifo_free(&cf);
     98    return NULL;
     99 }
    100 
    101 void av_container_fifo_free(AVContainerFifo **pcf)
    102 {
    103    AVContainerFifo *cf;
    104 
    105    if (!*pcf)
    106        return;
    107 
    108    cf = *pcf;
    109 
    110    if (cf->fifo) {
    111        void *obj;
    112        while (av_fifo_read(cf->fifo, &obj, 1) >= 0)
    113            av_refstruct_unref(&obj);
    114        av_fifo_freep2(&cf->fifo);
    115    }
    116 
    117    av_refstruct_pool_uninit(&cf->pool);
    118 
    119    av_freep(pcf);
    120 }
    121 
    122 int av_container_fifo_read(AVContainerFifo *cf, void *obj, unsigned flags)
    123 {
    124    void **psrc;
    125    int ret;
    126 
    127    ret = av_fifo_read(cf->fifo, &psrc, 1);
    128    if (ret < 0)
    129        return ret;
    130 
    131    ret = cf->fifo_transfer(cf->opaque, obj, *psrc, flags);
    132    av_refstruct_unref(&psrc);
    133 
    134    return ret;
    135 }
    136 
    137 int av_container_fifo_peek(AVContainerFifo *cf, void **pdst, size_t offset)
    138 {
    139    void **pobj;
    140    int ret;
    141 
    142    ret = av_fifo_peek(cf->fifo, &pobj, 1, offset);
    143    if (ret < 0)
    144        return ret;
    145 
    146    *pdst = *pobj;
    147 
    148    return 0;
    149 }
    150 
    151 void av_container_fifo_drain(AVContainerFifo *cf, size_t nb_elems)
    152 {
    153    av_assert0(nb_elems <= av_fifo_can_read(cf->fifo));
    154    while (nb_elems--) {
    155        void **pobj;
    156        int ret = av_fifo_read(cf->fifo, &pobj, 1);
    157        av_assert0(ret >= 0);
    158        av_refstruct_unref(&pobj);
    159    }
    160 }
    161 
    162 int av_container_fifo_write(AVContainerFifo *cf, void *obj, unsigned flags)
    163 {
    164    void **pdst;
    165    int ret;
    166 
    167    pdst = av_refstruct_pool_get(cf->pool);
    168    if (!pdst)
    169        return AVERROR(ENOMEM);
    170 
    171    ret = cf->fifo_transfer(cf->opaque, *pdst, obj, flags);
    172    if (ret < 0)
    173        goto fail;
    174 
    175    ret = av_fifo_write(cf->fifo, &pdst, 1);
    176    if (ret < 0)
    177        goto fail;
    178 
    179    return 0;
    180 fail:
    181    av_refstruct_unref(&pdst);
    182    return ret;
    183 }
    184 
    185 size_t av_container_fifo_can_read(const AVContainerFifo *cf)
    186 {
    187    return av_fifo_can_read(cf->fifo);
    188 }
    189 
    190 static void *frame_alloc(void *opaque)
    191 {
    192    return av_frame_alloc();
    193 }
    194 
    195 static void frame_reset(void *opaque, void *obj)
    196 {
    197    av_frame_unref(obj);
    198 }
    199 
    200 static void frame_free(void *opaque, void *obj)
    201 {
    202    AVFrame *frame = obj;
    203    av_frame_free(&frame);
    204 }
    205 
    206 static int frame_transfer(void *opaque, void *dst, void *src, unsigned flags)
    207 {
    208    if (flags & AV_CONTAINER_FIFO_FLAG_REF)
    209        return av_frame_ref(dst, src);
    210 
    211    av_frame_move_ref(dst, src);
    212    return 0;
    213 }
    214 
    215 AVContainerFifo *av_container_fifo_alloc_avframe(unsigned flags)
    216 {
    217    return av_container_fifo_alloc(NULL, frame_alloc, frame_reset, frame_free,
    218                                   frame_transfer, 0);
    219 }