]> git.sesse.net Git - ffmpeg/blob - libavfilter/buffer.c
aresample: add code to flush the internal swr buffer.
[ffmpeg] / libavfilter / buffer.c
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include "libavutil/audioconvert.h"
20 #include "libavutil/avassert.h"
21 #include "libavcodec/avcodec.h"
22
23 #include "avfilter.h"
24 #include "internal.h"
25 #include "avcodec.h"
26
27 void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr)
28 {
29     if (ptr->extended_data != ptr->data)
30         av_freep(&ptr->extended_data);
31     av_free(ptr->data[0]);
32     av_free(ptr);
33 }
34
35 AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
36 {
37     AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef));
38     if (!ret)
39         return NULL;
40     *ret = *ref;
41     if (ref->type == AVMEDIA_TYPE_VIDEO) {
42         ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps));
43         if (!ret->video) {
44             av_free(ret);
45             return NULL;
46         }
47         *ret->video = *ref->video;
48         ret->extended_data = ret->data;
49     } else if (ref->type == AVMEDIA_TYPE_AUDIO) {
50         ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps));
51         if (!ret->audio) {
52             av_free(ret);
53             return NULL;
54         }
55         *ret->audio = *ref->audio;
56
57         if (ref->extended_data && ref->extended_data != ref->data) {
58             int nb_channels = av_get_channel_layout_nb_channels(ref->audio->channel_layout);
59             if (!(ret->extended_data = av_malloc(sizeof(*ret->extended_data) *
60                                                  nb_channels))) {
61                 av_freep(&ret->audio);
62                 av_freep(&ret);
63                 return NULL;
64             }
65             memcpy(ret->extended_data, ref->extended_data,
66                    sizeof(*ret->extended_data) * nb_channels);
67         } else
68             ret->extended_data = ret->data;
69     }
70     ret->perms &= pmask;
71     ret->buf->refcount ++;
72     return ret;
73 }
74
75 void ff_free_pool(AVFilterPool *pool)
76 {
77     int i;
78
79     av_assert0(pool->refcount > 0);
80
81     for (i = 0; i < POOL_SIZE; i++) {
82         if (pool->pic[i]) {
83             AVFilterBufferRef *picref = pool->pic[i];
84             /* free buffer: picrefs stored in the pool are not
85              * supposed to contain a free callback */
86             av_assert0(!picref->buf->refcount);
87             av_freep(&picref->buf->data[0]);
88             av_freep(&picref->buf);
89
90             av_freep(&picref->audio);
91             av_freep(&picref->video);
92             av_freep(&pool->pic[i]);
93             pool->count--;
94         }
95     }
96     pool->draining = 1;
97
98     if (!--pool->refcount) {
99         av_assert0(!pool->count);
100         av_free(pool);
101     }
102 }
103
104 static void store_in_pool(AVFilterBufferRef *ref)
105 {
106     int i;
107     AVFilterPool *pool= ref->buf->priv;
108
109     av_assert0(ref->buf->data[0]);
110     av_assert0(pool->refcount>0);
111
112     if (pool->count == POOL_SIZE) {
113         AVFilterBufferRef *ref1 = pool->pic[0];
114         av_freep(&ref1->video);
115         av_freep(&ref1->audio);
116         av_freep(&ref1->buf->data[0]);
117         av_freep(&ref1->buf);
118         av_free(ref1);
119         memmove(&pool->pic[0], &pool->pic[1], sizeof(void*)*(POOL_SIZE-1));
120         pool->count--;
121         pool->pic[POOL_SIZE-1] = NULL;
122     }
123
124     for (i = 0; i < POOL_SIZE; i++) {
125         if (!pool->pic[i]) {
126             pool->pic[i] = ref;
127             pool->count++;
128             break;
129         }
130     }
131     if (pool->draining) {
132         ff_free_pool(pool);
133     } else
134         --pool->refcount;
135 }
136
137 void avfilter_unref_buffer(AVFilterBufferRef *ref)
138 {
139     if (!ref)
140         return;
141     av_assert0(ref->buf->refcount > 0);
142     if (!(--ref->buf->refcount)) {
143         if (!ref->buf->free) {
144             store_in_pool(ref);
145             return;
146         }
147         ref->buf->free(ref->buf);
148     }
149     if (ref->extended_data != ref->data)
150         av_freep(&ref->extended_data);
151     av_freep(&ref->video);
152     av_freep(&ref->audio);
153     av_free(ref);
154 }
155
156 void avfilter_unref_bufferp(AVFilterBufferRef **ref)
157 {
158     avfilter_unref_buffer(*ref);
159     *ref = NULL;
160 }
161
162 int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src)
163 {
164     dst->pts    = src->pts;
165     dst->pos    = src->pkt_pos;
166     dst->format = src->format;
167
168     switch (dst->type) {
169     case AVMEDIA_TYPE_VIDEO:
170         dst->video->w                   = src->width;
171         dst->video->h                   = src->height;
172         dst->video->sample_aspect_ratio = src->sample_aspect_ratio;
173         dst->video->interlaced          = src->interlaced_frame;
174         dst->video->top_field_first     = src->top_field_first;
175         dst->video->key_frame           = src->key_frame;
176         dst->video->pict_type           = src->pict_type;
177         break;
178     case AVMEDIA_TYPE_AUDIO:
179         dst->audio->sample_rate         = src->sample_rate;
180         dst->audio->channel_layout      = src->channel_layout;
181         break;
182     default:
183         return AVERROR(EINVAL);
184     }
185
186     return 0;
187 }
188
189 int avfilter_copy_buf_props(AVFrame *dst, const AVFilterBufferRef *src)
190 {
191     int planes, nb_channels;
192
193     memcpy(dst->data, src->data, sizeof(dst->data));
194     memcpy(dst->linesize, src->linesize, sizeof(dst->linesize));
195
196     dst->pts     = src->pts;
197     dst->format  = src->format;
198
199     switch (src->type) {
200     case AVMEDIA_TYPE_VIDEO:
201         dst->width               = src->video->w;
202         dst->height              = src->video->h;
203         dst->sample_aspect_ratio = src->video->sample_aspect_ratio;
204         dst->interlaced_frame    = src->video->interlaced;
205         dst->top_field_first     = src->video->top_field_first;
206         dst->key_frame           = src->video->key_frame;
207         dst->pict_type           = src->video->pict_type;
208         break;
209     case AVMEDIA_TYPE_AUDIO:
210         nb_channels = av_get_channel_layout_nb_channels(src->audio->channel_layout);
211         planes      = av_sample_fmt_is_planar(src->format) ? nb_channels : 1;
212
213         if (planes > FF_ARRAY_ELEMS(dst->data)) {
214             dst->extended_data = av_mallocz(planes * sizeof(*dst->extended_data));
215             if (!dst->extended_data)
216                 return AVERROR(ENOMEM);
217             memcpy(dst->extended_data, src->extended_data,
218                    planes * sizeof(dst->extended_data));
219         } else
220             dst->extended_data = dst->data;
221
222         dst->sample_rate         = src->audio->sample_rate;
223         dst->channel_layout      = src->audio->channel_layout;
224         dst->nb_samples          = src->audio->nb_samples;
225         break;
226     default:
227         return AVERROR(EINVAL);
228     }
229
230     return 0;
231 }
232
233 void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *src)
234 {
235     // copy common properties
236     dst->pts             = src->pts;
237     dst->pos             = src->pos;
238
239     switch (src->type) {
240     case AVMEDIA_TYPE_VIDEO: *dst->video = *src->video; break;
241     case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break;
242     default: break;
243     }
244 }