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