LCOV - code coverage report
Current view: top level - libavfilter - vf_hwdownload.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 87 0.0 %
Date: 2017-12-17 16:07:53 Functions: 0 5 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 "libavutil/buffer.h"
      20             : #include "libavutil/hwcontext.h"
      21             : #include "libavutil/log.h"
      22             : #include "libavutil/mem.h"
      23             : #include "libavutil/opt.h"
      24             : #include "libavutil/pixdesc.h"
      25             : 
      26             : #include "avfilter.h"
      27             : #include "formats.h"
      28             : #include "internal.h"
      29             : #include "video.h"
      30             : 
      31             : typedef struct HWDownloadContext {
      32             :     const AVClass *class;
      33             : 
      34             :     AVBufferRef       *hwframes_ref;
      35             :     AVHWFramesContext *hwframes;
      36             : } HWDownloadContext;
      37             : 
      38           0 : static int hwdownload_query_formats(AVFilterContext *avctx)
      39             : {
      40           0 :     AVFilterFormats  *infmts = NULL;
      41           0 :     AVFilterFormats *outfmts = NULL;
      42             :     const AVPixFmtDescriptor *desc;
      43             :     int err;
      44             : 
      45           0 :     for (desc = av_pix_fmt_desc_next(NULL); desc;
      46           0 :          desc = av_pix_fmt_desc_next(desc)) {
      47           0 :         if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
      48           0 :             err = ff_add_format(&infmts,  av_pix_fmt_desc_get_id(desc));
      49             :         else
      50           0 :             err = ff_add_format(&outfmts, av_pix_fmt_desc_get_id(desc));
      51           0 :         if (err) {
      52           0 :             ff_formats_unref(&infmts);
      53           0 :             ff_formats_unref(&outfmts);
      54           0 :             return err;
      55             :         }
      56             :     }
      57             : 
      58           0 :     if ((err = ff_formats_ref(infmts,  &avctx->inputs[0]->out_formats)) < 0 ||
      59           0 :         (err = ff_formats_ref(outfmts, &avctx->outputs[0]->in_formats)) < 0)
      60           0 :         return err;
      61             : 
      62           0 :     return 0;
      63             : }
      64             : 
      65           0 : static int hwdownload_config_input(AVFilterLink *inlink)
      66             : {
      67           0 :     AVFilterContext *avctx = inlink->dst;
      68           0 :     HWDownloadContext *ctx = avctx->priv;
      69             : 
      70           0 :     av_buffer_unref(&ctx->hwframes_ref);
      71             : 
      72           0 :     if (!inlink->hw_frames_ctx) {
      73           0 :         av_log(ctx, AV_LOG_ERROR, "The input must have a hardware frame "
      74             :                "reference.\n");
      75           0 :         return AVERROR(EINVAL);
      76             :     }
      77             : 
      78           0 :     ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx);
      79           0 :     if (!ctx->hwframes_ref)
      80           0 :         return AVERROR(ENOMEM);
      81             : 
      82           0 :     ctx->hwframes = (AVHWFramesContext*)ctx->hwframes_ref->data;
      83             : 
      84           0 :     return 0;
      85             : }
      86             : 
      87           0 : static int hwdownload_config_output(AVFilterLink *outlink)
      88             : {
      89           0 :     AVFilterContext *avctx = outlink->src;
      90           0 :     AVFilterLink *inlink   = avctx->inputs[0];
      91           0 :     HWDownloadContext *ctx = avctx->priv;
      92             :     enum AVPixelFormat *formats;
      93             :     int err, i, found;
      94             : 
      95           0 :     if (!ctx->hwframes_ref)
      96           0 :         return AVERROR(EINVAL);
      97             : 
      98           0 :     err = av_hwframe_transfer_get_formats(ctx->hwframes_ref,
      99             :                                           AV_HWFRAME_TRANSFER_DIRECTION_FROM,
     100             :                                           &formats, 0);
     101           0 :     if (err < 0)
     102           0 :         return err;
     103             : 
     104           0 :     found = 0;
     105           0 :     for (i = 0; formats[i] != AV_PIX_FMT_NONE; i++) {
     106           0 :         if (formats[i] == outlink->format) {
     107           0 :             found = 1;
     108           0 :             break;
     109             :         }
     110             :     }
     111           0 :     av_freep(&formats);
     112             : 
     113           0 :     if (!found) {
     114           0 :         av_log(ctx, AV_LOG_ERROR, "Invalid output format %s for hwframe "
     115           0 :                "download.\n", av_get_pix_fmt_name(outlink->format));
     116           0 :         return AVERROR(EINVAL);
     117             :     }
     118             : 
     119           0 :     outlink->w = inlink->w;
     120           0 :     outlink->h = inlink->h;
     121             : 
     122           0 :     return 0;
     123             : }
     124             : 
     125           0 : static int hwdownload_filter_frame(AVFilterLink *link, AVFrame *input)
     126             : {
     127           0 :     AVFilterContext *avctx = link->dst;
     128           0 :     AVFilterLink  *outlink = avctx->outputs[0];
     129           0 :     HWDownloadContext *ctx = avctx->priv;
     130           0 :     AVFrame *output = NULL;
     131             :     int err;
     132             : 
     133           0 :     if (!ctx->hwframes_ref || !input->hw_frames_ctx) {
     134           0 :         av_log(ctx, AV_LOG_ERROR, "Input frames must have hardware context.\n");
     135           0 :         err = AVERROR(EINVAL);
     136           0 :         goto fail;
     137             :     }
     138           0 :     if ((void*)ctx->hwframes != input->hw_frames_ctx->data) {
     139           0 :         av_log(ctx, AV_LOG_ERROR, "Input frame is not the in the configured "
     140             :                "hwframe context.\n");
     141           0 :         err = AVERROR(EINVAL);
     142           0 :         goto fail;
     143             :     }
     144             : 
     145           0 :     output = ff_get_video_buffer(outlink, ctx->hwframes->width,
     146           0 :                                  ctx->hwframes->height);
     147           0 :     if (!output) {
     148           0 :         err = AVERROR(ENOMEM);
     149           0 :         goto fail;
     150             :     }
     151             : 
     152           0 :     err = av_hwframe_transfer_data(output, input, 0);
     153           0 :     if (err < 0) {
     154           0 :         av_log(ctx, AV_LOG_ERROR, "Failed to download frame: %d.\n", err);
     155           0 :         goto fail;
     156             :     }
     157             : 
     158           0 :     output->width  = outlink->w;
     159           0 :     output->height = outlink->h;
     160             : 
     161           0 :     err = av_frame_copy_props(output, input);
     162           0 :     if (err < 0)
     163           0 :         goto fail;
     164             : 
     165           0 :     av_frame_free(&input);
     166             : 
     167           0 :     return ff_filter_frame(avctx->outputs[0], output);
     168             : 
     169           0 : fail:
     170           0 :     av_frame_free(&input);
     171           0 :     av_frame_free(&output);
     172           0 :     return err;
     173             : }
     174             : 
     175           0 : static av_cold void hwdownload_uninit(AVFilterContext *avctx)
     176             : {
     177           0 :     HWDownloadContext *ctx = avctx->priv;
     178             : 
     179           0 :     av_buffer_unref(&ctx->hwframes_ref);
     180           0 : }
     181             : 
     182             : static const AVClass hwdownload_class = {
     183             :     .class_name = "hwdownload",
     184             :     .item_name  = av_default_item_name,
     185             :     .option     = NULL,
     186             :     .version    = LIBAVUTIL_VERSION_INT,
     187             : };
     188             : 
     189             : static const AVFilterPad hwdownload_inputs[] = {
     190             :     {
     191             :         .name         = "default",
     192             :         .type         = AVMEDIA_TYPE_VIDEO,
     193             :         .config_props = hwdownload_config_input,
     194             :         .filter_frame = hwdownload_filter_frame,
     195             :     },
     196             :     { NULL }
     197             : };
     198             : 
     199             : static const AVFilterPad hwdownload_outputs[] = {
     200             :     {
     201             :         .name         = "default",
     202             :         .type         = AVMEDIA_TYPE_VIDEO,
     203             :         .config_props = hwdownload_config_output,
     204             :     },
     205             :     { NULL }
     206             : };
     207             : 
     208             : AVFilter ff_vf_hwdownload = {
     209             :     .name          = "hwdownload",
     210             :     .description   = NULL_IF_CONFIG_SMALL("Download a hardware frame to a normal frame"),
     211             :     .uninit        = hwdownload_uninit,
     212             :     .query_formats = hwdownload_query_formats,
     213             :     .priv_size     = sizeof(HWDownloadContext),
     214             :     .priv_class    = &hwdownload_class,
     215             :     .inputs        = hwdownload_inputs,
     216             :     .outputs       = hwdownload_outputs,
     217             :     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
     218             : };

Generated by: LCOV version 1.13