LCOV - code coverage report
Current view: top level - filters - ff_rescale.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 154 201 76.6 %
Date: 2021-04-29 23:48:07 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2018-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / ffmpeg video rescaler filter
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/setup.h>
      27             : 
      28             : #ifdef GPAC_HAS_FFMPEG
      29             : 
      30             : #include "ff_common.h"
      31             : 
      32             : typedef struct
      33             : {
      34             :         //options
      35             :         GF_PropVec2i osize;
      36             :         u32 ofmt, scale;
      37             :         Double p1, p2;
      38             :         Bool ofr;
      39             :         u32 brightness, saturation, contrast;
      40             :         GF_PropIntList otable, itable;
      41             :         //internal data
      42             :         Bool initialized;
      43             : 
      44             :         GF_FilterPid *ipid, *opid;
      45             :         u32 w, h, stride, s_pfmt;
      46             :         GF_Fraction ar;
      47             :         Bool passthrough;
      48             : 
      49             :         struct SwsContext *swscaler;
      50             : 
      51             :         u32 dst_stride[5];
      52             :         u32 src_stride[5];
      53             :         u32 nb_planes, nb_src_planes, out_size, out_src_size, src_uv_height, dst_uv_height, ow, oh;
      54             : 
      55             :         u32 swap_idx_1, swap_idx_2;
      56             :         Bool fullrange;
      57             : } GF_FFSWScaleCtx;
      58             : 
      59        2976 : static GF_Err ffsws_process(GF_Filter *filter)
      60             : {
      61             :         const char *data;
      62             :         u8 *output;
      63             :         u32 osize;
      64             :         s32 res;
      65             :         u8 *src_planes[5];
      66             :         u8 *dst_planes[5];
      67             :         GF_FilterPacket *dst_pck;
      68             :         GF_FilterFrameInterface *frame_ifce;
      69        2976 :         GF_FFSWScaleCtx *ctx = gf_filter_get_udta(filter);
      70             :         GF_FilterPacket *pck;
      71             : 
      72        2976 :         pck = gf_filter_pid_get_packet(ctx->ipid);
      73             : 
      74        2976 :         if (!pck) {
      75          70 :                 if (gf_filter_pid_is_eos(ctx->ipid)) {
      76          62 :                         gf_filter_pid_set_eos(ctx->opid);
      77          62 :                         return GF_EOS;
      78             :                 }
      79             :                 return GF_OK;
      80             :         }
      81             : 
      82        2906 :         if (ctx->passthrough) {
      83         173 :                 gf_filter_pck_forward(pck, ctx->opid);
      84         173 :                 gf_filter_pid_drop_packet(ctx->ipid);
      85         173 :                 return GF_OK;
      86             :         }
      87             :         //not yet configured
      88        2733 :         if (!ctx->ofmt && !ctx->ow && !ctx->oh)
      89             :                 return GF_OK;
      90             : 
      91        2733 :         if (!ctx->swscaler) {
      92           0 :                 gf_filter_pid_drop_packet(ctx->ipid);
      93           0 :                 return GF_NOT_SUPPORTED;
      94             :         }
      95             : 
      96        2733 :         data = gf_filter_pck_get_data(pck, &osize);
      97        2733 :         frame_ifce = gf_filter_pck_get_frame_interface(pck);
      98             :         //we may have biffer input (padding) but shall not have smaller
      99        2733 :         if (osize && (ctx->out_src_size > osize) ) {
     100           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[FFSWS] Mismatched in source osize, expected %d got %d - stride issue ?\n", ctx->out_src_size, osize));
     101           0 :                 gf_filter_pid_drop_packet(ctx->ipid);
     102           0 :                 return GF_NOT_SUPPORTED;
     103             :         }
     104             : 
     105             :         memset(src_planes, 0, sizeof(src_planes));
     106             :         memset(dst_planes, 0, sizeof(dst_planes));
     107        2733 :         dst_pck = gf_filter_pck_new_alloc(ctx->opid, ctx->out_size, &output);
     108        2733 :         if (!dst_pck) return GF_OUT_OF_MEM;
     109             : 
     110        2733 :         gf_filter_pck_merge_properties(pck, dst_pck);
     111             : 
     112        2733 :         if (data) {
     113        2731 :                 src_planes[0] = (u8 *) data;
     114             : 
     115        2731 :                 if (ctx->nb_src_planes==1) {
     116        2719 :                 } else if (ctx->nb_src_planes==2) {
     117           0 :                         src_planes[1] = src_planes[0] + ctx->src_stride[0]*ctx->h;
     118        2719 :                 } else if (ctx->nb_src_planes==3) {
     119        2719 :                         src_planes[1] = src_planes[0] + ctx->src_stride[0] * ctx->h;
     120        2719 :                         src_planes[2] = src_planes[1] + ctx->src_stride[1] * ctx->src_uv_height;
     121           0 :                 } else if (ctx->nb_src_planes==4) {
     122           0 :                         src_planes[1] = src_planes[0] + ctx->src_stride[0] * ctx->h;
     123           0 :                         src_planes[2] = src_planes[1] + ctx->src_stride[1] * ctx->src_uv_height;
     124           0 :                         src_planes[3] = src_planes[2] + ctx->src_stride[2] * ctx->src_uv_height;
     125             :                 }
     126           2 :         } else if (frame_ifce && frame_ifce->get_plane) {
     127             :                 u32 i=0;
     128           2 :                 for (i=0; i<ctx->nb_src_planes; i++) {
     129           2 :                         if (frame_ifce->get_plane(frame_ifce, i, (const u8 **) &src_planes[i], &ctx->src_stride[i])!=GF_OK)
     130             :                                 break;
     131             :                 }
     132             :         } else {
     133           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[FFSWS] No data associated with packet, not supported\n"));
     134           0 :                 gf_filter_pid_drop_packet(ctx->ipid);
     135           0 :                 return GF_NOT_SUPPORTED;
     136             :         }
     137        2733 :         dst_planes[0] = output;
     138        2733 :         if (ctx->nb_planes==1) {
     139        1632 :         } else if (ctx->nb_planes==2) {
     140         108 :                 dst_planes[1] = output + ctx->dst_stride[0] * ctx->oh;
     141        1524 :         } else if (ctx->nb_planes==3) {
     142        1524 :                 dst_planes[1] = output + ctx->dst_stride[0] * ctx->oh;
     143        1524 :                 dst_planes[2] = dst_planes[1] + ctx->dst_stride[1]*ctx->dst_uv_height;
     144           0 :         } else if (ctx->nb_planes==4) {
     145           0 :                 dst_planes[1] = output + ctx->dst_stride[0] * ctx->oh;
     146           0 :                 dst_planes[2] = dst_planes[1] + ctx->dst_stride[1]*ctx->dst_uv_height;
     147           0 :                 dst_planes[3] = dst_planes[2] + ctx->dst_stride[2]*ctx->dst_uv_height;
     148             :         }
     149             : 
     150             :         //rescale the cropped frame
     151        2733 :         res = sws_scale(ctx->swscaler, (const u8**) src_planes, ctx->src_stride, 0, ctx->h, dst_planes, ctx->dst_stride);
     152        2733 :         if (res != ctx->oh) {
     153           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[FFSWS] Error during scale, expected height %d got %d\n", ctx->oh, res));
     154           0 :                 gf_filter_pid_drop_packet(ctx->ipid);
     155           0 :                 gf_filter_pck_discard(dst_pck);
     156           0 :                 return GF_NOT_SUPPORTED;
     157             :         }
     158             : 
     159        2733 :         if (ctx->swap_idx_1 || ctx->swap_idx_2) {
     160             :                 u32 i, j;
     161       13824 :                 for (i=0; i<ctx->h; i++) {
     162       13824 :                         u8 *dst = output + ctx->dst_stride[0]*i;
     163      898560 :                         for (j=0; j<ctx->dst_stride[0]; j+=4) {
     164      884736 :                                 u8 tmp = dst[ctx->swap_idx_1];
     165      884736 :                                 dst[ctx->swap_idx_1] = dst[ctx->swap_idx_2];
     166      884736 :                                 dst[ctx->swap_idx_2] = tmp;
     167      884736 :                                 dst += 4;
     168             :                         }
     169             :                 }
     170             :         }
     171             : 
     172        2733 :         gf_filter_pck_send(dst_pck);
     173        2733 :         gf_filter_pid_drop_packet(ctx->ipid);
     174        2733 :         return GF_OK;
     175             : }
     176             : 
     177         115 : static u32 get_sws_mode(u32 mode, u32 *has_param)
     178             : {
     179         115 :         switch (mode) {
     180             :         case 0: return SWS_FAST_BILINEAR;
     181           0 :         case 1: return SWS_BILINEAR;
     182         115 :         case 2: *has_param = 2; return SWS_BICUBIC;
     183           0 :         case 3: return SWS_X;
     184           0 :         case 4: return SWS_POINT;
     185           0 :         case 5: return SWS_AREA;
     186           0 :         case 6: return SWS_BICUBLIN;
     187           0 :         case 7: *has_param = 1; return SWS_GAUSS;
     188           0 :         case 8: return SWS_SINC;
     189           0 :         case 9: *has_param = 1; return SWS_LANCZOS;
     190           0 :         case 10: return SWS_SPLINE;
     191             :         default: break;
     192             :         }
     193           0 :         *has_param = 2;
     194           0 :         return SWS_BICUBIC;
     195             : }
     196             : 
     197         177 : static GF_Err ffsws_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     198             : {
     199             :         const GF_PropertyValue *p;
     200             :         u32 w, h, stride, ofmt;
     201             :         GF_Fraction sar;
     202             :         Bool fullrange=GF_FALSE;
     203             :         Double par[2], *par_p=NULL;
     204         177 :         GF_FFSWScaleCtx *ctx = gf_filter_get_udta(filter);
     205             : 
     206         177 :         if (is_remove) {
     207           0 :                 if (ctx->opid) {
     208           0 :                         gf_filter_pid_remove(ctx->opid);
     209           0 :                         ctx->opid = NULL;
     210             :                 }
     211             :                 return GF_OK;
     212             :         }
     213         177 :         if (! gf_filter_pid_check_caps(pid))
     214             :                 return GF_NOT_SUPPORTED;
     215             : 
     216         176 :         if (!ctx->opid) {
     217          62 :                 ctx->opid = gf_filter_pid_new(filter);
     218             :         }
     219             : 
     220         176 :         if (!ctx->ipid) {
     221          62 :                 ctx->ipid = pid;
     222             :         }
     223             : 
     224             :         //if nothing is set we, consider we run as an adaptation filter, wait for caps to be set to declare output
     225         176 :         if (!ctx->ofmt && !ctx->osize.x && !ctx->osize.y)
     226             :                 return GF_OK;
     227             : 
     228             : 
     229             : 
     230             :         w = h = ofmt = stride = 0;
     231         124 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_WIDTH);
     232         124 :         if (p) w = p->value.uint;
     233         124 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_HEIGHT);
     234         124 :         if (p) h = p->value.uint;
     235         124 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_STRIDE);
     236         124 :         if (p) stride = p->value.uint;
     237         124 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_PIXFMT);
     238         124 :         if (p) ofmt = p->value.uint;
     239         124 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAR);
     240         124 :         if (p) sar = p->value.frac;
     241             :         else sar.den = sar.num = 1;
     242             : 
     243         124 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_COLR_RANGE);
     244         124 :         if (p) fullrange = p->value.boolean;
     245             : 
     246             :         //ctx->ofmt may be 0 if the filter is instantiated dynamically, we haven't yet been called for reconfigure
     247         124 :         if (!w || !h || !ofmt) {
     248             :                 return GF_OK;
     249             :         }
     250             :         //copy properties at init or reconfig
     251         116 :         gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
     252             : 
     253         116 :         if (!ctx->ofmt)
     254           9 :                 ctx->ofmt = ofmt;
     255             : 
     256         116 :         ctx->passthrough = GF_FALSE;
     257             : 
     258         116 :         ctx->ow = ctx->osize.x ? ctx->osize.x : w;
     259         116 :         ctx->oh = ctx->osize.y ? ctx->osize.y : h;
     260         116 :         if ((ctx->w == w) && (ctx->h == h) && (ctx->s_pfmt == ofmt) && (ctx->stride == stride) && (ctx->fullrange==fullrange)) {
     261             :                 //nothing to reconfigure
     262             :         }
     263             :         //passthrough mode
     264         116 :         else if ((ctx->ow == w) && (ctx->oh == h) && (ctx->s_pfmt == ofmt) && (ofmt==ctx->ofmt) && (ctx->ofr == fullrange)
     265           1 :                 && !ctx->brightness && !ctx->saturation && !ctx->contrast && (ctx->otable.nb_items!=4) && (ctx->itable.nb_items!=4)
     266             :         ) {
     267           1 :                 memset(ctx->dst_stride, 0, sizeof(ctx->dst_stride));
     268           1 :                 gf_pixel_get_size_info(ctx->ofmt, ctx->ow, ctx->oh, &ctx->out_size, &ctx->dst_stride[0], &ctx->dst_stride[1], &ctx->nb_planes, &ctx->dst_uv_height);
     269           1 :                 ctx->passthrough = GF_TRUE;
     270             :         } else {
     271         115 :                 u32 nb_par = 0;
     272             :                 nb_par = 0;
     273             :                 Bool res;
     274         115 :                 u32 mode = get_sws_mode(ctx->scale, &nb_par);
     275         115 :                 u32 ff_src_pfmt = ffmpeg_pixfmt_from_gpac(ofmt);
     276         115 :                 u32 ff_dst_pfmt = ffmpeg_pixfmt_from_gpac(ctx->ofmt);
     277             : 
     278             :                 //get layout info for source
     279         115 :                 memset(ctx->src_stride, 0, sizeof(ctx->src_stride));
     280         115 :                 if (ctx->stride) ctx->src_stride[0] = ctx->stride;
     281             : 
     282             : 
     283         115 :                 res = gf_pixel_get_size_info(ofmt, w, h, &ctx->out_src_size, &ctx->src_stride[0], &ctx->src_stride[1], &ctx->nb_src_planes, &ctx->src_uv_height);
     284         115 :                 if (!res) {
     285           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[FFSWS] Failed to query source pixel format characteristics\n"));
     286           0 :                         return GF_NOT_SUPPORTED;
     287             :                 }
     288         115 :                 if (ctx->nb_src_planes==3) ctx->src_stride[2] = ctx->src_stride[1];
     289         115 :                 if (ctx->nb_src_planes==4) ctx->src_stride[3] = ctx->src_stride[0];
     290             : 
     291             :                 //get layout info for dest
     292         115 :                 memset(ctx->dst_stride, 0, sizeof(ctx->dst_stride));
     293         115 :                 res = gf_pixel_get_size_info(ctx->ofmt, ctx->ow, ctx->oh, &ctx->out_size, &ctx->dst_stride[0], &ctx->dst_stride[1], &ctx->nb_planes, &ctx->dst_uv_height);
     294         115 :                 if (!res) {
     295           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[FFSWS] Failed to query output pixel format characteristics\n"));
     296             :                         return GF_NOT_SUPPORTED;
     297             :                 }
     298         115 :                 if (ctx->nb_planes==3) ctx->dst_stride[2] = ctx->dst_stride[1];
     299         115 :                 if (ctx->nb_planes==4) ctx->dst_stride[3] = ctx->dst_stride[0];
     300             : 
     301             : 
     302         115 :                 if (nb_par) {
     303         115 :                         if ((nb_par==1) && (ctx->p1!=GF_MAX_DOUBLE) ) {
     304           0 :                                 par[0] = ctx->p1;
     305           0 :                                 par_p = (Double *)par;
     306         115 :                         } else if ((nb_par==2) && (ctx->p1!=GF_MAX_DOUBLE) && (ctx->p2!=GF_MAX_DOUBLE)) {
     307           0 :                                 par[0] = ctx->p1;
     308           0 :                                 par[1] = ctx->p2;
     309             :                                 par_p = (Double *)par;
     310             :                         }
     311             :                 }
     312             :                 //create/get a swscale context
     313         115 :                 ctx->swscaler = sws_getCachedContext(ctx->swscaler, w, h, ff_src_pfmt, ctx->ow, ctx->oh, ff_dst_pfmt, mode, NULL, NULL, par_p);
     314             : 
     315         115 :                 if (!ctx->swscaler) {
     316             : #ifndef GPAC_DISABLE_LOG
     317           0 :                         Bool in_ok = sws_isSupportedInput(ff_src_pfmt);
     318           0 :                         Bool out_ok = sws_isSupportedInput(ff_dst_pfmt);
     319           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[FFSWS] Cannot allocate context for required format - input %s output %s\n", in_ok ? "OK" : "not supported" , out_ok ? "OK" : "not supported"));
     320             : #endif
     321             :                         return GF_NOT_SUPPORTED;
     322             :                 }
     323             :                 //set colorspace
     324         115 :                 if (fullrange || ctx->ofr || ctx->brightness || ctx->saturation || ctx->contrast || (ctx->itable.nb_items==4) || (ctx->otable.nb_items==4)) {
     325             :                         s32 in_full, out_full, brightness, contrast, saturation;
     326             :                         s32 *inv_table, *table;
     327             : 
     328           3 :                         sws_getColorspaceDetails(ctx->swscaler, &inv_table, &in_full, &table, &out_full, &brightness, &contrast, &saturation);
     329           3 :                         in_full = fullrange;
     330           3 :                         out_full = ctx->ofr;
     331           3 :                         if (ctx->brightness) brightness = ctx->brightness;
     332           3 :                         if (ctx->saturation) saturation = ctx->saturation;
     333           3 :                         if (ctx->contrast) contrast = ctx->contrast;
     334             : 
     335           3 :                         if (ctx->itable.nb_items==4)
     336           0 :                                 inv_table = ctx->itable.vals;
     337           3 :                         if (ctx->otable.nb_items==4)
     338           0 :                                 table = ctx->otable.vals;
     339             : 
     340           3 :                         sws_setColorspaceDetails(ctx->swscaler, (const int *) inv_table, in_full, (const int *)table, out_full, brightness, contrast, saturation);
     341             :                 }
     342         115 :                 ctx->w = w;
     343         115 :                 ctx->h = h;
     344         115 :                 ctx->s_pfmt = ofmt;
     345         115 :                 ctx->fullrange = fullrange;
     346         115 :                 GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[FFSWS] Setup rescaler from %dx%d fmt %s to %dx%d fmt %s\n", w, h, gf_pixel_fmt_name(ofmt), ctx->ow, ctx->oh, gf_pixel_fmt_name(ctx->ofmt)));
     347             : 
     348         115 :                 ctx->swap_idx_1 = ctx->swap_idx_2 = 0;
     349             :                 //if same source / dest pixel format, don'( swap UV components
     350         115 :                 if (ctx->s_pfmt != ctx->ofmt) {
     351          93 :                         if (ctx->ofmt==GF_PIXEL_VYUY) {
     352             :                                 ctx->swap_idx_1 = 0;
     353           4 :                                 ctx->swap_idx_2 = 2;
     354             :                         }
     355          89 :                         else if (ctx->ofmt==GF_PIXEL_YVYU) {
     356           4 :                                 ctx->swap_idx_1 = 1;
     357           4 :                                 ctx->swap_idx_2 = 3;
     358             :                         }
     359             :                 }
     360             :         }
     361             : 
     362         116 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(ctx->ow));
     363         116 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(ctx->oh));
     364         116 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE, &PROP_UINT(ctx->dst_stride[0]));
     365         116 :         if (ctx->nb_planes>1)
     366          57 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE_UV, &PROP_UINT(ctx->dst_stride[1]));
     367             : 
     368         116 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW));
     369         116 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT, &PROP_UINT(ctx->ofmt));
     370         116 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAR, &PROP_FRAC(sar) );
     371         116 :         return GF_OK;
     372             : }
     373             : 
     374          62 : static void ffsws_finalize(GF_Filter *filter)
     375             : {
     376          62 :         GF_FFSWScaleCtx *ctx = gf_filter_get_udta(filter);
     377          62 :         if (ctx->swscaler) sws_freeContext(ctx->swscaler);
     378          62 :         return;
     379             : }
     380             : 
     381             : 
     382          58 : static GF_Err ffsws_reconfigure_output(GF_Filter *filter, GF_FilterPid *pid)
     383             : {
     384             :         const GF_PropertyValue *p;
     385          58 :         GF_FFSWScaleCtx *ctx = gf_filter_get_udta(filter);
     386          58 :         if (ctx->opid != pid) return GF_BAD_PARAM;
     387             : 
     388          58 :         p = gf_filter_pid_caps_query(pid, GF_PROP_PID_WIDTH);
     389          58 :         if (p) ctx->osize.x = p->value.uint;
     390             : 
     391          58 :         p = gf_filter_pid_caps_query(pid, GF_PROP_PID_HEIGHT);
     392          58 :         if (p) ctx->osize.y = p->value.uint;
     393             : 
     394          58 :         p = gf_filter_pid_caps_query(pid, GF_PROP_PID_PIXFMT);
     395          58 :         if (p) ctx->ofmt = p->value.uint;
     396          58 :         return ffsws_configure_pid(filter, ctx->ipid, GF_FALSE);
     397             : }
     398             : 
     399             : 
     400             : #define OFFS(_n)        #_n, offsetof(GF_FFSWScaleCtx, _n)
     401             : static GF_FilterArgs FFSWSArgs[] =
     402             : {
     403             :         { OFFS(osize), "osize of output video. When not set, input osize is used", GF_PROP_VEC2I, NULL, NULL, 0},
     404             :         { OFFS(ofmt), "pixel format for output video. When not set, input format is used", GF_PROP_PIXFMT, "none", NULL, 0},
     405             :         { OFFS(scale), "scaling mode - see filter info", GF_PROP_UINT, "bicubic", "fastbilinear|bilinear|bicubic|X|point|area|bicublin|gauss|sinc|lanzcos|spline", GF_FS_ARG_HINT_ADVANCED},
     406             :         { OFFS(p1), "scaling algo param1 - see filter info", GF_PROP_DOUBLE, "+I", NULL, GF_FS_ARG_HINT_ADVANCED},
     407             :         { OFFS(p2), "scaling algo param2 - see filter info", GF_PROP_DOUBLE, "+I", NULL, GF_FS_ARG_HINT_ADVANCED},
     408             : 
     409             :         { OFFS(ofr), "force output full range", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT},
     410             :         { OFFS(brightness), "16.16 fixed point brightness correction, 0 means use default", GF_PROP_BOOL, "0", NULL, GF_FS_ARG_HINT_EXPERT},
     411             :         { OFFS(contrast), "16.16 fixed point brightness correction, 0 means use default", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_EXPERT},
     412             :         { OFFS(saturation), "16.16 fixed point brightness correction, 0 means use default", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_EXPERT},
     413             :         { OFFS(otable), "the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x], use default if not set", GF_PROP_SINT_LIST, NULL, NULL, GF_FS_ARG_HINT_EXPERT},
     414             :         { OFFS(itable), "the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x], use default if not set", GF_PROP_SINT_LIST, NULL, NULL, GF_FS_ARG_HINT_EXPERT},
     415             :         {0}
     416             : };
     417             : 
     418             : static const GF_FilterCapability FFSWSCaps[] =
     419             : {
     420             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
     421             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_RAW)
     422             : };
     423             : 
     424             : 
     425             : GF_FilterRegister FFSWSRegister = {
     426             :         .name = "ffsws",
     427             :         .version=LIBSWSCALE_IDENT,
     428             :         GF_FS_SET_DESCRIPTION("FFMPEG video rescaler")
     429             :         GF_FS_SET_HELP("For bicubic, to tune the shape of the basis function, [-p1]() tunes f(1) and [-p2]() f´(1)\n"\
     430             :                                 "For gauss [-p1]() tunes the exponent and thus cutoff frequency\n"\
     431             :                                 "For lanczos [-p1]() tunes the width of the window function"\
     432             :                                 "\nSee FFMPEG documentation (https://ffmpeg.org/documentation.html) for more details")
     433             : 
     434             :         .private_size = sizeof(GF_FFSWScaleCtx),
     435             :         .args = FFSWSArgs,
     436             :         .configure_pid = ffsws_configure_pid,
     437             :         SETCAPS(FFSWSCaps),
     438             :         .finalize = ffsws_finalize,
     439             :         .process = ffsws_process,
     440             :         .reconfigure_output = ffsws_reconfigure_output,
     441             : };
     442             : 
     443             : #else
     444             : #include <gpac/filters.h>
     445             : #endif //GPAC_HAS_FFMPEG
     446             : 
     447        2877 : const GF_FilterRegister *ffsws_register(GF_FilterSession *session)
     448             : {
     449             : #ifdef GPAC_HAS_FFMPEG
     450        2877 :         FFSWSArgs[1].min_max_enum = gf_pixel_fmt_all_names();
     451        2877 :         return &FFSWSRegister;
     452             : #else
     453             :         return NULL;
     454             : #endif
     455             : }
     456             : 

Generated by: LCOV version 1.13