LCOV - code coverage report
Current view: top level - filters - vflip.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 184 218 84.4 %
Date: 2021-04-29 23:48:07 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Samir Mustapha - Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2019-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / video flip 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/filters.h>
      27             : #include <gpac/list.h>
      28             : #include <gpac/constants.h>
      29             : #include <gpac/network.h>
      30             : 
      31             : typedef struct
      32             : {
      33             :         //options
      34             :         u32 mode;
      35             : 
      36             :         //internal data
      37             :         Bool initialized;
      38             : 
      39             :         GF_FilterPid *ipid, *opid;
      40             :         u32 w, h, stride, s_pfmt;
      41             :         u32 bps;
      42             :         GF_Fraction ar;
      43             :         Bool passthrough;
      44             :         u32 dst_width, dst_height;
      45             : 
      46             :         u32 dst_stride[5];
      47             :         u32 src_stride[5];
      48             :         u32 nb_planes, nb_src_planes, out_size, out_src_size, src_uv_height, dst_uv_height;
      49             : 
      50             :         Bool use_reference;
      51             :         Bool packed_422;
      52             : 
      53             : 
      54             :         char *line_buffer_vf; //vertical flip
      55             :         char *line_buffer_hf; //horizontal flip
      56             : 
      57             : } GF_VFlipCtx;
      58             : 
      59             : enum
      60             : {
      61             :         VFLIP_OFF = 0,
      62             :         VFLIP_VERT,
      63             :         VFLIP_HORIZ,
      64             :         VFLIP_BOTH,
      65             : };
      66             : 
      67             : 
      68             : 
      69      884736 : static void swap_2Ys_YUVpixel(GF_VFlipCtx *ctx, u8 *line_src, u8 *line_dst, u32 FourBytes_start_index)
      70             : {
      71             :         u32 isFirstY_indexOne;
      72      884736 :         switch (ctx->s_pfmt) {
      73             :         case GF_PIXEL_YUYV:
      74             :         case GF_PIXEL_YVYU:
      75             :                 isFirstY_indexOne= (u32) 0;
      76             :                 break;
      77      442368 :         case GF_PIXEL_UYVY:
      78             :         case GF_PIXEL_VYUY:
      79             :                 isFirstY_indexOne= (u32) 1;
      80             :                 break;
      81             :         default:
      82             :                 return;
      83             :         }
      84             : 
      85             :         //Y2_dst = Y1_src
      86      884736 :         line_dst[FourBytes_start_index + 2 + isFirstY_indexOne]=line_src[FourBytes_start_index + 0 + isFirstY_indexOne];
      87             : 
      88             :         //Y1_dst = Y2_src
      89      884736 :         line_dst[FourBytes_start_index + 0 + isFirstY_indexOne]=line_src[FourBytes_start_index + 2 + isFirstY_indexOne];
      90             : }
      91             : 
      92      110592 : static void horizontal_flip_per_line(GF_VFlipCtx *ctx, u8 *line_src, u8 *line_dst, u32 plane_idx, u32 wiB)
      93             : {
      94             :         u32 j, line_size = wiB;
      95             : 
      96      110592 :         if (ctx->s_pfmt == GF_PIXEL_RGB || ctx->s_pfmt == GF_PIXEL_BGR || ctx->s_pfmt == GF_PIXEL_XRGB || ctx->s_pfmt == GF_PIXEL_RGBX || ctx->s_pfmt == GF_PIXEL_XBGR || ctx->s_pfmt == GF_PIXEL_BGRX){
      97             :                 //to avoid "3*j > line_size - 3*j - 3" or "4*j > line_size - 4*j - 4"
      98             :                 //jmax=line_size/(2*3) or jmax=line_size/(2*4)
      99     1347840 :                 for (j=0; j < line_size/(2*ctx->bps); j++) {
     100             :                         u8 pix[4];
     101     1327104 :                         memcpy(pix, line_src + line_size - ctx->bps*(j+1), ctx->bps);
     102     1327104 :                         memcpy(line_dst + line_size - ctx->bps*(j+1), line_src + ctx->bps*j, ctx->bps);
     103     1327104 :                         memcpy(line_dst + ctx->bps*j, pix, ctx->bps);
     104             :                 }
     105       89856 :         } else if (ctx->packed_422) {
     106             :                 //If the source data is assigned to the output packet during the destination pack allocation
     107             :                 //i.e dst_planes[0]= src_planes[0], line_src is going to change while reading it as far as writing on line_dst=line_src
     108             :                 //To avoid this situation, ctx->line_buffer_hf keeps the values of line_src
     109       13824 :                 memcpy(ctx->line_buffer_hf, line_src, wiB);
     110             : 
     111             :                 //reversing of 4-bytes sequences
     112       13824 :                 u32 fourBytesSize = wiB/4;
     113      898560 :                 for (j=0; j < fourBytesSize; j++) {
     114             :                         //buffer = last 4 columns
     115      884736 :                         u32 last_4bytes_index = wiB-4-(4*j);
     116             :                         u32 p, first_4bytes_index = 4*j;
     117     4423680 :                         for (p = 0; p < 4; p++) {
     118     3538944 :                                 line_dst[first_4bytes_index+p] = ctx->line_buffer_hf[last_4bytes_index+p];
     119             :                         }
     120             :                         //exchanging of Ys within a yuv pixel
     121      884736 :                         swap_2Ys_YUVpixel(ctx, line_dst, line_dst, first_4bytes_index);
     122             :                 }
     123             :         } else {
     124             :                 //nv12/21
     125             :                 //second plane is U-plane={u1,v1, u2,v2...}
     126       76032 :                 if (ctx->nb_planes==2 && plane_idx==1){
     127        3456 :                         if (ctx->bps==1) {
     128             :                                 //to avoid "line_size - 2*j - 2 > 2*j", jmax=line_size/4
     129      110592 :                                 for (j=0; j < line_size/4; j++) {
     130             :                                         u8 u_comp, v_comp;
     131      110592 :                                         u_comp = line_src[line_size - 2*j - 2];
     132      110592 :                                         v_comp = line_src[line_size - 2*j - 1];
     133             : 
     134      110592 :                                         line_dst[line_size - 2*j - 2] = line_src[2*j];
     135      110592 :                                         line_dst[line_size - 2*j - 1] = line_src[2*j + 1];
     136             : 
     137      110592 :                                         line_dst[2*j] = u_comp;
     138      110592 :                                         line_dst[2*j + 1] = v_comp;
     139             :                                 }
     140             :                         } else {
     141           0 :                                 for (j=0; j < line_size/4; j++) {
     142             :                                         u16 u_comp, v_comp;
     143           0 :                                         u_comp = line_src[line_size - 2*j - 2];
     144           0 :                                         v_comp = line_src[line_size - 2*j - 1];
     145             : 
     146           0 :                                         ((u16 *)line_dst)[line_size - 2*j - 2] = ((u16 *)line_src)[2*j];
     147           0 :                                         ((u16 *)line_dst)[line_size - 2*j - 1] = ((u16 *)line_src)[2*j + 1];
     148             : 
     149           0 :                                         ((u16 *)line_dst)[2*j] = u_comp;
     150           0 :                                         ((u16 *)line_dst)[2*j + 1] = v_comp;
     151             :                                 }
     152             :                         }
     153       72576 :                 } else if (ctx->bps==1) {
     154       44928 :                         u32 wx = line_size/2;
     155             :                         u8 tmp;
     156     2477952 :                         for (j=0; j < wx; j++) {
     157             :                                 //tmp = last column
     158     2433024 :                                 tmp = line_src[line_size-1-j];
     159             : 
     160             :                                 //last column = first column
     161     2433024 :                                 line_dst[line_size-1-j] = line_src[j];
     162             : 
     163             :                                 //first column = tmp
     164     2433024 :                                 line_dst[j]=tmp;
     165             :                         }
     166             :                 } else {
     167       27648 :                         line_size /= 2;
     168       27648 :                         u32 wx = line_size/2;
     169             :                         u16 tmp;
     170     1465344 :                         for (j=0; j < wx; j++) {
     171             :                                 //tmp = last column
     172     1437696 :                                 tmp = (u16) ( ((u16 *)line_src) [line_size-1-j] );
     173             : 
     174             :                                 //last column = first column
     175     1437696 :                                 ((u16 *)line_dst) [line_size-1-j] = ((u16*)line_src)[j];
     176             : 
     177             :                                 //first column = tmp
     178     1437696 :                                 ((u16 *)line_dst) [j]=tmp;
     179             :                         }
     180             :                 }
     181             :         }
     182      110592 : }
     183             : 
     184         972 : static void horizontal_flip(GF_VFlipCtx *ctx, u8 *src_plane, u8 *dst_plane, u32 height, u32 plane_idx, u32 wiB, u32 *src_stride)
     185             : {
     186             :         u32 i;
     187      111564 :         for (i=0; i<height; i++) {
     188      110592 :                 u8 *src_first_line = src_plane + i * src_stride[plane_idx];
     189      110592 :                 u8 *dst_first_line = dst_plane + i * ctx->dst_stride[plane_idx];
     190             : 
     191      110592 :                 horizontal_flip_per_line(ctx, src_first_line, dst_first_line, plane_idx, wiB);
     192             :         }
     193         972 : }
     194             : 
     195         972 : static void vertical_flip(GF_VFlipCtx *ctx, u8 *src_plane, u8 *dst_plane, u32 height, u32 plane_idx, u32 wiB){
     196             :         u32 hy, i;
     197         972 :         hy = height/2;
     198       56268 :         for (i=0; i<hy; i++) {
     199       55296 :                 u8 *src_first_line = src_plane+ i*ctx->src_stride[plane_idx];
     200       55296 :                 u8 *src_last_line  = src_plane+ (height  - 1 - i) * ctx->src_stride[plane_idx];
     201             : 
     202       55296 :                 u8 *dst_first_line = dst_plane+ i*ctx->dst_stride[plane_idx];
     203       55296 :                 u8 *dst_last_line  = dst_plane+ (height  - 1 - i) * ctx->dst_stride[plane_idx];
     204             : 
     205       55296 :                 memcpy(ctx->line_buffer_vf, src_last_line, wiB);
     206             :                 memcpy(dst_last_line, src_first_line, wiB);
     207       55296 :                 memcpy(dst_first_line, ctx->line_buffer_vf, wiB);
     208             :         }
     209         972 : }
     210             : 
     211        2160 : static GF_Err vflip_process(GF_Filter *filter)
     212             : {
     213             :         const char *data;
     214             :         u8 *output;
     215             :         u32 size;
     216             :         u32 i;
     217             :         u32 wiB, height; //wiB: width in Bytes of a plane
     218             :         u8 *src_planes[5];
     219             :         u8 *dst_planes[5];
     220             :         GF_FilterPacket *dst_pck;
     221             :         GF_FilterFrameInterface *frame_ifce;
     222        2160 :         GF_VFlipCtx *ctx = gf_filter_get_udta(filter);
     223        2160 :         GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
     224             : 
     225        2160 :         if (!pck) {
     226        1080 :                 if (gf_filter_pid_is_eos(ctx->ipid)) {
     227          40 :                         gf_filter_pid_set_eos(ctx->opid);
     228          40 :                         return GF_EOS;
     229             :                 }
     230             :                 return GF_OK;
     231             :         }
     232             : 
     233        1080 :         if (ctx->passthrough) {
     234          27 :                 gf_filter_pck_forward(pck, ctx->opid);
     235          27 :                 gf_filter_pid_drop_packet(ctx->ipid);
     236          27 :                 return GF_OK;
     237             :         }
     238        1053 :         data = gf_filter_pck_get_data(pck, &size);
     239        1053 :         frame_ifce = gf_filter_pck_get_frame_interface(pck);
     240             : 
     241             :         memset(src_planes, 0, sizeof(src_planes));
     242             :         memset(dst_planes, 0, sizeof(dst_planes));
     243             : 
     244        1053 :         if (data) {
     245        1053 :                 src_planes[0] = (u8 *) data;
     246             : 
     247        1053 :                 if (ctx->nb_src_planes==1) {
     248         459 :                 } else if (ctx->nb_src_planes==2) {
     249         108 :                         src_planes[1] = src_planes[0] + ctx->src_stride[0]*ctx->h;
     250         351 :                 } else if (ctx->nb_src_planes==3) {
     251         351 :                         src_planes[1] = src_planes[0] + ctx->src_stride[0] * ctx->h;
     252         351 :                         src_planes[2] = src_planes[1] + ctx->src_stride[1] * ctx->src_uv_height;
     253           0 :                 } else if (ctx->nb_src_planes==4) {
     254           0 :                         src_planes[1] = src_planes[0] + ctx->src_stride[0] * ctx->h;
     255           0 :                         src_planes[2] = src_planes[1] + ctx->src_stride[1] * ctx->src_uv_height;
     256           0 :                         src_planes[3] = src_planes[2] + ctx->src_stride[2] * ctx->src_uv_height;
     257             :                 }
     258           0 :         } else if (frame_ifce && frame_ifce->get_plane) {
     259           0 :                 for (i=0; i<4; i++) {
     260           0 :                         if (frame_ifce->get_plane(frame_ifce, i, (const u8 **) &src_planes[i], &ctx->src_stride[i])!=GF_OK)
     261             :                                 break;
     262             :                 }
     263             :         } else {
     264           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[VFlip] No data associated with packet, not supported\n"));
     265           0 :                 gf_filter_pid_drop_packet(ctx->ipid);
     266           0 :                 return GF_NOT_SUPPORTED;
     267             :         }
     268             : 
     269        1053 :         ctx->bps = gf_pixel_get_bytes_per_pixel(ctx->s_pfmt);
     270             : 
     271             : 
     272        1053 :         if (frame_ifce){
     273           0 :                 dst_pck = gf_filter_pck_new_alloc(ctx->opid, ctx->out_size, &output);
     274           0 :                 if (dst_pck)
     275           0 :                         gf_filter_pck_merge_properties(pck, dst_pck);
     276             :         } else {
     277        1053 :                 dst_pck = gf_filter_pck_new_clone(ctx->opid, pck, &output);
     278             :         }
     279        1053 :         if (!dst_pck) return GF_OUT_OF_MEM;
     280             : 
     281        1053 :         dst_planes[0] = output;
     282        1053 :         if (ctx->nb_planes==1) {
     283         459 :         } else if (ctx->nb_planes==2) {
     284         108 :                 dst_planes[1] = output + ctx->dst_stride[0] * ctx->dst_height;
     285         351 :         } else if (ctx->nb_planes==3) {
     286         351 :                 dst_planes[1] = output + ctx->dst_stride[0] * ctx->dst_height;
     287         351 :                 dst_planes[2] = dst_planes[1] + ctx->dst_stride[1]*ctx->dst_uv_height;
     288           0 :         } else if (ctx->nb_planes==4) {
     289           0 :                 dst_planes[1] = output + ctx->dst_stride[0] * ctx->dst_height;
     290           0 :                 dst_planes[2] = dst_planes[1] + ctx->dst_stride[1]*ctx->dst_uv_height;
     291           0 :                 dst_planes[3] = dst_planes[2] + ctx->dst_stride[2]*ctx->dst_uv_height;
     292             :         }
     293             : 
     294             :         //computing of height and wiB
     295             :         //YUYV variations need *2 on horizontal dimension
     296        1863 :         for (i=0; i<ctx->nb_planes; i++) {
     297        1863 :                 if (i==0) {
     298        1053 :                         if (ctx->packed_422) {
     299         216 :                                 wiB = ctx->bps * ctx->dst_width *2;
     300             :                         } else {
     301         837 :                                 wiB = ctx->bps * ctx->dst_width;
     302             :                         }
     303        1053 :                         height = ctx->h;
     304             :                 }else {
     305             :                         //nv12/21
     306         810 :                         if (i==1 && ctx->nb_planes==2) {
     307             :                                 //half vertical res (/2)
     308             :                                 //half horizontal res (/2) but two chroma packed per pixel (*2)
     309         108 :                                 wiB = ctx->bps * ctx->dst_width;
     310         108 :                                 height = ctx->h / 2;
     311         702 :                         } else if (ctx->nb_planes>=3) {
     312             :                                 u32 div_x, div_y;
     313             :                                 //alpha/depth/other plane, treat as luma plane
     314         702 :                                 if (i==3 && ctx->nb_planes==4) {
     315           0 :                                         wiB = ctx->bps * ctx->dst_width;
     316           0 :                                         height = ctx->h;
     317         702 :                                 }else if (i==1 || i==2) {
     318         702 :                                         div_x = (ctx->src_stride[1]==ctx->src_stride[0]) ? 1 : 2;
     319         702 :                                         div_y = (ctx->src_uv_height==ctx->h) ? 1 : 2;
     320         702 :                                         height = ctx->dst_height;
     321         702 :                                         height /= div_y;
     322         702 :                                         wiB = ctx->bps * ctx->dst_width;
     323         702 :                                         wiB /= div_x;
     324             :                                 }
     325             :                         }
     326             :                 }
     327             : 
     328             :                 //processing according selected mode
     329        1863 :                 if (ctx->mode==VFLIP_VERT){
     330         891 :                         vertical_flip(ctx, src_planes[i], dst_planes[i], height, i, wiB);
     331         972 :                 }else if (ctx->mode==VFLIP_HORIZ){
     332         891 :                         horizontal_flip(ctx, src_planes[i], dst_planes[i], height, i, wiB, ctx->src_stride);
     333          81 :                 }else if (ctx->mode==VFLIP_BOTH){
     334          81 :                         vertical_flip(ctx, src_planes[i], dst_planes[i], height, i, wiB);
     335          81 :                         horizontal_flip(ctx, dst_planes[i], dst_planes[i], height, i, wiB, ctx->dst_stride);
     336             :                 }
     337             :         }
     338             : 
     339        1053 :         gf_filter_pck_send(dst_pck);
     340        1053 :         gf_filter_pid_drop_packet(ctx->ipid);
     341        1053 :         return GF_OK;
     342             : }
     343             : 
     344             : 
     345          40 : static GF_Err vflip_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     346             : {
     347             :         const GF_PropertyValue *p;
     348             :         u32 w, h, stride, pfmt;
     349             :         GF_Fraction sar;
     350          40 :         GF_VFlipCtx *ctx = gf_filter_get_udta(filter);
     351             : 
     352          40 :         if (is_remove) {
     353           0 :                 if (ctx->opid) {
     354           0 :                         gf_filter_pid_remove(ctx->opid);
     355           0 :                         ctx->opid = NULL;
     356             :                 }
     357             :                 return GF_OK;
     358             :         }
     359          40 :         if (! gf_filter_pid_check_caps(pid))
     360             :                 return GF_NOT_SUPPORTED;
     361             : 
     362          40 :         if (!ctx->opid) {
     363          40 :                 ctx->opid = gf_filter_pid_new(filter);
     364             :         }
     365             :         //copy properties at init or reconfig
     366          40 :         gf_filter_pid_copy_properties(ctx->opid, pid);
     367             : 
     368          40 :         if (!ctx->ipid) {
     369          40 :                 ctx->ipid = pid;
     370             :         }
     371             :         w = h = pfmt = stride = 0;
     372          40 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_WIDTH);
     373          40 :         if (p) w = p->value.uint;
     374          40 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_HEIGHT);
     375          40 :         if (p) h = p->value.uint;
     376          40 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_STRIDE);
     377          40 :         if (p) stride = p->value.uint;
     378          40 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_PIXFMT);
     379          40 :         if (p) pfmt = p->value.uint;
     380          40 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAR);
     381          40 :         if (p) sar = p->value.frac;
     382             :         else sar.den = sar.num = 1;
     383             : 
     384          40 :         if (!w || !h || !pfmt) {
     385           0 :                 ctx->passthrough = GF_TRUE;
     386           0 :                 return GF_OK;
     387             :         }
     388             : 
     389          40 :         if ((ctx->w == w) && (ctx->h == h) && (ctx->s_pfmt == pfmt) && (ctx->stride == stride)) {
     390             :                 //nothing to reconfigure
     391           0 :                 ctx->passthrough = GF_TRUE;
     392          40 :         } else if (ctx->mode==VFLIP_OFF) {
     393           1 :                 ctx->passthrough = GF_TRUE;
     394             :         } else {
     395             :                 Bool res;
     396             : 
     397          39 :                 ctx->w = w;
     398          39 :                 ctx->h = h;
     399          39 :                 ctx->s_pfmt = pfmt;
     400          39 :                 ctx->stride = stride;
     401          39 :                 ctx->dst_width  = w;
     402          39 :                 ctx->dst_height = h;
     403          39 :                 ctx->passthrough = GF_FALSE;
     404             : 
     405             :                 //get layout info for source
     406          39 :                 memset(ctx->src_stride, 0, sizeof(ctx->src_stride));
     407          39 :                 if (ctx->stride) ctx->src_stride[0] = ctx->stride;
     408             : 
     409          39 :                 res = gf_pixel_get_size_info(pfmt, w, h, &ctx->out_src_size, &ctx->src_stride[0], &ctx->src_stride[1], &ctx->nb_src_planes, &ctx->src_uv_height);
     410          39 :                 if (!res) {
     411           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[VFlip] Failed to query source pixel format characteristics\n"));
     412             :                         return GF_NOT_SUPPORTED;
     413             :                 }
     414          39 :                 if (ctx->nb_src_planes==3) ctx->src_stride[2] = ctx->src_stride[1];
     415          39 :                 if (ctx->nb_src_planes==4) ctx->src_stride[3] = ctx->src_stride[0];
     416             : 
     417             : 
     418             :                 //get layout info for dest
     419          39 :                 memset(ctx->dst_stride, 0, sizeof(ctx->dst_stride));
     420          39 :                 res = gf_pixel_get_size_info(pfmt, ctx->dst_width, ctx->dst_height, &ctx->out_size, &ctx->dst_stride[0], &ctx->dst_stride[1], &ctx->nb_planes, &ctx->dst_uv_height);
     421          39 :                 if (!res) {
     422           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[VFlip] Failed to query output pixel format characteristics\n"));
     423             :                         return GF_NOT_SUPPORTED;
     424             :                 }
     425          39 :                 if (ctx->nb_planes==3) ctx->dst_stride[2] = ctx->dst_stride[1];
     426          39 :                 if (ctx->nb_planes==4) ctx->dst_stride[3] = ctx->dst_stride[0];
     427             : 
     428             : 
     429          39 :                 ctx->w = w;
     430          39 :                 ctx->h = h;
     431          39 :                 ctx->s_pfmt = pfmt;
     432             : 
     433          39 :                 GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[VFlip] Configured output full frame size %dx%d\n", ctx->w, ctx->h));
     434             : 
     435          39 :                 ctx->line_buffer_vf = gf_realloc(ctx->line_buffer_vf, sizeof(char)*ctx->dst_stride[0] );
     436          39 :                 ctx->line_buffer_hf = gf_realloc(ctx->line_buffer_hf, sizeof(char)*ctx->src_stride[0] );
     437             : 
     438          39 :                 ctx->packed_422 = GF_FALSE;
     439          39 :                 switch (pfmt) {
     440             :                 //for YUV 422, adjust to multiple of 2 on horizontal dim
     441           8 :                 case GF_PIXEL_YUYV:
     442             :                 case GF_PIXEL_YVYU:
     443             :                 case GF_PIXEL_UYVY:
     444             :                 case GF_PIXEL_VYUY:
     445           8 :                         ctx->packed_422 = GF_TRUE;
     446           8 :                         break;
     447             :                 }
     448             :         }
     449             : 
     450          40 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(ctx->dst_width));
     451          40 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(ctx->dst_height));
     452             : 
     453          40 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE, &PROP_UINT(ctx->dst_stride[0] ));
     454          40 :         if (ctx->nb_planes>1)
     455          17 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE_UV, &PROP_UINT(ctx->dst_stride[1]));
     456             : 
     457          40 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAR, &PROP_FRAC(sar) );
     458             : 
     459             :         //an access unit corresponds to a single packet
     460          40 :         gf_filter_pid_set_framing_mode(pid, GF_TRUE);
     461          40 :         return GF_OK;
     462             : }
     463             : 
     464          40 : void vflip_finalize(GF_Filter *filter)
     465             : {
     466          40 :         GF_VFlipCtx *ctx = gf_filter_get_udta(filter);
     467          40 :         if (ctx->line_buffer_vf) gf_free(ctx->line_buffer_vf);
     468          40 :         if (ctx->line_buffer_hf) gf_free(ctx->line_buffer_hf);
     469          40 : }
     470             : 
     471             : 
     472             : #define OFFS(_n)        #_n, offsetof(GF_VFlipCtx, _n)
     473             : static GF_FilterArgs VFlipArgs[] =
     474             : {
     475             :                 { OFFS(mode), "flip mode\n"
     476             :                 "- off: no flipping (passthrough)\n"
     477             :                 "- vert: vertical flip\n"
     478             :                 "- horiz: horizontal flip\n"
     479             :                 "- both: horizontal and vertical flip"
     480             :                 "", GF_PROP_UINT, "vert", "off|vert|horiz|both", GF_FS_ARG_UPDATE | GF_FS_ARG_HINT_ADVANCED},
     481             :                 {0}
     482             : };
     483             : 
     484             : static const GF_FilterCapability VFlipCaps[] =
     485             : {
     486             :                 CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
     487             :                 CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_RAW)
     488             : };
     489             : 
     490             : GF_FilterRegister VFlipRegister = {
     491             :                 .name = "vflip",
     492             :                 GF_FS_SET_DESCRIPTION("Video flip")
     493             :                 GF_FS_SET_HELP("Filter used to flip video frames vertically, horizontally, in both directions or no flip")
     494             :                 .private_size = sizeof(GF_VFlipCtx),
     495             :                 .flags = GF_FS_REG_EXPLICIT_ONLY,
     496             :                 .args = VFlipArgs,
     497             :                 .configure_pid = vflip_configure_pid,
     498             :                 SETCAPS(VFlipCaps),
     499             :                 .process = vflip_process,
     500             :                 .finalize = vflip_finalize,
     501             : };
     502             : 
     503             : 
     504             : 
     505        2877 : const GF_FilterRegister *vflip_register(GF_FilterSession *session)
     506             : {
     507        2877 :         return &VFlipRegister;
     508             : }

Generated by: LCOV version 1.13