tor-browser

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

progressframe.h (6519B)


      1 /*
      2 * Copyright (c) 2022 Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
      3 *
      4 * This file is part of FFmpeg.
      5 *
      6 * FFmpeg is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * FFmpeg is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with FFmpeg; if not, write to the Free Software
     18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19 */
     20 
     21 #ifndef AVCODEC_PROGRESSFRAME_H
     22 #define AVCODEC_PROGRESSFRAME_H
     23 
     24 /**
     25 * ProgressFrame is an API to easily share frames without an underlying
     26 * av_frame_ref(). Its main usecase is in frame-threading scenarios,
     27 * yet it could also be used for purely single-threaded decoders that
     28 * want to keep multiple references to the same frame.
     29 *
     30 * The underlying principle behind the API is that all that is needed
     31 * to share a frame is a reference count and a contract between all parties.
     32 * The ProgressFrame provides the reference count and the frame is unreferenced
     33 * via ff_thread_release_buffer() when the reference count reaches zero.
     34 *
     35 * In order to make this API also usable for frame-threaded decoders it also
     36 * provides a way of exchanging simple information about the state of
     37 * decoding the frame via ff_thread_progress_report() and
     38 * ff_thread_progress_await().
     39 *
     40 * The typical contract for frame-threaded decoders is as follows:
     41 * Thread A initializes a ProgressFrame via ff_thread_progress_get_buffer()
     42 * (which already allocates the AVFrame's data buffers), calls
     43 * ff_thread_finish_setup() and starts decoding the frame. Later threads
     44 * receive a reference to this frame, which means they get a pointer
     45 * to the AVFrame and the internal reference count gets incremented.
     46 * Later threads whose frames use A's frame as reference as well as
     47 * the thread that will eventually output A's frame will wait for
     48 * progress on said frame reported by A. As soon as A has reported
     49 * that it has finished decoding its frame, it must no longer modify it
     50 * (neither its data nor its properties).
     51 *
     52 * Because creating a reference with this API does not involve reads
     53 * from the actual AVFrame, the decoding thread may modify the properties
     54 * (i.e. non-data fields) until it has indicated to be done with this
     55 * frame. This is important for e.g. propagating decode_error_flags;
     56 * it also allows to add side-data late.
     57 */
     58 
     59 struct AVCodecContext;
     60 
     61 /**
     62 * The ProgressFrame structure.
     63 * Hint: It is guaranteed that the AVFrame pointer is at the start
     64 *       of ProgressFrame. This allows to use an unnamed
     65 *       union {
     66 *            struct {
     67 *                AVFrame *f;
     68 *            };
     69 *            ProgressFrame pf;
     70 *       };
     71 *       to simplify accessing the embedded AVFrame.
     72 */
     73 typedef struct ProgressFrame {
     74    struct AVFrame *f;
     75    struct ProgressInternal *progress;
     76 } ProgressFrame;
     77 
     78 /**
     79 * Notify later decoding threads when part of their reference frame is ready.
     80 * Call this when some part of the frame is finished decoding.
     81 * Later calls with lower values of progress have no effect.
     82 *
     83 * @param f The frame being decoded.
     84 * @param progress Value, in arbitrary units, of how much of the frame has decoded.
     85 *
     86 * @warning Calling this on a blank ProgressFrame causes undefined behaviour
     87 */
     88 void ff_progress_frame_report(ProgressFrame *f, int progress);
     89 
     90 /**
     91 * Wait for earlier decoding threads to finish reference frames.
     92 * Call this before accessing some part of a frame, with a given
     93 * value for progress, and it will return after the responsible decoding
     94 * thread calls ff_thread_progress_report() with the same or
     95 * higher value for progress.
     96 *
     97 * @param f The frame being referenced.
     98 * @param progress Value, in arbitrary units, to wait for.
     99 *
    100 * @warning Calling this on a blank ProgressFrame causes undefined behaviour
    101 */
    102 void ff_progress_frame_await(const ProgressFrame *f, int progress);
    103 
    104 /**
    105 * This function allocates ProgressFrame.f
    106 * May be called before ff_progress_frame_get_buffer() in the cases where the
    107 * AVFrame needs to be accessed before the ff_thread_get_buffer() call in
    108 * ff_progress_frame_alloc().
    109 *
    110 * @note: This must only be called by codecs with the
    111 *        FF_CODEC_CAP_USES_PROGRESSFRAMES internal cap.
    112 */
    113 int ff_progress_frame_alloc(struct AVCodecContext *avctx, ProgressFrame *f);
    114 
    115 /**
    116 * This function sets up the ProgressFrame, i.e. allocates ProgressFrame.f
    117 * if needed, and also calls ff_thread_get_buffer() on the frame.
    118 *
    119 * @note: This must only be called by codecs with the
    120 *        FF_CODEC_CAP_USES_PROGRESSFRAMES internal cap.
    121 * @see ff_progress_frame_alloc
    122 */
    123 int ff_progress_frame_get_buffer(struct AVCodecContext *avctx,
    124                                 ProgressFrame *f, int flags);
    125 
    126 /**
    127 * Give up a reference to the underlying frame contained in a ProgressFrame
    128 * and reset the ProgressFrame, setting all pointers to NULL.
    129 *
    130 * @note: This implies that when using this API the check for whether
    131 *        a frame exists is by checking ProgressFrame.f and not
    132 *        ProgressFrame.f->data[0] or ProgressFrame.f->buf[0].
    133 */
    134 void ff_progress_frame_unref(ProgressFrame *f);
    135 
    136 /**
    137 * Set dst->f to src->f and make dst a co-owner of src->f.
    138 * dst can then be used to wait on progress of the underlying frame.
    139 *
    140 * @note: There is no underlying av_frame_ref() here. dst->f and src->f
    141 *        really point to the same AVFrame. Typically this means that
    142 *        the decoding thread is allowed to set all the properties of
    143 *        the AVFrame until it has indicated to have finished decoding.
    144 *        Afterwards later threads may read all of these fields.
    145 *        Access to the frame's data is governed by
    146 *        ff_thread_progress_report/await().
    147 */
    148 void ff_progress_frame_ref(ProgressFrame *dst, const ProgressFrame *src);
    149 
    150 /**
    151 * Do nothing if dst and src already refer to the same AVFrame;
    152 * otherwise unreference dst and if src is not blank, put a reference
    153 * to src's AVFrame in its place (in case src is not blank).
    154 */
    155 void ff_progress_frame_replace(ProgressFrame *dst, const ProgressFrame *src);
    156 
    157 #endif /* AVCODEC_PROGRESSFRAME_H */