515 | 520 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,189 @@ |
0 |
+/* |
|
1 |
+ * This file is part of FFmpeg. |
|
2 |
+ * |
|
3 |
+ * Copyright (c) 2015 Matthieu Bouron <matthieu.bouron stupeflix.com> |
|
4 |
+ * |
|
5 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
7 |
+ * License as published by the Free Software Foundation; either |
|
8 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
9 |
+ * |
|
10 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
+ * Lesser General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
16 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+#include "framepool.h" |
|
21 |
+#include "libavutil/avassert.h" |
|
22 |
+#include "libavutil/buffer.h" |
|
23 |
+#include "libavutil/frame.h" |
|
24 |
+#include "libavutil/imgutils.h" |
|
25 |
+#include "libavutil/mem.h" |
|
26 |
+#include "libavutil/pixfmt.h" |
|
27 |
+ |
|
28 |
+struct FFVideoFramePool { |
|
29 |
+ |
|
30 |
+ int width; |
|
31 |
+ int height; |
|
32 |
+ int format; |
|
33 |
+ int align; |
|
34 |
+ int linesize[4]; |
|
35 |
+ AVBufferPool *pools[4]; |
|
36 |
+ |
|
37 |
+}; |
|
38 |
+ |
|
39 |
+FFVideoFramePool *ff_video_frame_pool_init(AVBufferRef* (*alloc)(int size), |
|
40 |
+ int width, |
|
41 |
+ int height, |
|
42 |
+ enum AVPixelFormat format, |
|
43 |
+ int align) |
|
44 |
+{ |
|
45 |
+ int i, ret; |
|
46 |
+ FFVideoFramePool *pool; |
|
47 |
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); |
|
48 |
+ |
|
49 |
+ if (!desc) |
|
50 |
+ return NULL; |
|
51 |
+ |
|
52 |
+ pool = av_mallocz(sizeof(FFVideoFramePool)); |
|
53 |
+ if (!pool) |
|
54 |
+ return NULL; |
|
55 |
+ |
|
56 |
+ pool->width = width; |
|
57 |
+ pool->height = height; |
|
58 |
+ pool->format = format; |
|
59 |
+ pool->align = align; |
|
60 |
+ |
|
61 |
+ if ((ret = av_image_check_size(width, height, 0, NULL)) < 0) { |
|
62 |
+ goto fail; |
|
63 |
+ } |
|
64 |
+ |
|
65 |
+ if (!pool->linesize[0]) { |
|
66 |
+ for(i = 1; i <= align; i += i) { |
|
67 |
+ ret = av_image_fill_linesizes(pool->linesize, pool->format, |
|
68 |
+ FFALIGN(pool->width, i)); |
|
69 |
+ if (ret < 0) { |
|
70 |
+ goto fail; |
|
71 |
+ } |
|
72 |
+ if (!(pool->linesize[0] & (pool->align - 1))) |
|
73 |
+ break; |
|
74 |
+ } |
|
75 |
+ |
|
76 |
+ for (i = 0; i < 4 && pool->linesize[i]; i++) { |
|
77 |
+ pool->linesize[i] = FFALIGN(pool->linesize[i], pool->align); |
|
78 |
+ } |
|
79 |
+ } |
|
80 |
+ |
|
81 |
+ for (i = 0; i < 4 && pool->linesize[i]; i++) { |
|
82 |
+ int h = FFALIGN(pool->height, 32); |
|
83 |
+ if (i == 1 || i == 2) |
|
84 |
+ h = FF_CEIL_RSHIFT(h, desc->log2_chroma_h); |
|
85 |
+ |
|
86 |
+ pool->pools[i] = av_buffer_pool_init(pool->linesize[i] * h + 16 + 16 - 1, |
|
87 |
+ alloc); |
|
88 |
+ if (!pool->pools[i]) |
|
89 |
+ goto fail; |
|
90 |
+ } |
|
91 |
+ |
|
92 |
+ if (desc->flags & AV_PIX_FMT_FLAG_PAL || |
|
93 |
+ desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { |
|
94 |
+ pool->pools[1] = av_buffer_pool_init(AVPALETTE_SIZE, alloc); |
|
95 |
+ if (!pool->pools[1]) |
|
96 |
+ goto fail; |
|
97 |
+ } |
|
98 |
+ |
|
99 |
+ return pool; |
|
100 |
+ |
|
101 |
+fail: |
|
102 |
+ ff_video_frame_pool_uninit(&pool); |
|
103 |
+ return NULL; |
|
104 |
+} |
|
105 |
+ |
|
106 |
+int ff_video_frame_pool_get_config(FFVideoFramePool *pool, |
|
107 |
+ int *width, |
|
108 |
+ int *height, |
|
109 |
+ enum AVPixelFormat *format, |
|
110 |
+ int *align) |
|
111 |
+{ |
|
112 |
+ if (!pool) |
|
113 |
+ return AVERROR(EINVAL); |
|
114 |
+ |
|
115 |
+ *width = pool->width; |
|
116 |
+ *height = pool->height; |
|
117 |
+ *format = pool->format; |
|
118 |
+ *align = pool->align; |
|
119 |
+ |
|
120 |
+ return 0; |
|
121 |
+} |
|
122 |
+ |
|
123 |
+ |
|
124 |
+AVFrame *ff_video_frame_pool_get(FFVideoFramePool *pool) |
|
125 |
+{ |
|
126 |
+ int i; |
|
127 |
+ AVFrame *frame; |
|
128 |
+ const AVPixFmtDescriptor *desc; |
|
129 |
+ |
|
130 |
+ frame = av_frame_alloc(); |
|
131 |
+ if (!frame) { |
|
132 |
+ return NULL; |
|
133 |
+ } |
|
134 |
+ |
|
135 |
+ desc = av_pix_fmt_desc_get(pool->format); |
|
136 |
+ if (!desc) { |
|
137 |
+ goto fail; |
|
138 |
+ } |
|
139 |
+ |
|
140 |
+ frame->width = pool->width; |
|
141 |
+ frame->height = pool->height; |
|
142 |
+ frame->format = pool->format; |
|
143 |
+ |
|
144 |
+ for (i = 0; i < 4; i++) { |
|
145 |
+ frame->linesize[i] = pool->linesize[i]; |
|
146 |
+ if (!pool->pools[i]) |
|
147 |
+ break; |
|
148 |
+ |
|
149 |
+ frame->buf[i] = av_buffer_pool_get(pool->pools[i]); |
|
150 |
+ if (!frame->buf[i]) { |
|
151 |
+ goto fail; |
|
152 |
+ } |
|
153 |
+ |
|
154 |
+ frame->data[i] = frame->buf[i]->data; |
|
155 |
+ } |
|
156 |
+ |
|
157 |
+ if (desc->flags & AV_PIX_FMT_FLAG_PAL || |
|
158 |
+ desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { |
|
159 |
+ enum AVPixelFormat format = |
|
160 |
+ pool->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : pool->format; |
|
161 |
+ |
|
162 |
+ av_assert0(frame->data[1] != NULL); |
|
163 |
+ if (avpriv_set_systematic_pal2((uint32_t *)frame->data[1], format) < 0) { |
|
164 |
+ goto fail; |
|
165 |
+ } |
|
166 |
+ } |
|
167 |
+ |
|
168 |
+ frame->extended_data = frame->data; |
|
169 |
+ |
|
170 |
+ return frame; |
|
171 |
+fail: |
|
172 |
+ av_frame_free(&frame); |
|
173 |
+ return NULL; |
|
174 |
+} |
|
175 |
+ |
|
176 |
+void ff_video_frame_pool_uninit(FFVideoFramePool **pool) |
|
177 |
+{ |
|
178 |
+ int i; |
|
179 |
+ |
|
180 |
+ if (!pool || !*pool) |
|
181 |
+ return; |
|
182 |
+ |
|
183 |
+ for (i = 0; i < 4; i++) { |
|
184 |
+ av_buffer_pool_uninit(&(*pool)->pools[i]); |
|
185 |
+ } |
|
186 |
+ |
|
187 |
+ av_freep(pool); |
|
188 |
+} |
0 | 189 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,84 @@ |
0 |
+/* |
|
1 |
+ * This file is part of FFmpeg. |
|
2 |
+ * |
|
3 |
+ * Copyright (c) 2015 Matthieu Bouron <matthieu.bouron stupeflix.com> |
|
4 |
+ * |
|
5 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
7 |
+ * License as published by the Free Software Foundation; either |
|
8 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
9 |
+ * |
|
10 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
+ * Lesser General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
16 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+#ifndef AVUTIL_FRAME_POOL_H |
|
21 |
+#define AVUTIL_FRAME_POOL_H |
|
22 |
+ |
|
23 |
+#include "libavutil/buffer.h" |
|
24 |
+#include "libavutil/frame.h" |
|
25 |
+ |
|
26 |
+/** |
|
27 |
+ * Video frame pool. This structure is opaque and not meant to be accessed |
|
28 |
+ * directly. It is allocated with ff_video_frame_pool_init() and freed with |
|
29 |
+ * ff_video_frame_pool_uninit(). |
|
30 |
+ */ |
|
31 |
+typedef struct FFVideoFramePool FFVideoFramePool; |
|
32 |
+ |
|
33 |
+/** |
|
34 |
+ * Allocate and initialize a video frame pool. |
|
35 |
+ * |
|
36 |
+ * @param alloc a function that will be used to allocate new frame buffers when |
|
37 |
+ * the pool is empty. May be NULL, then the default allocator will be used |
|
38 |
+ * (av_buffer_alloc()). |
|
39 |
+ * @param width width of each frame in this pool |
|
40 |
+ * @param height height of each frame in this pool |
|
41 |
+ * @param format format of each frame in this pool |
|
42 |
+ * @param align buffers alignement of each frame in this pool |
|
43 |
+ * @return newly created video frame pool on success, NULL on error. |
|
44 |
+ */ |
|
45 |
+FFVideoFramePool *ff_video_frame_pool_init(AVBufferRef* (*alloc)(int size), |
|
46 |
+ int width, |
|
47 |
+ int height, |
|
48 |
+ enum AVPixelFormat format, |
|
49 |
+ int align); |
|
50 |
+ |
|
51 |
+/** |
|
52 |
+ * Deallocate the video frame pool. It is safe to call this function while |
|
53 |
+ * some of the allocated video frame are still in use. |
|
54 |
+ * |
|
55 |
+ * @param pool pointer to the video frame pool to be freed. It will be set to NULL. |
|
56 |
+ */ |
|
57 |
+void ff_video_frame_pool_uninit(FFVideoFramePool **pool); |
|
58 |
+ |
|
59 |
+/** |
|
60 |
+ * Get the video frame pool configuration. |
|
61 |
+ * |
|
62 |
+ * @param width width of each frame in this pool |
|
63 |
+ * @param height height of each frame in this pool |
|
64 |
+ * @param format format of each frame in this pool |
|
65 |
+ * @param align buffers alignement of each frame in this pool |
|
66 |
+ * @return 0 on success, a negative AVERROR otherwise. |
|
67 |
+ */ |
|
68 |
+int ff_video_frame_pool_get_config(FFVideoFramePool *pool, |
|
69 |
+ int *width, |
|
70 |
+ int *height, |
|
71 |
+ enum AVPixelFormat *format, |
|
72 |
+ int *align); |
|
73 |
+ |
|
74 |
+/** |
|
75 |
+ * Allocate a new AVFrame, reussing old buffers from the pool when available. |
|
76 |
+ * This function may be called simultaneously from multiple threads. |
|
77 |
+ * |
|
78 |
+ * @return a new AVFrame on success, NULL on error. |
|
79 |
+ */ |
|
80 |
+AVFrame *ff_video_frame_pool_get(FFVideoFramePool *pool); |
|
81 |
+ |
|
82 |
+ |
|
83 |
+#endif /* AVUTIL_FRAME_POOL_H */ |
... | ... |
@@ -32,31 +32,45 @@ |
32 | 32 |
#include "internal.h" |
33 | 33 |
#include "video.h" |
34 | 34 |
|
35 |
+#define BUFFER_ALIGN 32 |
|
36 |
+ |
|
37 |
+ |
|
35 | 38 |
AVFrame *ff_null_get_video_buffer(AVFilterLink *link, int w, int h) |
36 | 39 |
{ |
37 | 40 |
return ff_get_video_buffer(link->dst->outputs[0], w, h); |
38 | 41 |
} |
39 | 42 |
|
40 |
-/* TODO: set the buffer's priv member to a context structure for the whole |
|
41 |
- * filter chain. This will allow for a buffer pool instead of the constant |
|
42 |
- * alloc & free cycle currently implemented. */ |
|
43 | 43 |
AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) |
44 | 44 |
{ |
45 |
- AVFrame *frame = av_frame_alloc(); |
|
46 |
- int ret; |
|
45 |
+ int pool_width = 0; |
|
46 |
+ int pool_height = 0; |
|
47 |
+ int pool_align = 0; |
|
48 |
+ enum AVPixelFormat pool_format = AV_PIX_FMT_NONE; |
|
47 | 49 |
|
48 |
- if (!frame) |
|
49 |
- return NULL; |
|
50 |
+ if (!link->video_frame_pool) { |
|
51 |
+ link->video_frame_pool = ff_video_frame_pool_init(av_buffer_allocz, w, h, |
|
52 |
+ link->format, BUFFER_ALIGN); |
|
53 |
+ if (!link->video_frame_pool) |
|
54 |
+ return NULL; |
|
55 |
+ } else { |
|
56 |
+ if (ff_video_frame_pool_get_config(link->video_frame_pool, |
|
57 |
+ &pool_width, &pool_height, |
|
58 |
+ &pool_format, &pool_align) < 0) { |
|
59 |
+ return NULL; |
|
60 |
+ } |
|
50 | 61 |
|
51 |
- frame->width = w; |
|
52 |
- frame->height = h; |
|
53 |
- frame->format = link->format; |
|
62 |
+ if (pool_width != w || pool_height != h || |
|
63 |
+ pool_format != link->format || pool_align != BUFFER_ALIGN) { |
|
54 | 64 |
|
55 |
- ret = av_frame_get_buffer(frame, 32); |
|
56 |
- if (ret < 0) |
|
57 |
- av_frame_free(&frame); |
|
65 |
+ ff_video_frame_pool_uninit((FFVideoFramePool **)&link->video_frame_pool); |
|
66 |
+ link->video_frame_pool = ff_video_frame_pool_init(av_buffer_allocz, w, h, |
|
67 |
+ link->format, BUFFER_ALIGN); |
|
68 |
+ if (!link->video_frame_pool) |
|
69 |
+ return NULL; |
|
70 |
+ } |
|
71 |
+ } |
|
58 | 72 |
|
59 |
- return frame; |
|
73 |
+ return ff_video_frame_pool_get(link->video_frame_pool); |
|
60 | 74 |
} |
61 | 75 |
|
62 | 76 |
AVFrame *ff_get_video_buffer(AVFilterLink *link, int w, int h) |