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
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  */
22 #include "libavutil/avassert.h"
23 #include "framequeue.h"
25 static inline FFFrameBucket *bucket(FFFrameQueue *fq, size_t idx)
26 {
27  return &fq->queue[(fq->tail + idx) & (fq->allocated - 1)];
28 }
31 {
32 }
35 {
36 #if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
37  uint64_t nb_samples = 0;
38  size_t i;
41  for (i = 0; i < fq->queued; i++)
44 #endif
45 }
48 {
49  fq->queue = &fq->first_bucket;
50  fq->allocated = 1;
51 }
54 {
55  while (fq->queued) {
58  }
59  if (fq->queue != &fq->first_bucket)
60  av_freep(&fq->queue);
61 }
64 {
68  if (fq->queued == fq->allocated) {
69  if (fq->allocated == 1) {
70  size_t na = 8;
71  FFFrameBucket *nq = av_realloc_array(NULL, na, sizeof(*nq));
72  if (!nq)
73  return AVERROR(ENOMEM);
74  nq[0] = fq->queue[0];
75  fq->queue = nq;
76  fq->allocated = na;
77  } else {
78  size_t na = fq->allocated << 1;
79  FFFrameBucket *nq = av_realloc_array(fq->queue, na, sizeof(*nq));
80  if (!nq)
81  return AVERROR(ENOMEM);
82  if (fq->tail + fq->queued > fq->allocated)
83  memmove(nq + fq->allocated, nq,
84  (fq->tail + fq->queued - fq->allocated) * sizeof(*nq));
85  fq->queue = nq;
86  fq->allocated = na;
87  }
88  }
89  b = bucket(fq, fq->queued);
90  b->frame = frame;
91  fq->queued++;
92  fq->total_frames_head++;
93  fq->total_samples_head += frame->nb_samples;
95  return 0;
96 }
99 {
100  FFFrameBucket *b;
102  check_consistency(fq);
103  av_assert1(fq->queued);
104  b = bucket(fq, 0);
105  fq->queued--;
106  fq->tail++;
107  fq->tail &= fq->allocated - 1;
108  fq->total_frames_tail++;
109  fq->total_samples_tail += b->frame->nb_samples;
110  fq->samples_skipped = 0;
111  check_consistency(fq);
112  return b->frame;
113 }
116 {
117  FFFrameBucket *b;
119  check_consistency(fq);
120  av_assert1(idx < fq->queued);
121  b = bucket(fq, idx);
122  check_consistency(fq);
123  return b->frame;
124 }
127 {
128  FFFrameBucket *b;
129  size_t bytes;
130  int planar, planes, i;
132  check_consistency(fq);
133  av_assert1(fq->queued);
134  b = bucket(fq, 0);
135  av_assert1(samples < b->frame->nb_samples);
136  planar = av_sample_fmt_is_planar(b->frame->format);
137  planes = planar ? b->frame->ch_layout.nb_channels : 1;
138  bytes = samples * av_get_bytes_per_sample(b->frame->format);
139  if (!planar)
140  bytes *= b->frame->ch_layout.nb_channels;
141  if (b->frame->pts != AV_NOPTS_VALUE)
142  b->frame->pts += av_rescale_q(samples, av_make_q(1, b->frame->sample_rate), time_base);
143  b->frame->nb_samples -= samples;
144  b->frame->linesize[0] -= bytes;
145  for (i = 0; i < planes; i++)
146  b->frame->extended_data[i] += bytes;
147  for (i = 0; i < planes && i < AV_NUM_DATA_POINTERS; i++)
148  b->frame->data[i] = b->frame->extended_data[i];
150  fq->samples_skipped = 1;
152 }
static const struct @346 planes[]
FFFrameBucket first_bucket
Pre-allocated bucket for queues of size 1.
Definition: framequeue.h:79
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
AVFrame * frame
Definition: framequeue.h:35
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:99
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
#define b
Definition: input.c:41
int nb_samples
Definition: framepool.c:41
FFFrameBucket * queue
Array of allocated buckets, used as a circular buffer.
Definition: framequeue.h:58
void ff_framequeue_init(FFFrameQueue *fq, FFFrameQueueGlobal *fqg)
Init a frame queue and attach it to a global structure.
Definition: framequeue.c:47
size_t allocated
Size of the array of buckets.
Definition: framequeue.h:63
FFFrameQueue: simple AVFrame queue API.
Definition: framequeue.h:34
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:126
uint64_t total_samples_tail
Total number of samples dequeued from the queue.
Definition: framequeue.h:101
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
Definition: audioconvert.c:56
size_t queued
Number of currently queued frames.
Definition: framequeue.h:74
int samples_skipped
Indicate that samples are skipped.
Definition: framequeue.h:106
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:215
Structure to hold global options and statistics for frame queues.
Definition: framequeue.h:46
static FFFrameBucket * bucket(FFFrameQueue *fq, size_t idx)
Definition: framequeue.c:25
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:114
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
AVFrame * ff_framequeue_take(FFFrameQueue *fq)
Take the first frame in the queue.
Definition: framequeue.c:98
#define NULL
Definition: coverity.c:32
int ff_framequeue_add(FFFrameQueue *fq, AVFrame *frame)
Add a frame.
Definition: framequeue.c:63
void ff_framequeue_free(FFFrameQueue *fq)
Free the queue and all queued frames.
Definition: framequeue.c:53
Rational number (pair of numerator and denominator).
Definition: rational.h:58
uint64_t total_frames_head
Total number of frames entered in the queue.
Definition: framequeue.h:84
Queue of AVFrame pointers.
Definition: framequeue.h:53
Definition: h264pred_template.c:425
Definition: frame.h:331
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
Undefined timestamp value.
Definition: avutil.h:248
size_t tail
Tail of the queue.
Definition: framequeue.h:69
AVFrame * ff_framequeue_peek(FFFrameQueue *fq, size_t idx)
Access a frame in the queue, without removing it.
Definition: framequeue.c:115
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:410
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
static void check_consistency(FFFrameQueue *fq)
Definition: framequeue.c:34
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:108
uint64_t total_samples_head
Total number of samples entered in the queue.
Definition: framequeue.h:95
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:53
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
uint64_t total_frames_tail
Total number of frames dequeued from the queue.
Definition: framequeue.h:90
void ff_framequeue_global_init(FFFrameQueueGlobal *fqg)
Init a global structure.
Definition: framequeue.c:30
Filter the word “frame” indicates either a video frame or a group of audio samples
Definition: filter_design.txt:8
#define av_freep(p)
Definition: tableprint_vlc.h:34
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:164