LCOV - code coverage report
Current view: top level - src/libavutil - hwcontext.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 260 0.0 %
Date: 2017-01-21 09:32:20 Functions: 0 15 0.0 %

          Line data    Source code
       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 "config.h"
      20             : 
      21             : #include "buffer.h"
      22             : #include "common.h"
      23             : #include "hwcontext.h"
      24             : #include "hwcontext_internal.h"
      25             : #include "imgutils.h"
      26             : #include "log.h"
      27             : #include "mem.h"
      28             : #include "pixdesc.h"
      29             : #include "pixfmt.h"
      30             : 
      31             : static const HWContextType *hw_table[] = {
      32             : #if CONFIG_CUDA
      33             :     &ff_hwcontext_type_cuda,
      34             : #endif
      35             : #if CONFIG_DXVA2
      36             :     &ff_hwcontext_type_dxva2,
      37             : #endif
      38             : #if CONFIG_QSV
      39             :     &ff_hwcontext_type_qsv,
      40             : #endif
      41             : #if CONFIG_VAAPI
      42             :     &ff_hwcontext_type_vaapi,
      43             : #endif
      44             : #if CONFIG_VDPAU
      45             :     &ff_hwcontext_type_vdpau,
      46             : #endif
      47             :     NULL,
      48             : };
      49             : 
      50             : static const AVClass hwdevice_ctx_class = {
      51             :     .class_name = "AVHWDeviceContext",
      52             :     .item_name  = av_default_item_name,
      53             :     .version    = LIBAVUTIL_VERSION_INT,
      54             : };
      55             : 
      56           0 : static void hwdevice_ctx_free(void *opaque, uint8_t *data)
      57             : {
      58           0 :     AVHWDeviceContext *ctx = (AVHWDeviceContext*)data;
      59             : 
      60             :     /* uninit might still want access the hw context and the user
      61             :      * free() callback might destroy it, so uninit has to be called first */
      62           0 :     if (ctx->internal->hw_type->device_uninit)
      63           0 :         ctx->internal->hw_type->device_uninit(ctx);
      64             : 
      65           0 :     if (ctx->free)
      66           0 :         ctx->free(ctx);
      67             : 
      68           0 :     av_freep(&ctx->hwctx);
      69           0 :     av_freep(&ctx->internal->priv);
      70           0 :     av_freep(&ctx->internal);
      71           0 :     av_freep(&ctx);
      72           0 : }
      73             : 
      74           0 : AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
      75             : {
      76             :     AVHWDeviceContext *ctx;
      77             :     AVBufferRef *buf;
      78           0 :     const HWContextType *hw_type = NULL;
      79             :     int i;
      80             : 
      81           0 :     for (i = 0; hw_table[i]; i++) {
      82           0 :         if (hw_table[i]->type == type) {
      83           0 :             hw_type = hw_table[i];
      84           0 :             break;
      85             :         }
      86             :     }
      87           0 :     if (!hw_type)
      88           0 :         return NULL;
      89             : 
      90           0 :     ctx = av_mallocz(sizeof(*ctx));
      91           0 :     if (!ctx)
      92           0 :         return NULL;
      93             : 
      94           0 :     ctx->internal = av_mallocz(sizeof(*ctx->internal));
      95           0 :     if (!ctx->internal)
      96           0 :         goto fail;
      97             : 
      98           0 :     if (hw_type->device_priv_size) {
      99           0 :         ctx->internal->priv = av_mallocz(hw_type->device_priv_size);
     100           0 :         if (!ctx->internal->priv)
     101           0 :             goto fail;
     102             :     }
     103             : 
     104           0 :     if (hw_type->device_hwctx_size) {
     105           0 :         ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
     106           0 :         if (!ctx->hwctx)
     107           0 :             goto fail;
     108             :     }
     109             : 
     110           0 :     buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
     111             :                            hwdevice_ctx_free, NULL,
     112             :                            AV_BUFFER_FLAG_READONLY);
     113           0 :     if (!buf)
     114           0 :         goto fail;
     115             : 
     116           0 :     ctx->type     = type;
     117           0 :     ctx->av_class = &hwdevice_ctx_class;
     118             : 
     119           0 :     ctx->internal->hw_type = hw_type;
     120             : 
     121           0 :     return buf;
     122             : 
     123             : fail:
     124           0 :     if (ctx->internal)
     125           0 :         av_freep(&ctx->internal->priv);
     126           0 :     av_freep(&ctx->internal);
     127           0 :     av_freep(&ctx->hwctx);
     128           0 :     av_freep(&ctx);
     129           0 :     return NULL;
     130             : }
     131             : 
     132           0 : int av_hwdevice_ctx_init(AVBufferRef *ref)
     133             : {
     134           0 :     AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
     135             :     int ret;
     136             : 
     137           0 :     if (ctx->internal->hw_type->device_init) {
     138           0 :         ret = ctx->internal->hw_type->device_init(ctx);
     139           0 :         if (ret < 0)
     140           0 :             goto fail;
     141             :     }
     142             : 
     143           0 :     return 0;
     144             : fail:
     145           0 :     if (ctx->internal->hw_type->device_uninit)
     146           0 :         ctx->internal->hw_type->device_uninit(ctx);
     147           0 :     return ret;
     148             : }
     149             : 
     150             : static const AVClass hwframe_ctx_class = {
     151             :     .class_name = "AVHWFramesContext",
     152             :     .item_name  = av_default_item_name,
     153             :     .version    = LIBAVUTIL_VERSION_INT,
     154             : };
     155             : 
     156           0 : static void hwframe_ctx_free(void *opaque, uint8_t *data)
     157             : {
     158           0 :     AVHWFramesContext *ctx = (AVHWFramesContext*)data;
     159             : 
     160           0 :     if (ctx->internal->pool_internal)
     161           0 :         av_buffer_pool_uninit(&ctx->internal->pool_internal);
     162             : 
     163           0 :     if (ctx->internal->hw_type->frames_uninit)
     164           0 :         ctx->internal->hw_type->frames_uninit(ctx);
     165             : 
     166           0 :     if (ctx->free)
     167           0 :         ctx->free(ctx);
     168             : 
     169           0 :     av_buffer_unref(&ctx->device_ref);
     170             : 
     171           0 :     av_freep(&ctx->hwctx);
     172           0 :     av_freep(&ctx->internal->priv);
     173           0 :     av_freep(&ctx->internal);
     174           0 :     av_freep(&ctx);
     175           0 : }
     176             : 
     177           0 : AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
     178             : {
     179           0 :     AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data;
     180           0 :     const HWContextType  *hw_type = device_ctx->internal->hw_type;
     181             :     AVHWFramesContext *ctx;
     182           0 :     AVBufferRef *buf, *device_ref = NULL;
     183             : 
     184           0 :     ctx = av_mallocz(sizeof(*ctx));
     185           0 :     if (!ctx)
     186           0 :         return NULL;
     187             : 
     188           0 :     ctx->internal = av_mallocz(sizeof(*ctx->internal));
     189           0 :     if (!ctx->internal)
     190           0 :         goto fail;
     191             : 
     192           0 :     if (hw_type->frames_priv_size) {
     193           0 :         ctx->internal->priv = av_mallocz(hw_type->frames_priv_size);
     194           0 :         if (!ctx->internal->priv)
     195           0 :             goto fail;
     196             :     }
     197             : 
     198           0 :     if (hw_type->frames_hwctx_size) {
     199           0 :         ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
     200           0 :         if (!ctx->hwctx)
     201           0 :             goto fail;
     202             :     }
     203             : 
     204           0 :     device_ref = av_buffer_ref(device_ref_in);
     205           0 :     if (!device_ref)
     206           0 :         goto fail;
     207             : 
     208           0 :     buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
     209             :                            hwframe_ctx_free, NULL,
     210             :                            AV_BUFFER_FLAG_READONLY);
     211           0 :     if (!buf)
     212           0 :         goto fail;
     213             : 
     214           0 :     ctx->av_class   = &hwframe_ctx_class;
     215           0 :     ctx->device_ref = device_ref;
     216           0 :     ctx->device_ctx = device_ctx;
     217           0 :     ctx->format     = AV_PIX_FMT_NONE;
     218           0 :     ctx->sw_format  = AV_PIX_FMT_NONE;
     219             : 
     220           0 :     ctx->internal->hw_type = hw_type;
     221             : 
     222           0 :     return buf;
     223             : 
     224             : fail:
     225           0 :     if (device_ref)
     226           0 :         av_buffer_unref(&device_ref);
     227           0 :     if (ctx->internal)
     228           0 :         av_freep(&ctx->internal->priv);
     229           0 :     av_freep(&ctx->internal);
     230           0 :     av_freep(&ctx->hwctx);
     231           0 :     av_freep(&ctx);
     232           0 :     return NULL;
     233             : }
     234             : 
     235           0 : static int hwframe_pool_prealloc(AVBufferRef *ref)
     236             : {
     237           0 :     AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
     238             :     AVFrame **frames;
     239           0 :     int i, ret = 0;
     240             : 
     241           0 :     frames = av_mallocz_array(ctx->initial_pool_size, sizeof(*frames));
     242           0 :     if (!frames)
     243           0 :         return AVERROR(ENOMEM);
     244             : 
     245           0 :     for (i = 0; i < ctx->initial_pool_size; i++) {
     246           0 :         frames[i] = av_frame_alloc();
     247           0 :         if (!frames[i])
     248           0 :             goto fail;
     249             : 
     250           0 :         ret = av_hwframe_get_buffer(ref, frames[i], 0);
     251           0 :         if (ret < 0)
     252           0 :             goto fail;
     253             :     }
     254             : 
     255             : fail:
     256           0 :     for (i = 0; i < ctx->initial_pool_size; i++)
     257           0 :         av_frame_free(&frames[i]);
     258           0 :     av_freep(&frames);
     259             : 
     260           0 :     return ret;
     261             : }
     262             : 
     263           0 : int av_hwframe_ctx_init(AVBufferRef *ref)
     264             : {
     265           0 :     AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
     266             :     const enum AVPixelFormat *pix_fmt;
     267             :     int ret;
     268             : 
     269             :     /* validate the pixel format */
     270           0 :     for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) {
     271           0 :         if (*pix_fmt == ctx->format)
     272           0 :             break;
     273             :     }
     274           0 :     if (*pix_fmt == AV_PIX_FMT_NONE) {
     275           0 :         av_log(ctx, AV_LOG_ERROR,
     276             :                "The hardware pixel format '%s' is not supported by the device type '%s'\n",
     277           0 :                av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name);
     278           0 :         return AVERROR(ENOSYS);
     279             :     }
     280             : 
     281             :     /* validate the dimensions */
     282           0 :     ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
     283           0 :     if (ret < 0)
     284           0 :         return ret;
     285             : 
     286             :     /* format-specific init */
     287           0 :     if (ctx->internal->hw_type->frames_init) {
     288           0 :         ret = ctx->internal->hw_type->frames_init(ctx);
     289           0 :         if (ret < 0)
     290           0 :             goto fail;
     291             :     }
     292             : 
     293           0 :     if (ctx->internal->pool_internal && !ctx->pool)
     294           0 :         ctx->pool = ctx->internal->pool_internal;
     295             : 
     296             :     /* preallocate the frames in the pool, if requested */
     297           0 :     if (ctx->initial_pool_size > 0) {
     298           0 :         ret = hwframe_pool_prealloc(ref);
     299           0 :         if (ret < 0)
     300           0 :             goto fail;
     301             :     }
     302             : 
     303           0 :     return 0;
     304             : fail:
     305           0 :     if (ctx->internal->hw_type->frames_uninit)
     306           0 :         ctx->internal->hw_type->frames_uninit(ctx);
     307           0 :     return ret;
     308             : }
     309             : 
     310           0 : int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref,
     311             :                                     enum AVHWFrameTransferDirection dir,
     312             :                                     enum AVPixelFormat **formats, int flags)
     313             : {
     314           0 :     AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
     315             : 
     316           0 :     if (!ctx->internal->hw_type->transfer_get_formats)
     317           0 :         return AVERROR(ENOSYS);
     318             : 
     319           0 :     return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats);
     320             : }
     321             : 
     322           0 : static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
     323             : {
     324           0 :     AVHWFramesContext *ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
     325             :     AVFrame *frame_tmp;
     326           0 :     int ret = 0;
     327             : 
     328           0 :     frame_tmp = av_frame_alloc();
     329           0 :     if (!frame_tmp)
     330           0 :         return AVERROR(ENOMEM);
     331             : 
     332             :     /* if the format is set, use that
     333             :      * otherwise pick the first supported one */
     334           0 :     if (dst->format >= 0) {
     335           0 :         frame_tmp->format = dst->format;
     336             :     } else {
     337             :         enum AVPixelFormat *formats;
     338             : 
     339           0 :         ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx,
     340             :                                               AV_HWFRAME_TRANSFER_DIRECTION_FROM,
     341             :                                               &formats, 0);
     342           0 :         if (ret < 0)
     343           0 :             goto fail;
     344           0 :         frame_tmp->format = formats[0];
     345           0 :         av_freep(&formats);
     346             :     }
     347           0 :     frame_tmp->width  = ctx->width;
     348           0 :     frame_tmp->height = ctx->height;
     349             : 
     350           0 :     ret = av_frame_get_buffer(frame_tmp, 32);
     351           0 :     if (ret < 0)
     352           0 :         goto fail;
     353             : 
     354           0 :     ret = av_hwframe_transfer_data(frame_tmp, src, flags);
     355           0 :     if (ret < 0)
     356           0 :         goto fail;
     357             : 
     358           0 :     frame_tmp->width  = src->width;
     359           0 :     frame_tmp->height = src->height;
     360             : 
     361           0 :     av_frame_move_ref(dst, frame_tmp);
     362             : 
     363             : fail:
     364           0 :     av_frame_free(&frame_tmp);
     365           0 :     return ret;
     366             : }
     367             : 
     368           0 : int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
     369             : {
     370             :     AVHWFramesContext *ctx;
     371             :     int ret;
     372             : 
     373           0 :     if (!dst->buf[0])
     374           0 :         return transfer_data_alloc(dst, src, flags);
     375             : 
     376           0 :     if (src->hw_frames_ctx) {
     377           0 :         ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
     378             : 
     379           0 :         ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
     380           0 :         if (ret < 0)
     381           0 :             return ret;
     382           0 :     } else if (dst->hw_frames_ctx) {
     383           0 :         ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
     384             : 
     385           0 :         ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
     386           0 :         if (ret < 0)
     387           0 :             return ret;
     388             :     } else
     389           0 :         return AVERROR(ENOSYS);
     390             : 
     391           0 :     return 0;
     392             : }
     393             : 
     394           0 : int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
     395             : {
     396           0 :     AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
     397             :     int ret;
     398             : 
     399           0 :     if (!ctx->internal->hw_type->frames_get_buffer)
     400           0 :         return AVERROR(ENOSYS);
     401             : 
     402           0 :     if (!ctx->pool)
     403           0 :         return AVERROR(EINVAL);
     404             : 
     405           0 :     frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
     406           0 :     if (!frame->hw_frames_ctx)
     407           0 :         return AVERROR(ENOMEM);
     408             : 
     409           0 :     ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame);
     410           0 :     if (ret < 0) {
     411           0 :         av_buffer_unref(&frame->hw_frames_ctx);
     412           0 :         return ret;
     413             :     }
     414             : 
     415           0 :     return 0;
     416             : }
     417             : 
     418           0 : void *av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
     419             : {
     420           0 :     AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
     421           0 :     const HWContextType  *hw_type = ctx->internal->hw_type;
     422             : 
     423           0 :     if (hw_type->device_hwconfig_size == 0)
     424           0 :         return NULL;
     425             : 
     426           0 :     return av_mallocz(hw_type->device_hwconfig_size);
     427             : }
     428             : 
     429           0 : AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,
     430             :                                                            const void *hwconfig)
     431             : {
     432           0 :     AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
     433           0 :     const HWContextType  *hw_type = ctx->internal->hw_type;
     434             :     AVHWFramesConstraints *constraints;
     435             : 
     436           0 :     if (!hw_type->frames_get_constraints)
     437           0 :         return NULL;
     438             : 
     439           0 :     constraints = av_mallocz(sizeof(*constraints));
     440           0 :     if (!constraints)
     441           0 :         return NULL;
     442             : 
     443           0 :     constraints->min_width = constraints->min_height = 0;
     444           0 :     constraints->max_width = constraints->max_height = INT_MAX;
     445             : 
     446           0 :     if (hw_type->frames_get_constraints(ctx, hwconfig, constraints) >= 0) {
     447           0 :         return constraints;
     448             :     } else {
     449           0 :         av_hwframe_constraints_free(&constraints);
     450           0 :         return NULL;
     451             :     }
     452             : }
     453             : 
     454           0 : void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
     455             : {
     456           0 :     if (*constraints) {
     457           0 :         av_freep(&(*constraints)->valid_hw_formats);
     458           0 :         av_freep(&(*constraints)->valid_sw_formats);
     459             :     }
     460           0 :     av_freep(constraints);
     461           0 : }
     462             : 
     463           0 : int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type,
     464             :                            const char *device, AVDictionary *opts, int flags)
     465             : {
     466           0 :     AVBufferRef *device_ref = NULL;
     467             :     AVHWDeviceContext *device_ctx;
     468           0 :     int ret = 0;
     469             : 
     470           0 :     device_ref = av_hwdevice_ctx_alloc(type);
     471           0 :     if (!device_ref) {
     472           0 :         ret = AVERROR(ENOMEM);
     473           0 :         goto fail;
     474             :     }
     475           0 :     device_ctx = (AVHWDeviceContext*)device_ref->data;
     476             : 
     477           0 :     if (!device_ctx->internal->hw_type->device_create) {
     478           0 :         ret = AVERROR(ENOSYS);
     479           0 :         goto fail;
     480             :     }
     481             : 
     482           0 :     ret = device_ctx->internal->hw_type->device_create(device_ctx, device,
     483             :                                                        opts, flags);
     484           0 :     if (ret < 0)
     485           0 :         goto fail;
     486             : 
     487           0 :     ret = av_hwdevice_ctx_init(device_ref);
     488           0 :     if (ret < 0)
     489           0 :         goto fail;
     490             : 
     491           0 :     *pdevice_ref = device_ref;
     492           0 :     return 0;
     493             : fail:
     494           0 :     av_buffer_unref(&device_ref);
     495           0 :     *pdevice_ref = NULL;
     496           0 :     return ret;
     497             : }

Generated by: LCOV version 1.12