static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) { FramePool *pool = avctx->internal->pool; int planes = pool->planes; int i; frame->linesize[0] = pool->linesize[0]; if (planes > AV_NUM_DATA_POINTERS) { frame->extended_data = av_mallocz(planes * sizeof(*frame->extended_data)); frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; frame->extended_buf = av_mallocz(frame->nb_extended_buf * sizeof(*frame->extended_buf)); if (!frame->extended_data || !frame->extended_buf) { av_freep(&frame->extended_data); av_freep(&frame->extended_buf); return AVERROR(ENOMEM); } } else frame->extended_data = frame->data; for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { frame->buf[i] = av_buffer_pool_get(pool->pools[0]); if (!frame->buf[i]) goto fail; frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; } for (i = 0; i < frame->nb_extended_buf; i++) { frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]); if (!frame->extended_buf[i]) goto fail; frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; } if (avctx->debug & FF_DEBUG_BUFFERS) av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", frame); return 0; fail: av_frame_unref(frame); return AVERROR(ENOMEM); }
static int cuda_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) { int aligned_width; int width_in_bytes = ctx->width; if (ctx->sw_format == AV_PIX_FMT_P010 || ctx->sw_format == AV_PIX_FMT_P016 || ctx->sw_format == AV_PIX_FMT_YUV444P16) { width_in_bytes *= 2; } aligned_width = FFALIGN(width_in_bytes, CUDA_FRAME_ALIGNMENT); frame->buf[0] = av_buffer_pool_get(ctx->pool); if (!frame->buf[0]) return AVERROR(ENOMEM); switch (ctx->sw_format) { case AV_PIX_FMT_NV12: case AV_PIX_FMT_P010: case AV_PIX_FMT_P016: frame->data[0] = frame->buf[0]->data; frame->data[1] = frame->data[0] + aligned_width * ctx->height; frame->linesize[0] = aligned_width; frame->linesize[1] = aligned_width; break; case AV_PIX_FMT_YUV420P: frame->data[0] = frame->buf[0]->data; frame->data[2] = frame->data[0] + aligned_width * ctx->height; frame->data[1] = frame->data[2] + aligned_width * ctx->height / 4; frame->linesize[0] = aligned_width; frame->linesize[1] = aligned_width / 2; frame->linesize[2] = aligned_width / 2; break; case AV_PIX_FMT_YUV444P: case AV_PIX_FMT_YUV444P16: frame->data[0] = frame->buf[0]->data; frame->data[1] = frame->data[0] + aligned_width * ctx->height; frame->data[2] = frame->data[1] + aligned_width * ctx->height; frame->linesize[0] = aligned_width; frame->linesize[1] = aligned_width; frame->linesize[2] = aligned_width; break; default: av_frame_unref(frame); return AVERROR_BUG; } frame->format = AV_PIX_FMT_CUDA; frame->width = ctx->width; frame->height = ctx->height; return 0; }
static int dxva2_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) { frame->buf[0] = av_buffer_pool_get(ctx->pool); if (!frame->buf[0]) return AVERROR(ENOMEM); frame->data[3] = frame->buf[0]->data; frame->format = AV_PIX_FMT_DXVA2_VLD; frame->width = ctx->width; frame->height = ctx->height; return 0; }
static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame) { frame->buf[0] = av_buffer_pool_get(hwfc->pool); if (!frame->buf[0]) return AVERROR(ENOMEM); frame->data[3] = frame->buf[0]->data; frame->format = AV_PIX_FMT_VAAPI; frame->width = hwfc->width; frame->height = hwfc->height; return 0; }
AVFrame *ff_video_frame_pool_get(FFVideoFramePool *pool) { int i; AVFrame *frame; const AVPixFmtDescriptor *desc; frame = av_frame_alloc(); if (!frame) { return NULL; } desc = av_pix_fmt_desc_get(pool->format); if (!desc) { goto fail; } frame->width = pool->width; frame->height = pool->height; frame->format = pool->format; for (i = 0; i < 4; i++) { frame->linesize[i] = pool->linesize[i]; if (!pool->pools[i]) break; frame->buf[i] = av_buffer_pool_get(pool->pools[i]); if (!frame->buf[i]) { goto fail; } frame->data[i] = frame->buf[i]->data; } if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { enum AVPixelFormat format = pool->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : pool->format; av_assert0(frame->data[1] != NULL); if (avpriv_set_systematic_pal2((uint32_t *)frame->data[1], format) < 0) { goto fail; } } frame->extended_data = frame->data; return frame; fail: av_frame_free(&frame); return NULL; }
int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame) { NVDECContext *ctx = avctx->internal->hwaccel_priv_data; FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; NVDECFrame *cf = NULL; int ret; ctx->bitstream_len = 0; ctx->nb_slices = 0; if (fdd->hwaccel_priv) return 0; cf = av_mallocz(sizeof(*cf)); if (!cf) return AVERROR(ENOMEM); cf->decoder_ref = av_buffer_ref(ctx->decoder_ref); if (!cf->decoder_ref) { ret = AVERROR(ENOMEM); goto fail; } cf->idx_ref = av_buffer_pool_get(ctx->decoder_pool); if (!cf->idx_ref) { av_log(avctx, AV_LOG_ERROR, "No decoder surfaces left\n"); ret = AVERROR(ENOMEM); goto fail; } cf->idx = *(unsigned int*)cf->idx_ref->data; fdd->hwaccel_priv = cf; fdd->hwaccel_priv_free = nvdec_fdd_priv_free; fdd->post_process = nvdec_retrieve_data; return 0; fail: nvdec_fdd_priv_free(cf); return ret; }
static int video_get_buffer(AVCodecContext *s, AVFrame *pic) { FramePool *pool = s->internal->pool; int i; if (pic->data[0]) { av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n"); return -1; } memset(pic->data, 0, sizeof(pic->data)); pic->extended_data = pic->data; for (i = 0; i < 4 && pool->pools[i]; i++) { pic->linesize[i] = pool->linesize[i]; pic->buf[i] = av_buffer_pool_get(pool->pools[i]); if (!pic->buf[i]) goto fail; pic->data[i] = pic->buf[i]->data; } for (; i < AV_NUM_DATA_POINTERS; i++) { pic->data[i] = NULL; pic->linesize[i] = 0; } if (pic->data[1] && !pic->data[2]) avpriv_set_systematic_pal2((uint32_t *)pic->data[1], s->pix_fmt); if (s->debug & FF_DEBUG_BUFFERS) av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic); return 0; fail: av_frame_unref(pic); return AVERROR(ENOMEM); }
static int vaapi_frames_init(AVHWFramesContext *hwfc) { AVVAAPIFramesContext *avfc = hwfc->hwctx; VAAPIFramesContext *ctx = hwfc->internal->priv; AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; VAImageFormat *expected_format; AVBufferRef *test_surface = NULL; VASurfaceID test_surface_id; VAImage test_image; VAStatus vas; int err, i; unsigned int fourcc, rt_format; for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) { if (vaapi_format_map[i].pix_fmt == hwfc->sw_format) { fourcc = vaapi_format_map[i].fourcc; rt_format = vaapi_format_map[i].rt_format; break; } } if (i >= FF_ARRAY_ELEMS(vaapi_format_map)) { av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n", av_get_pix_fmt_name(hwfc->sw_format)); return AVERROR(EINVAL); } if (!hwfc->pool) { int need_memory_type = 1, need_pixel_format = 1; for (i = 0; i < avfc->nb_attributes; i++) { if (ctx->attributes[i].type == VASurfaceAttribMemoryType) need_memory_type = 0; if (ctx->attributes[i].type == VASurfaceAttribPixelFormat) need_pixel_format = 0; } ctx->nb_attributes = avfc->nb_attributes + need_memory_type + need_pixel_format; ctx->attributes = av_malloc(ctx->nb_attributes * sizeof(*ctx->attributes)); if (!ctx->attributes) { err = AVERROR(ENOMEM); goto fail; } for (i = 0; i < avfc->nb_attributes; i++) ctx->attributes[i] = avfc->attributes[i]; if (need_memory_type) { ctx->attributes[i++] = (VASurfaceAttrib) { .type = VASurfaceAttribMemoryType, .flags = VA_SURFACE_ATTRIB_SETTABLE, .value.type = VAGenericValueTypeInteger, .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA, }; } if (need_pixel_format) { ctx->attributes[i++] = (VASurfaceAttrib) { .type = VASurfaceAttribPixelFormat, .flags = VA_SURFACE_ATTRIB_SETTABLE, .value.type = VAGenericValueTypeInteger, .value.value.i = fourcc, }; } av_assert0(i == ctx->nb_attributes); ctx->rt_format = rt_format; if (hwfc->initial_pool_size > 0) { // This pool will be usable as a render target, so we need to store // all of the surface IDs somewhere that vaCreateContext() calls // will be able to access them. avfc->nb_surfaces = 0; avfc->surface_ids = av_malloc(hwfc->initial_pool_size * sizeof(*avfc->surface_ids)); if (!avfc->surface_ids) { err = AVERROR(ENOMEM); goto fail; } } else { // This pool allows dynamic sizing, and will not be usable as a // render target. avfc->nb_surfaces = 0; avfc->surface_ids = NULL; } hwfc->internal->pool_internal = av_buffer_pool_init2(sizeof(VASurfaceID), hwfc, &vaapi_pool_alloc, NULL); if (!hwfc->internal->pool_internal) { av_log(hwfc, AV_LOG_ERROR, "Failed to create VAAPI surface pool.\n"); err = AVERROR(ENOMEM); goto fail; } } // Allocate a single surface to test whether vaDeriveImage() is going // to work for the specific configuration. if (hwfc->pool) { test_surface = av_buffer_pool_get(hwfc->pool); if (!test_surface) { av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from " "user-configured buffer pool.\n"); err = AVERROR(ENOMEM); goto fail; } } else { test_surface = av_buffer_pool_get(hwfc->internal->pool_internal); if (!test_surface) { av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from " "internal buffer pool.\n"); err = AVERROR(ENOMEM); goto fail; } } test_surface_id = (VASurfaceID)(uintptr_t)test_surface->data; ctx->derive_works = 0; err = vaapi_get_image_format(hwfc->device_ctx, hwfc->sw_format, &expected_format); if (err == 0) { vas = vaDeriveImage(hwctx->display, test_surface_id, &test_image); if (vas == VA_STATUS_SUCCESS) { if (expected_format->fourcc == test_image.format.fourcc) { av_log(hwfc, AV_LOG_DEBUG, "Direct mapping possible.\n"); ctx->derive_works = 1; } else { av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " "derived image format %08x does not match " "expected format %08x.\n", expected_format->fourcc, test_image.format.fourcc); } vaDestroyImage(hwctx->display, test_image.image_id); } else { av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " "deriving image does not work: " "%d (%s).\n", vas, vaErrorStr(vas)); } } else { av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " "image format is not supported.\n"); } av_buffer_unref(&test_surface); return 0; fail: av_buffer_unref(&test_surface); av_freep(&avfc->surface_ids); av_freep(&ctx->attributes); return err; } static void vaapi_frames_uninit(AVHWFramesContext *hwfc) { AVVAAPIFramesContext *avfc = hwfc->hwctx; VAAPIFramesContext *ctx = hwfc->internal->priv; av_freep(&avfc->surface_ids); av_freep(&ctx->attributes); }