/src/ffmpeg/libavcodec/get_buffer.c
Line | Count | Source |
1 | | /* |
2 | | * The default get_buffer2() implementation |
3 | | * |
4 | | * This file is part of FFmpeg. |
5 | | * |
6 | | * FFmpeg is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * FFmpeg is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with FFmpeg; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #include <stdint.h> |
22 | | |
23 | | #include "libavutil/avassert.h" |
24 | | #include "libavutil/avutil.h" |
25 | | #include "libavutil/buffer.h" |
26 | | #include "libavutil/frame.h" |
27 | | #include "libavutil/hwcontext.h" |
28 | | #include "libavutil/imgutils.h" |
29 | | #include "libavutil/mem.h" |
30 | | #include "libavutil/samplefmt.h" |
31 | | #include "libavutil/version.h" |
32 | | |
33 | | #include "avcodec.h" |
34 | | #include "internal.h" |
35 | | #include "libavutil/refstruct.h" |
36 | | |
37 | | typedef struct FramePool { |
38 | | /** |
39 | | * Pools for each data plane. For audio all the planes have the same size, |
40 | | * so only pools[0] is used. |
41 | | */ |
42 | | AVBufferPool *pools[4]; |
43 | | |
44 | | /* |
45 | | * Pool parameters |
46 | | */ |
47 | | int format; |
48 | | int width, height; |
49 | | int stride_align[AV_NUM_DATA_POINTERS]; |
50 | | int linesize[4]; |
51 | | int planes; |
52 | | int channels; |
53 | | int samples; |
54 | | } FramePool; |
55 | | |
56 | | static void frame_pool_free(AVRefStructOpaque unused, void *obj) |
57 | 0 | { |
58 | 0 | FramePool *pool = obj; |
59 | 0 | int i; |
60 | |
|
61 | 0 | for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) |
62 | 0 | av_buffer_pool_uninit(&pool->pools[i]); |
63 | 0 | } |
64 | | |
65 | | static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) |
66 | 0 | { |
67 | 0 | FramePool *pool = avctx->internal->pool; |
68 | 0 | int i, ret; |
69 | |
|
70 | 0 | if (pool && pool->format == frame->format) { |
71 | 0 | if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && |
72 | 0 | pool->width == frame->width && pool->height == frame->height) |
73 | 0 | return 0; |
74 | 0 | if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && |
75 | 0 | pool->channels == frame->ch_layout.nb_channels && |
76 | 0 | frame->nb_samples == pool->samples) |
77 | 0 | return 0; |
78 | 0 | } |
79 | | |
80 | 0 | pool = av_refstruct_alloc_ext(sizeof(*pool), 0, NULL, frame_pool_free); |
81 | 0 | if (!pool) |
82 | 0 | return AVERROR(ENOMEM); |
83 | | |
84 | 0 | switch (avctx->codec_type) { |
85 | 0 | case AVMEDIA_TYPE_VIDEO: { |
86 | 0 | int linesize[4]; |
87 | 0 | int w = frame->width; |
88 | 0 | int h = frame->height; |
89 | 0 | int unaligned; |
90 | 0 | ptrdiff_t linesize1[4]; |
91 | 0 | size_t size[4]; |
92 | |
|
93 | 0 | avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align); |
94 | |
|
95 | 0 | do { |
96 | | // NOTE: do not align linesizes individually, this breaks e.g. assumptions |
97 | | // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 |
98 | 0 | ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w); |
99 | 0 | if (ret < 0) |
100 | 0 | goto fail; |
101 | | // increase alignment of w for next try (rhs gives the lowest bit set in w) |
102 | 0 | w += w & ~(w - 1); |
103 | |
|
104 | 0 | unaligned = 0; |
105 | 0 | for (i = 0; i < 4; i++) |
106 | 0 | unaligned |= linesize[i] % pool->stride_align[i]; |
107 | 0 | } while (unaligned); |
108 | | |
109 | 0 | for (i = 0; i < 4; i++) |
110 | 0 | linesize1[i] = linesize[i]; |
111 | 0 | ret = av_image_fill_plane_sizes(size, avctx->pix_fmt, h, linesize1); |
112 | 0 | if (ret < 0) |
113 | 0 | goto fail; |
114 | | |
115 | 0 | for (i = 0; i < 4; i++) { |
116 | 0 | pool->linesize[i] = linesize[i]; |
117 | 0 | if (size[i]) { |
118 | 0 | if (size[i] > INT_MAX - (16 + STRIDE_ALIGN - 1)) { |
119 | 0 | ret = AVERROR(EINVAL); |
120 | 0 | goto fail; |
121 | 0 | } |
122 | 0 | pool->pools[i] = av_buffer_pool_init(size[i] + 16 + STRIDE_ALIGN - 1, |
123 | 0 | CONFIG_MEMORY_POISONING ? |
124 | 0 | NULL : |
125 | 0 | av_buffer_allocz); |
126 | 0 | if (!pool->pools[i]) { |
127 | 0 | ret = AVERROR(ENOMEM); |
128 | 0 | goto fail; |
129 | 0 | } |
130 | 0 | } |
131 | 0 | } |
132 | 0 | pool->format = frame->format; |
133 | 0 | pool->width = frame->width; |
134 | 0 | pool->height = frame->height; |
135 | |
|
136 | 0 | break; |
137 | 0 | } |
138 | 0 | case AVMEDIA_TYPE_AUDIO: { |
139 | 0 | ret = av_samples_get_buffer_size(&pool->linesize[0], |
140 | 0 | frame->ch_layout.nb_channels, |
141 | 0 | frame->nb_samples, frame->format, 0); |
142 | 0 | if (ret < 0) |
143 | 0 | goto fail; |
144 | | |
145 | 0 | pool->pools[0] = av_buffer_pool_init(pool->linesize[0], |
146 | 0 | CONFIG_MEMORY_POISONING ? |
147 | 0 | NULL : |
148 | 0 | av_buffer_allocz); |
149 | 0 | if (!pool->pools[0]) { |
150 | 0 | ret = AVERROR(ENOMEM); |
151 | 0 | goto fail; |
152 | 0 | } |
153 | | |
154 | 0 | pool->format = frame->format; |
155 | 0 | pool->channels = frame->ch_layout.nb_channels; |
156 | 0 | pool->samples = frame->nb_samples; |
157 | 0 | pool->planes = av_sample_fmt_is_planar(pool->format) ? pool->channels : 1; |
158 | 0 | break; |
159 | 0 | } |
160 | 0 | default: av_assert0(0); |
161 | 0 | } |
162 | | |
163 | 0 | av_refstruct_unref(&avctx->internal->pool); |
164 | 0 | avctx->internal->pool = pool; |
165 | |
|
166 | 0 | return 0; |
167 | 0 | fail: |
168 | 0 | av_refstruct_unref(&pool); |
169 | 0 | return ret; |
170 | 0 | } |
171 | | |
172 | | static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) |
173 | 0 | { |
174 | 0 | FramePool *pool = avctx->internal->pool; |
175 | 0 | int planes = pool->planes; |
176 | 0 | int i; |
177 | |
|
178 | 0 | frame->linesize[0] = pool->linesize[0]; |
179 | |
|
180 | 0 | if (planes > AV_NUM_DATA_POINTERS) { |
181 | 0 | frame->extended_data = av_calloc(planes, sizeof(*frame->extended_data)); |
182 | 0 | frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; |
183 | 0 | frame->extended_buf = av_calloc(frame->nb_extended_buf, |
184 | 0 | sizeof(*frame->extended_buf)); |
185 | 0 | if (!frame->extended_data || !frame->extended_buf) { |
186 | 0 | av_freep(&frame->extended_data); |
187 | 0 | av_freep(&frame->extended_buf); |
188 | 0 | return AVERROR(ENOMEM); |
189 | 0 | } |
190 | 0 | } else { |
191 | 0 | frame->extended_data = frame->data; |
192 | 0 | av_assert0(frame->nb_extended_buf == 0); |
193 | 0 | } |
194 | | |
195 | 0 | for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { |
196 | 0 | frame->buf[i] = av_buffer_pool_get(pool->pools[0]); |
197 | 0 | if (!frame->buf[i]) |
198 | 0 | goto fail; |
199 | 0 | frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; |
200 | 0 | } |
201 | 0 | for (i = 0; i < frame->nb_extended_buf; i++) { |
202 | 0 | frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]); |
203 | 0 | if (!frame->extended_buf[i]) |
204 | 0 | goto fail; |
205 | 0 | frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; |
206 | 0 | } |
207 | | |
208 | 0 | if (avctx->debug & FF_DEBUG_BUFFERS) |
209 | 0 | av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", frame); |
210 | |
|
211 | 0 | return 0; |
212 | 0 | fail: |
213 | 0 | av_frame_unref(frame); |
214 | 0 | return AVERROR(ENOMEM); |
215 | 0 | } |
216 | | |
217 | | static int video_get_buffer(AVCodecContext *s, AVFrame *pic) |
218 | 0 | { |
219 | 0 | FramePool *pool = s->internal->pool; |
220 | 0 | int i; |
221 | |
|
222 | 0 | if (pic->data[0] || pic->data[1] || pic->data[2] || pic->data[3]) { |
223 | 0 | av_log(s, AV_LOG_ERROR, "pic->data[*]!=NULL in avcodec_default_get_buffer\n"); |
224 | 0 | return -1; |
225 | 0 | } |
226 | | |
227 | 0 | memset(pic->data, 0, sizeof(pic->data)); |
228 | 0 | pic->extended_data = pic->data; |
229 | |
|
230 | 0 | for (i = 0; i < 4 && pool->pools[i]; i++) { |
231 | 0 | pic->linesize[i] = pool->linesize[i]; |
232 | |
|
233 | 0 | pic->buf[i] = av_buffer_pool_get(pool->pools[i]); |
234 | 0 | if (!pic->buf[i]) |
235 | 0 | goto fail; |
236 | | |
237 | 0 | pic->data[i] = pic->buf[i]->data; |
238 | 0 | } |
239 | 0 | for (; i < AV_NUM_DATA_POINTERS; i++) { |
240 | 0 | pic->data[i] = NULL; |
241 | 0 | pic->linesize[i] = 0; |
242 | 0 | } |
243 | |
|
244 | 0 | if (s->debug & FF_DEBUG_BUFFERS) |
245 | 0 | av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic); |
246 | |
|
247 | 0 | return 0; |
248 | 0 | fail: |
249 | 0 | av_frame_unref(pic); |
250 | 0 | return AVERROR(ENOMEM); |
251 | 0 | } |
252 | | |
253 | | int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags) |
254 | 0 | { |
255 | 0 | int ret; |
256 | |
|
257 | 0 | if (avctx->hw_frames_ctx) { |
258 | 0 | ret = av_hwframe_get_buffer(avctx->hw_frames_ctx, frame, 0); |
259 | 0 | if (ret == AVERROR(ENOMEM)) { |
260 | 0 | AVHWFramesContext *frames_ctx = |
261 | 0 | (AVHWFramesContext*)avctx->hw_frames_ctx->data; |
262 | 0 | if (frames_ctx->initial_pool_size > 0 && |
263 | 0 | !avctx->internal->warned_on_failed_allocation_from_fixed_pool) { |
264 | 0 | av_log(avctx, AV_LOG_WARNING, "Failed to allocate a %s/%s " |
265 | 0 | "frame from a fixed pool of hardware frames.\n", |
266 | 0 | av_get_pix_fmt_name(frames_ctx->format), |
267 | 0 | av_get_pix_fmt_name(frames_ctx->sw_format)); |
268 | 0 | av_log(avctx, AV_LOG_WARNING, "Consider setting " |
269 | 0 | "extra_hw_frames to a larger value " |
270 | 0 | "(currently set to %d, giving a pool size of %d).\n", |
271 | 0 | avctx->extra_hw_frames, frames_ctx->initial_pool_size); |
272 | 0 | avctx->internal->warned_on_failed_allocation_from_fixed_pool = 1; |
273 | 0 | } |
274 | 0 | } |
275 | 0 | frame->width = avctx->coded_width; |
276 | 0 | frame->height = avctx->coded_height; |
277 | 0 | return ret; |
278 | 0 | } |
279 | | |
280 | 0 | if ((ret = update_frame_pool(avctx, frame)) < 0) |
281 | 0 | return ret; |
282 | | |
283 | 0 | switch (avctx->codec_type) { |
284 | 0 | case AVMEDIA_TYPE_VIDEO: |
285 | 0 | return video_get_buffer(avctx, frame); |
286 | 0 | case AVMEDIA_TYPE_AUDIO: |
287 | 0 | return audio_get_buffer(avctx, frame); |
288 | 0 | default: |
289 | 0 | return -1; |
290 | 0 | } |
291 | 0 | } |