| @@ -20,21 +20,22 @@ · 19 unmodified lines |
| 20 | 20 | |
| 21 | 21 | /** |
| 22 | 22 | * @file |
| 23 | | − * FIFO buffering video filter |
| 23 | + * FIFO buffering filter |
| 24 | 24 | */ |
| 25 | 25 | |
| 26 | +#include "audio.h" |
| 26 | 27 | #include "avfilter.h" |
| 27 | 28 | #include "internal.h" |
| 28 | 29 | #include "video.h" |
| 29 | 30 | |
| 30 | | −typedef struct BufPic { |
| 31 | | − AVFilterBufferRef *picref; |
| 32 | | − struct BufPic *next; |
| 33 | | −} BufPic; |
| 31 | +typedef struct Buf { |
| 32 | + AVFilterBufferRef *buf; |
| 33 | + struct Buf *next; |
| 34 | +} Buf; |
| 34 | 35 | |
| 35 | 36 | typedef struct { |
| 36 | | − BufPic root; |
| 37 | | − BufPic *last; ///< last buffered picture |
| 37 | + Buf root; |
| 38 | + Buf *last; ///< last buffered frame |
| 38 | 39 | } FifoContext; |
| 39 | 40 | |
| 40 | 41 | static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
| @@ -49,22 +50,22 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) · 8 unmodified lines |
| 49 | 50 | static av_cold void uninit(AVFilterContext *ctx) |
| 50 | 51 | { |
| 51 | 52 | FifoContext *fifo = ctx->priv; |
| 52 | | − BufPic *pic, *tmp; |
| 53 | + Buf *buf, *tmp; |
| 53 | 54 | |
| 54 | | − for (pic = fifo->root.next; pic; pic = tmp) { |
| 55 | | − tmp = pic->next; |
| 56 | | − avfilter_unref_buffer(pic->picref); |
| 57 | | − av_free(pic); |
| 55 | + for (buf = fifo->root.next; buf; buf = tmp) { |
| 56 | + tmp = buf->next; |
| 57 | + avfilter_unref_buffer(buf->buf); |
| 58 | + av_free(buf); |
| 58 | 59 | } |
| 59 | 60 | } |
| 60 | 61 | |
| 61 | | −static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) |
| 62 | +static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) |
| 62 | 63 | { |
| 63 | 64 | FifoContext *fifo = inlink->dst->priv; |
| 64 | 65 | |
| 65 | | − fifo->last->next = av_mallocz(sizeof(BufPic)); |
| 66 | + fifo->last->next = av_mallocz(sizeof(Buf)); |
| 66 | 67 | fifo->last = fifo->last->next; |
| 67 | | − fifo->last->picref = picref; |
| 68 | + fifo->last->buf = buf; |
| 68 | 69 | } |
| 69 | 70 | |
| 70 | 71 | static void end_frame(AVFilterLink *inlink) { } |
| @@ -74,7 +75,7 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) { } · 3 unmodified lines |
| 74 | 75 | static int request_frame(AVFilterLink *outlink) |
| 75 | 76 | { |
| 76 | 77 | FifoContext *fifo = outlink->src->priv; |
| 77 | | − BufPic *tmp; |
| 78 | + Buf *tmp; |
| 78 | 79 | int ret; |
| 79 | 80 | |
| 80 | 81 | if (!fifo->root.next) { |
| @@ -84,9 +85,18 @@ static int request_frame(AVFilterLink *outlink) · 3 unmodified lines |
| 84 | 85 | |
| 85 | 86 | /* by doing this, we give ownership of the reference to the next filter, |
| 86 | 87 | * so we don't have to worry about dereferencing it ourselves. */ |
| 87 | | − ff_start_frame(outlink, fifo->root.next->picref); |
| 88 | | − ff_draw_slice (outlink, 0, outlink->h, 1); |
| 89 | | − ff_end_frame (outlink); |
| 88 | + switch (outlink->type) { |
| 89 | + case AVMEDIA_TYPE_VIDEO: |
| 90 | + ff_start_frame(outlink, fifo->root.next->buf); |
| 91 | + ff_draw_slice (outlink, 0, outlink->h, 1); |
| 92 | + ff_end_frame (outlink); |
| 93 | + break; |
| 94 | + case AVMEDIA_TYPE_AUDIO: |
| 95 | + ff_filter_samples(outlink, fifo->root.next->buf); |
| 96 | + break; |
| 97 | + default: |
| 98 | + return AVERROR(EINVAL); |
| 99 | + } |
| 90 | 100 | |
| 91 | 101 | if (fifo->last == fifo->root.next) |
| 92 | 102 | fifo->last = &fifo->root; |
| @@ -109,7 +119,7 @@ AVFilter avfilter_vf_fifo = { · 16 unmodified lines |
| 109 | 119 | .inputs = (AVFilterPad[]) {{ .name = "default", |
| 110 | 120 | .type = AVMEDIA_TYPE_VIDEO, |
| 111 | 121 | .get_video_buffer= ff_null_get_video_buffer, |
| 112 | | − .start_frame = start_frame, |
| 122 | + .start_frame = add_to_queue, |
| 113 | 123 | .draw_slice = draw_slice, |
| 114 | 124 | .end_frame = end_frame, |
| 115 | 125 | .rej_perms = AV_PERM_REUSE2, }, |
| @@ -119,3 +129,24 @@ AVFilter avfilter_vf_fifo = { · 3 unmodified lines |
| 119 | 129 | .request_frame = request_frame, }, |
| 120 | 130 | { .name = NULL}}, |
| 121 | 131 | }; |
| 132 | + |
| 133 | +AVFilter avfilter_af_afifo = { |
| 134 | + .name = "afifo", |
| 135 | + .description = NULL_IF_CONFIG_SMALL("Buffer input frames and send them when they are requested."), |
| 136 | + |
| 137 | + .init = init, |
| 138 | + .uninit = uninit, |
| 139 | + |
| 140 | + .priv_size = sizeof(FifoContext), |
| 141 | + |
| 142 | + .inputs = (AVFilterPad[]) {{ .name = "default", |
| 143 | + .type = AVMEDIA_TYPE_AUDIO, |
| 144 | + .get_audio_buffer = ff_null_get_audio_buffer, |
| 145 | + .filter_samples = add_to_queue, |
| 146 | + .rej_perms = AV_PERM_REUSE2, }, |
| 147 | + { .name = NULL}}, |
| 148 | + .outputs = (AVFilterPad[]) {{ .name = "default", |
| 149 | + .type = AVMEDIA_TYPE_AUDIO, |
| 150 | + .request_frame = request_frame, }, |
| 151 | + { .name = NULL}}, |
| 152 | +}; |