FFmpeg
Loading...
Searching...
No Matches
framequeue.c
Go to the documentation of this file.
1/*
2 * Generic frame queue
3 * Copyright (c) 2016 Nicolas George
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavutil/avassert.h"
23#include "libavutil/mem.h"
24#include "framequeue.h"
25
26static inline FFFrameBucket *bucket(FFFrameQueue *fq, size_t idx)
27{
28 return &fq->queue[(fq->tail + idx) & (fq->allocated - 1)];
29}
30
32{
33 fqg->max_queued = SIZE_MAX;
34 fqg->queued = 0;
35}
36
38{
39#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
40 uint64_t nb_samples = 0;
41 size_t i;
42
44 for (i = 0; i < fq->queued; i++)
45 nb_samples += bucket(fq, i)->frame->nb_samples;
46 av_assert0(nb_samples == fq->total_samples_head - fq->total_samples_tail);
47#endif
48}
49
51{
52 fq->queue = &fq->first_bucket;
53 fq->allocated = 1;
54 fq->global = fqg;
55}
56
58{
59 while (fq->queued) {
62 }
63 if (fq->queue != &fq->first_bucket)
64 av_freep(&fq->queue);
65}
66
68{
70
72 if (fq->global->queued >= fq->global->max_queued)
73 return AVERROR(ENOMEM);
74 if (fq->queued == fq->allocated) {
75 if (fq->allocated == 1) {
76 size_t na = 8;
77 FFFrameBucket *nq = av_realloc_array(NULL, na, sizeof(*nq));
78 if (!nq)
79 return AVERROR(ENOMEM);
80 nq[0] = fq->queue[0];
81 fq->queue = nq;
82 fq->allocated = na;
83 } else {
84 size_t na = fq->allocated << 1;
85 FFFrameBucket *nq = av_realloc_array(fq->queue, na, sizeof(*nq));
86 if (!nq)
87 return AVERROR(ENOMEM);
88 if (fq->tail)
89 memmove(nq + fq->allocated, nq, fq->tail * sizeof(*nq));
90 fq->queue = nq;
91 fq->allocated = na;
92 }
93 }
94 b = bucket(fq, fq->queued);
95 b->frame = frame;
96 fq->queued++;
97 fq->global->queued++;
99 fq->total_samples_head += frame->nb_samples;
101 return 0;
102}
103
105{
107
109 av_assert1(fq->queued);
110 b = bucket(fq, 0);
111 fq->queued--;
112 fq->global->queued--;
113 fq->tail++;
114 fq->tail &= fq->allocated - 1;
115 fq->total_frames_tail++;
116 fq->total_samples_tail += b->frame->nb_samples;
117 fq->samples_skipped = 0;
119 return b->frame;
120}
121
123{
125
127 av_assert1(idx < fq->queued);
128 b = bucket(fq, idx);
130 return b->frame;
131}
132
133void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t samples, AVRational time_base)
134{
136 size_t bytes;
137 int planar, planes, i;
138
140 av_assert1(fq->queued);
141 b = bucket(fq, 0);
142 av_assert1(samples < b->frame->nb_samples);
143 planar = av_sample_fmt_is_planar(b->frame->format);
144 planes = planar ? b->frame->ch_layout.nb_channels : 1;
145 bytes = samples * av_get_bytes_per_sample(b->frame->format);
146 if (!planar)
147 bytes *= b->frame->ch_layout.nb_channels;
148 if (b->frame->pts != AV_NOPTS_VALUE)
149 b->frame->pts += av_rescale_q(samples, av_make_q(1, b->frame->sample_rate), time_base);
150 b->frame->nb_samples -= samples;
151 b->frame->linesize[0] -= bytes;
152 for (i = 0; i < planes; i++)
153 b->frame->extended_data[i] += bytes;
154 for (i = 0; i < planes && i < AV_NUM_DATA_POINTERS; i++)
155 b->frame->data[i] = b->frame->extended_data[i];
156 fq->total_samples_tail += samples;
157 fq->samples_skipped = 1;
159}
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi - 0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi > >8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1<< 16)) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi > >24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi > >56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0f/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(UINT64_C(1)<< 63))) #define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={ FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64), };static void cpy1(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, len);} static void cpy2(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 2 *len);} static void cpy4(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 4 *len);} static void cpy8(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 8 *len);} AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags) { AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){ in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);} ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map) { switch(av_get_bytes_per_sample(in_fmt)){ case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;} } return ctx;} void swri_audio_convert_free(AudioConvert **ctx) { av_freep(ctx);} int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len) { int ch;int off=0;const int os=(out->planar ? 1 :out->ch_count) *out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask) { int planes=in->planar ? in->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;} if(ctx->out_simd_align_mask) { int planes=out->planar ? out->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;} if(ctx->simd_f &&!ctx->ch_map &&!misaligned){ off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){ if(out->planar==in->planar){ int planes=out->planar ? out->ch_count :1;for(ch=0;ch< planes;ch++){ ctx->simd_f(out->ch+ch,(const uint8_t **) in->ch+ch, off *(out-> planar
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define NULL
Definition coverity.c:32
static AVFrame * frame
#define AV_NUM_DATA_POINTERS
Definition frame.h:473
AVFrame * ff_framequeue_take(FFFrameQueue *fq)
Take the first frame in the queue.
Definition framequeue.c:104
void ff_framequeue_init(FFFrameQueue *fq, FFFrameQueueGlobal *fqg)
Init a frame queue and attach it to a global structure.
Definition framequeue.c:50
int ff_framequeue_add(FFFrameQueue *fq, AVFrame *frame)
Add a frame.
Definition framequeue.c:67
void ff_framequeue_free(FFFrameQueue *fq)
Free the queue and all queued frames.
Definition framequeue.c:57
void ff_framequeue_global_init(FFFrameQueueGlobal *fqg)
Init a global structure.
Definition framequeue.c:31
AVFrame * ff_framequeue_peek(FFFrameQueue *fq, size_t idx)
Access a frame in the queue, without removing it.
Definition framequeue.c:122
void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t samples, AVRational time_base)
Skip samples from the first frame in the queue.
Definition framequeue.c:133
static void check_consistency(FFFrameQueue *fq)
Definition framequeue.c:37
static FFFrameBucket * bucket(FFFrameQueue *fq, size_t idx)
Definition framequeue.c:26
static void ff_framequeue_update_peeked(FFFrameQueue *fq, size_t idx)
Update the statistics after a frame accessed using ff_framequeue_peek() was modified.
Definition framequeue.h:176
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition rational.h:71
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition mem.c:217
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition samplefmt.c:114
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition samplefmt.c:108
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define b
Definition input.c:43
static const struct @257111027162314367033347246032313251342043035002 planes[]
Memory handling functions.
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int nb_samples
number of audio samples (per channel) described by this frame
Definition frame.h:552
Rational number (pair of numerator and denominator).
Definition rational.h:58
FFFrameQueue: simple AVFrame queue API.
Definition framequeue.h:34
AVFrame * frame
Definition framequeue.h:35
Structure to hold global options and statistics for frame queues.
Definition framequeue.h:44
size_t queued
Total number of queued frames in the queues combined.
Definition framequeue.h:54
size_t max_queued
Maximum number of allowed frames in the queues combined.
Definition framequeue.h:49
Queue of AVFrame pointers.
Definition framequeue.h:60
size_t tail
Tail of the queue.
Definition framequeue.h:81
size_t allocated
Size of the array of buckets.
Definition framequeue.h:75
FFFrameQueueGlobal * global
Pointer to the global frame queue struct holding statistics and limits.
Definition framequeue.h:65
int samples_skipped
Indicate that samples are skipped.
Definition framequeue.h:118
size_t queued
Number of currently queued frames.
Definition framequeue.h:86
uint64_t total_samples_tail
Total number of samples dequeued from the queue.
Definition framequeue.h:113
uint64_t total_samples_head
Total number of samples entered in the queue.
Definition framequeue.h:107
FFFrameBucket first_bucket
Pre-allocated bucket for queues of size 1.
Definition framequeue.h:91
uint64_t total_frames_head
Total number of frames entered in the queue.
Definition framequeue.h:96
uint64_t total_frames_tail
Total number of frames dequeued from the queue.
Definition framequeue.h:102
FFFrameBucket * queue
Array of allocated buckets, used as a circular buffer.
Definition framequeue.h:70
#define av_freep(p)