/* | |
* Generic frame queue | |
* Copyright (c) 2016 Nicolas George | |
* | |
* 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 | |
*/ | |
/** | |
* FFFrameQueue: simple AVFrame queue API | |
* | |
* Note: this API is not thread-safe. Concurrent access to the same queue | |
* must be protected by a mutex or any synchronization mechanism. | |
*/ | |
typedef struct FFFrameBucket { | |
AVFrame *frame; | |
} FFFrameBucket; | |
/** | |
* Structure to hold global options and statistics for frame queues. | |
* | |
* This structure is intended to allow implementing global control of the | |
* frame queues, including memory consumption caps. | |
* | |
* It is currently empty. | |
*/ | |
typedef struct FFFrameQueueGlobal { | |
char dummy; /* C does not allow empty structs */ | |
} FFFrameQueueGlobal; | |
/** | |
* Queue of AVFrame pointers. | |
*/ | |
typedef struct FFFrameQueue { | |
/** | |
* Array of allocated buckets, used as a circular buffer. | |
*/ | |
FFFrameBucket *queue; | |
/** | |
* Size of the array of buckets. | |
*/ | |
size_t allocated; | |
/** | |
* Tail of the queue. | |
* It is the index in the array of the next frame to take. | |
*/ | |
size_t tail; | |
/** | |
* Number of currently queued frames. | |
*/ | |
size_t queued; | |
/** | |
* Pre-allocated bucket for queues of size 1. | |
*/ | |
FFFrameBucket first_bucket; | |
/** | |
* Total number of frames entered in the queue. | |
*/ | |
uint64_t total_frames_head; | |
/** | |
* Total number of frames dequeued from the queue. | |
* queued = total_frames_head - total_frames_tail | |
*/ | |
uint64_t total_frames_tail; | |
/** | |
* Total number of samples entered in the queue. | |
*/ | |
uint64_t total_samples_head; | |
/** | |
* Total number of samples dequeued from the queue. | |
* queued_samples = total_samples_head - total_samples_tail | |
*/ | |
uint64_t total_samples_tail; | |
/** | |
* Indicate that samples are skipped | |
*/ | |
int samples_skipped; | |
} FFFrameQueue; | |
/** | |
* Init a global structure. | |
*/ | |
void ff_framequeue_global_init(FFFrameQueueGlobal *fqg); | |
/** | |
* Init a frame queue and attach it to a global structure. | |
*/ | |
void ff_framequeue_init(FFFrameQueue *fq, FFFrameQueueGlobal *fqg); | |
/** | |
* Free the queue and all queued frames. | |
*/ | |
void ff_framequeue_free(FFFrameQueue *fq); | |
/** | |
* Add a frame. | |
* @return >=0 or an AVERROR code. | |
*/ | |
int ff_framequeue_add(FFFrameQueue *fq, AVFrame *frame); | |
/** | |
* Take the first frame in the queue. | |
* Must not be used with empty queues. | |
*/ | |
AVFrame *ff_framequeue_take(FFFrameQueue *fq); | |
/** | |
* Access a frame in the queue, without removing it. | |
* The first frame is numbered 0; the designated frame must exist. | |
*/ | |
AVFrame *ff_framequeue_peek(FFFrameQueue *fq, size_t idx); | |
/** | |
* Get the number of queued frames. | |
*/ | |
static inline size_t ff_framequeue_queued_frames(const FFFrameQueue *fq) | |
{ | |
return fq->queued; | |
} | |
/** | |
* Get the number of queued samples. | |
*/ | |
static inline uint64_t ff_framequeue_queued_samples(const FFFrameQueue *fq) | |
{ | |
return fq->total_samples_head - fq->total_samples_tail; | |
} | |
/** | |
* Update the statistics after a frame accessed using ff_framequeue_peek() | |
* was modified. | |
* Currently used only as a marker. | |
*/ | |
static inline void ff_framequeue_update_peeked(FFFrameQueue *fq, size_t idx) | |
{ | |
} | |
/** | |
* Skip samples from the first frame in the queue. | |
* | |
* This function must be used when the first frame was accessed using | |
* ff_framequeue_peek() and samples were consumed from it. | |
* It adapts the data pointers and timestamps of the head frame to account | |
* for the skipped samples. | |
*/ | |
void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t samples, AVRational time_base); | |