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 */