LCOV - code coverage report
Current view: top level - filters - ff_common.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 464 509 91.2 %
Date: 2021-04-29 23:48:07 Functions: 20 21 95.2 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2017-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / common ffmpeg filters
       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             : #include <libavfilter/avfilter.h>
      33             : 
      34             : #if !defined(__GNUC__)
      35             : # if defined(_WIN32_WCE) || defined (WIN32)
      36             : #  pragma comment(lib, "avutil")
      37             : #  pragma comment(lib, "avformat")
      38             : #  pragma comment(lib, "avcodec")
      39             : #  pragma comment(lib, "avdevice")
      40             : #  pragma comment(lib, "swscale")
      41             : #  pragma comment(lib, "avfilter")
      42             : # endif
      43             : #endif
      44             : 
      45             : 
      46             : static Bool ffmpeg_init = GF_FALSE;
      47             : 
      48             : typedef struct
      49             : {
      50             :         GF_List *all_filters;
      51             :         u32 nb_arg_skip;
      52             : } GF_FFRegistryExt;
      53             : 
      54             : typedef struct
      55             : {
      56             :         u32 ff_pf;
      57             :         u32 gpac_pf;
      58             :         u32 flags; //only 1 used, for full range
      59             : } GF_FF_PFREG;
      60             : 
      61             : #ifndef FFMPEG_ENABLE_VVC
      62             : //enable this when compiling under xcode or visual (eg without ./configure), or add macro to configuration.h or project settings
      63             : //to remove once we have a known API version number for vvc in libavcodec
      64             : //#define FFMPEG_ENABLE_VVC
      65             : #endif
      66             : 
      67             : static const GF_FF_PFREG FF2GPAC_PixelFormats[] =
      68             : {
      69             :         {AV_PIX_FMT_YUV420P, GF_PIXEL_YUV},
      70             :         {AV_PIX_FMT_YUV420P10LE, GF_PIXEL_YUV_10},
      71             :         {AV_PIX_FMT_YUV422P, GF_PIXEL_YUV422},
      72             :         {AV_PIX_FMT_YUV422P10LE, GF_PIXEL_YUV422_10},
      73             :         {AV_PIX_FMT_YUV444P, GF_PIXEL_YUV444},
      74             :         {AV_PIX_FMT_YUV444P10LE, GF_PIXEL_YUV444_10},
      75             :         {AV_PIX_FMT_RGBA, GF_PIXEL_RGBA},
      76             :         {AV_PIX_FMT_RGB24, GF_PIXEL_RGB},
      77             :         {AV_PIX_FMT_BGR24, GF_PIXEL_BGR},
      78             :         {AV_PIX_FMT_UYVY422, GF_PIXEL_UYVY},
      79             :         {AV_PIX_FMT_YUYV422, GF_PIXEL_YUYV},
      80             :         //remap unsupported pix formats
      81             :         {AV_PIX_FMT_UYVY422, GF_PIXEL_VYUY},
      82             :         {AV_PIX_FMT_YUYV422, GF_PIXEL_YVYU},
      83             : 
      84             :         {AV_PIX_FMT_NV12, GF_PIXEL_NV12},
      85             : #if LIBAVCODEC_VERSION_MAJOR >= 58
      86             :         {AV_PIX_FMT_P010LE, GF_PIXEL_NV12_10},
      87             : #endif
      88             :         {AV_PIX_FMT_NV21, GF_PIXEL_NV21},
      89             :         {AV_PIX_FMT_0RGB, GF_PIXEL_XRGB},
      90             :         {AV_PIX_FMT_RGB0, GF_PIXEL_RGBX},
      91             :         {AV_PIX_FMT_0BGR, GF_PIXEL_XBGR},
      92             :         {AV_PIX_FMT_BGR0, GF_PIXEL_BGRX},
      93             :         {AV_PIX_FMT_GRAY8, GF_PIXEL_GREYSCALE},
      94             :         {AV_PIX_FMT_YA8, GF_PIXEL_GREYALPHA},
      95             :         {AV_PIX_FMT_RGB444, GF_PIXEL_RGB_444},
      96             :         {AV_PIX_FMT_RGB555, GF_PIXEL_RGB_555},
      97             :         {AV_PIX_FMT_RGB565, GF_PIXEL_RGB_565},
      98             :         {AV_PIX_FMT_RGBA, GF_PIXEL_RGBA},
      99             :         {AV_PIX_FMT_ARGB, GF_PIXEL_ARGB},
     100             :         {AV_PIX_FMT_ABGR, GF_PIXEL_ABGR},
     101             :         {AV_PIX_FMT_BGRA, GF_PIXEL_BGRA},
     102             : 
     103             :         /*aliases*/
     104             :         {AV_PIX_FMT_YUVJ420P, GF_PIXEL_YUV, 1},
     105             :         {AV_PIX_FMT_YUVJ422P, GF_PIXEL_YUV422, 1},
     106             :         {AV_PIX_FMT_YUVJ444P, GF_PIXEL_YUV444, 1},
     107             :         {0},
     108             : };
     109             : 
     110         256 : u32 ffmpeg_pixfmt_from_gpac(u32 pfmt)
     111             : {
     112             :         u32 i=0;
     113        1532 :         while (FF2GPAC_PixelFormats[i].gpac_pf) {
     114        1276 :                 if (FF2GPAC_PixelFormats[i].gpac_pf == pfmt)
     115         256 :                         return FF2GPAC_PixelFormats[i].ff_pf;
     116        1020 :                 i++;
     117             :         }
     118           0 :         GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[FFMPEG] Unmapped GPAC pixel format %s, patch welcome\n", gf_4cc_to_str(pfmt) ));
     119             :         return 0;
     120             : }
     121             : 
     122          48 : u32 ffmpeg_pixfmt_to_gpac(u32 pfmt)
     123             : {
     124          48 :         const AVPixFmtDescriptor *ffdesc = av_pix_fmt_desc_get(pfmt);
     125          48 :         if (!ffdesc) {
     126           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[FFMPEG] Unrecognized FFMPEG pixel format %d\n", pfmt ));
     127             :                 return 0;
     128             :         }
     129             :         u32 i=0;
     130         558 :         while (FF2GPAC_PixelFormats[i].gpac_pf) {
     131         558 :                 if (FF2GPAC_PixelFormats[i].ff_pf == pfmt)
     132             :                         return FF2GPAC_PixelFormats[i].gpac_pf;
     133         510 :                 i++;
     134             :         }
     135           0 :         GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[FFMPEG] Unmapped FFMPEG pixel format %s, patch welcome\n", ffdesc->name));
     136             :         return 0;
     137             : }
     138             : 
     139         125 : Bool ffmpeg_pixfmt_is_fullrange(u32 pfmt)
     140             : {
     141             :         u32 i=0;
     142        3393 :         while (FF2GPAC_PixelFormats[i].gpac_pf) {
     143        3169 :                 if (FF2GPAC_PixelFormats[i].ff_pf == pfmt)
     144          26 :                         return (FF2GPAC_PixelFormats[i].flags & 1) ? GF_TRUE : GF_FALSE;
     145        3143 :                 i++;
     146             :         }
     147             :         return GF_FALSE;
     148             : }
     149             : 
     150           0 : u32 ffmpeg_pixfmt_from_codec_tag(u32 codec_tag, Bool *is_full_range)
     151             : {
     152             :         u32 i=0;
     153           0 :         if (is_full_range) *is_full_range = 0;
     154             : 
     155           0 :         while (FF2GPAC_PixelFormats[i].gpac_pf) {
     156           0 :                 if (avcodec_pix_fmt_to_codec_tag(FF2GPAC_PixelFormats[i].ff_pf) == codec_tag) {
     157           0 :                         if (is_full_range && (FF2GPAC_PixelFormats[i].flags & 1)) {
     158           0 :                                 *is_full_range = GF_TRUE;
     159             :                         }
     160             :                         return FF2GPAC_PixelFormats[i].gpac_pf;
     161             :                 }
     162           0 :                 i++;
     163             :         }
     164             :         return 0;
     165             : }
     166             : 
     167             : 
     168             : typedef struct
     169             : {
     170             :         u32 ff_sf;
     171             :         u32 gpac_sf;
     172             : } GF_FF_AFREG;
     173             : 
     174             : static const GF_FF_AFREG FF2GPAC_AudioFormats[] =
     175             : {
     176             :         {AV_SAMPLE_FMT_U8, GF_AUDIO_FMT_U8},
     177             :         {AV_SAMPLE_FMT_S16, GF_AUDIO_FMT_S16},
     178             :         {AV_SAMPLE_FMT_S32, GF_AUDIO_FMT_S32},
     179             :         {AV_SAMPLE_FMT_FLT, GF_AUDIO_FMT_FLT},
     180             :         {AV_SAMPLE_FMT_DBL, GF_AUDIO_FMT_DBL},
     181             :         {AV_SAMPLE_FMT_U8P, GF_AUDIO_FMT_U8P},
     182             :         {AV_SAMPLE_FMT_S16P, GF_AUDIO_FMT_S16P},
     183             :         {AV_SAMPLE_FMT_S32P, GF_AUDIO_FMT_S32P},
     184             :         {AV_SAMPLE_FMT_FLTP, GF_AUDIO_FMT_FLTP},
     185             :         {AV_SAMPLE_FMT_DBLP, GF_AUDIO_FMT_DBLP},
     186             :         {0},
     187             : };
     188             : 
     189          18 : u32 ffmpeg_audio_fmt_from_gpac(u32 sfmt)
     190             : {
     191             :         u32 i=0;
     192         124 :         while (FF2GPAC_AudioFormats[i].gpac_sf) {
     193         106 :                 if (FF2GPAC_AudioFormats[i].gpac_sf == sfmt)
     194          18 :                         return FF2GPAC_AudioFormats[i].ff_sf;
     195          88 :                 i++;
     196             :         }
     197           0 :         GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[FFMPEG] Unmapped GPAC audio format %s, patch welcome\n", gf_4cc_to_str(sfmt) ));
     198             :         return 0;
     199             : }
     200             : 
     201          39 : u32 ffmpeg_audio_fmt_to_gpac(u32 sfmt)
     202             : {
     203             :         u32 i=0;
     204         351 :         while (FF2GPAC_AudioFormats[i].gpac_sf) {
     205         312 :                 if (FF2GPAC_AudioFormats[i].ff_sf == sfmt)
     206             :                         return FF2GPAC_AudioFormats[i].gpac_sf;
     207         273 :                 i++;
     208             :         }
     209           0 :         GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[FFMPEG] Unmapped FFMPEG audio format %d, patch welcome\n", sfmt ));
     210             :         return 0;
     211             : }
     212             : 
     213             : 
     214             : typedef struct
     215             : {
     216             :         u64 ff_ch_mask;
     217             :         u64 gpac_ch_mask;
     218             : } GF_FF_LAYOUTREG;
     219             : 
     220             : static const GF_FF_LAYOUTREG FF2GPAC_ChannelLayout[] =
     221             : {
     222             :         {AV_CH_FRONT_LEFT, GF_AUDIO_CH_FRONT_LEFT},
     223             :         {AV_CH_FRONT_RIGHT, GF_AUDIO_CH_FRONT_RIGHT},
     224             :         {AV_CH_FRONT_CENTER, GF_AUDIO_CH_FRONT_CENTER},
     225             :         {AV_CH_LOW_FREQUENCY, GF_AUDIO_CH_LFE},
     226             :         {AV_CH_BACK_LEFT, GF_AUDIO_CH_SURROUND_LEFT},
     227             :         {AV_CH_BACK_RIGHT, GF_AUDIO_CH_SURROUND_RIGHT},
     228             :         {AV_CH_FRONT_LEFT_OF_CENTER, GF_AUDIO_CH_FRONT_CENTER_LEFT},
     229             :         {AV_CH_FRONT_RIGHT_OF_CENTER, GF_AUDIO_CH_FRONT_CENTER_RIGHT},
     230             :         {AV_CH_BACK_CENTER, GF_AUDIO_CH_REAR_CENTER},
     231             :         {AV_CH_SIDE_LEFT, GF_AUDIO_CH_REAR_SURROUND_LEFT},
     232             :         {AV_CH_SIDE_RIGHT, GF_AUDIO_CH_REAR_SURROUND_RIGHT},
     233             :         {AV_CH_TOP_CENTER, GF_AUDIO_CH_CENTER_SURROUND_TOP},
     234             :         {AV_CH_TOP_FRONT_LEFT, GF_AUDIO_CH_FRONT_TOP_LEFT},
     235             :         {AV_CH_TOP_FRONT_CENTER, GF_AUDIO_CH_FRONT_TOP_CENTER},
     236             :         {AV_CH_TOP_FRONT_RIGHT, GF_AUDIO_CH_FRONT_TOP_RIGHT},
     237             :         {AV_CH_TOP_BACK_LEFT, GF_AUDIO_CH_SURROUND_TOP_LEFT},
     238             :         {AV_CH_TOP_BACK_CENTER, GF_AUDIO_CH_REAR_CENTER_TOP},
     239             :         {AV_CH_TOP_BACK_RIGHT, GF_AUDIO_CH_SURROUND_TOP_RIGHT},
     240             :         {AV_CH_WIDE_LEFT, GF_AUDIO_CH_WIDE_FRONT_LEFT},
     241             :         {AV_CH_WIDE_RIGHT, GF_AUDIO_CH_WIDE_FRONT_RIGHT},
     242             :         {AV_CH_SURROUND_DIRECT_LEFT, GF_AUDIO_CH_SURROUND_DIRECT_LEFT},
     243             :         {AV_CH_SURROUND_DIRECT_RIGHT, GF_AUDIO_CH_SURROUND_DIRECT_RIGHT},
     244             :         {AV_CH_LOW_FREQUENCY_2, GF_AUDIO_CH_LFE2},
     245             : /*      {AV_CH_STEREO_LEFT, },
     246             :         {AV_CH_STEREO_RIGHT, },
     247             : */
     248             : };
     249             : 
     250          11 : u64 ffmpeg_channel_layout_from_gpac(u64 gpac_ch_layout)
     251             : {
     252             :         u32 i, nb_layout = sizeof(FF2GPAC_ChannelLayout) / sizeof(GF_FF_LAYOUTREG);
     253             :         u64 res = 0;
     254         264 :         for (i=0; i<nb_layout; i++) {
     255         253 :                 if (FF2GPAC_ChannelLayout[i].gpac_ch_mask & gpac_ch_layout)
     256          21 :                         res |= FF2GPAC_ChannelLayout[i].ff_ch_mask;
     257             :         }
     258          11 :         return res;
     259             : }
     260          28 : u64 ffmpeg_channel_layout_to_gpac(u64 ff_ch_layout)
     261             : {
     262             :         u32 i, nb_layout = sizeof(FF2GPAC_ChannelLayout) / sizeof(GF_FF_LAYOUTREG);
     263             :         u64 res = 0;
     264         672 :         for (i=0; i<nb_layout; i++) {
     265         644 :                 if (FF2GPAC_ChannelLayout[i].ff_ch_mask & ff_ch_layout)
     266          53 :                         res |= FF2GPAC_ChannelLayout[i].gpac_ch_mask;
     267             :         }
     268          28 :         return res;
     269             : }
     270             : 
     271             : 
     272             : typedef struct
     273             : {
     274             :         u32 ff_codec_id;
     275             :         u32 gpac_codec_id;
     276             :         u32 ff_codectag;
     277             : } GF_FF_CIDREG;
     278             : 
     279             : static const GF_FF_CIDREG FF2GPAC_CodecIDs[] =
     280             : {
     281             :         {AV_CODEC_ID_MP2, GF_CODECID_MPEG_AUDIO, 0},
     282             :         {AV_CODEC_ID_MP3, GF_CODECID_MPEG2_PART3, 0},
     283             :         {AV_CODEC_ID_AAC, GF_CODECID_AAC_MPEG4, 0},
     284             :         {AV_CODEC_ID_AC3, GF_CODECID_AC3, 0},
     285             :         {AV_CODEC_ID_EAC3, GF_CODECID_EAC3, 0},
     286             :         {AV_CODEC_ID_AMR_NB, GF_CODECID_AMR, 0},
     287             :         {AV_CODEC_ID_AMR_WB, GF_CODECID_AMR_WB, 0},
     288             :         {AV_CODEC_ID_QCELP, GF_CODECID_QCELP, 0},
     289             :         {AV_CODEC_ID_EVRC, GF_CODECID_EVRC, 0},
     290             :         {AV_CODEC_ID_SMV, GF_CODECID_SMV, 0},
     291             :         {AV_CODEC_ID_VORBIS, GF_CODECID_VORBIS, 0},
     292             :         {AV_CODEC_ID_FLAC, GF_CODECID_FLAC, 0},
     293             :         {AV_CODEC_ID_SPEEX, GF_CODECID_SPEEX, 0},
     294             :         {AV_CODEC_ID_THEORA, GF_CODECID_THEORA, 0},
     295             :         {AV_CODEC_ID_MPEG4, GF_CODECID_MPEG4_PART2, 0},
     296             :         {AV_CODEC_ID_H264, GF_CODECID_AVC, 0},
     297             :         {AV_CODEC_ID_HEVC, GF_CODECID_HEVC, 0},
     298             :         {AV_CODEC_ID_MPEG1VIDEO, GF_CODECID_MPEG1, 0},
     299             :         {AV_CODEC_ID_MPEG2VIDEO, GF_CODECID_MPEG2_SIMPLE, 0},
     300             :         {AV_CODEC_ID_MPEG2VIDEO, GF_CODECID_MPEG2_MAIN, 0},
     301             :         {AV_CODEC_ID_MPEG2VIDEO, GF_CODECID_MPEG2_HIGH, 0},
     302             :         {AV_CODEC_ID_MPEG2VIDEO, GF_CODECID_MPEG2_SPATIAL, 0},
     303             :         {AV_CODEC_ID_MPEG2VIDEO, GF_CODECID_MPEG2_SNR, 0},
     304             :         {AV_CODEC_ID_MPEG2VIDEO, GF_CODECID_MPEG2_422, 0},
     305             :         {AV_CODEC_ID_H263, GF_CODECID_S263, 0},
     306             :         {AV_CODEC_ID_H263, GF_CODECID_H263, 0},
     307             :         {AV_CODEC_ID_MJPEG, GF_CODECID_JPEG, 0},
     308             :         {AV_CODEC_ID_PNG, GF_CODECID_PNG, 0},
     309             :         {AV_CODEC_ID_JPEG2000, GF_CODECID_J2K, 0},
     310             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     311             :         {AV_CODEC_ID_AV1, GF_CODECID_AV1, 0},
     312             : #endif
     313             :         {AV_CODEC_ID_VP8, GF_CODECID_VP8, 0},
     314             :         {AV_CODEC_ID_VP9, GF_CODECID_VP9, 0},
     315             :         {AV_CODEC_ID_VC1, GF_CODECID_SMPTE_VC1, 0},
     316             : 
     317             :         {AV_CODEC_ID_OPUS, GF_CODECID_OPUS, 0},
     318             : 
     319             : 
     320             :         //ProRes
     321             :         {AV_CODEC_ID_PRORES, GF_CODECID_APCH, GF_4CC('h','c','p','a') },
     322             :         {AV_CODEC_ID_PRORES, GF_CODECID_APCO, GF_4CC('o','c','p','a') },
     323             :         {AV_CODEC_ID_PRORES, GF_CODECID_APCN, GF_4CC('n','c','p','a')},
     324             :         {AV_CODEC_ID_PRORES, GF_CODECID_APCS, GF_4CC('s','c','p','a')},
     325             :         {AV_CODEC_ID_PRORES, GF_CODECID_AP4X, GF_4CC('x','4','p','a')},
     326             :         {AV_CODEC_ID_PRORES, GF_CODECID_AP4H, GF_4CC('h','4','p','a')},
     327             : 
     328             :         //RAW codecs
     329             :         {AV_CODEC_ID_RAWVIDEO, GF_CODECID_RAW, 0},
     330             :         {AV_CODEC_ID_PCM_S16LE, GF_CODECID_RAW, 0},
     331             :         {AV_CODEC_ID_PCM_S16BE, GF_CODECID_RAW, 0},
     332             :         {AV_CODEC_ID_PCM_U16LE, GF_CODECID_RAW, 0},
     333             :         {AV_CODEC_ID_PCM_U16BE, GF_CODECID_RAW, 0},
     334             :         {AV_CODEC_ID_PCM_S8, GF_CODECID_RAW, 0},
     335             :         {AV_CODEC_ID_PCM_U8, GF_CODECID_RAW, 0},
     336             :         {AV_CODEC_ID_PCM_MULAW, GF_CODECID_RAW, 0},
     337             :         {AV_CODEC_ID_PCM_ALAW, GF_CODECID_RAW, 0},
     338             :         {AV_CODEC_ID_PCM_S32LE, GF_CODECID_RAW, 0},
     339             :         {AV_CODEC_ID_PCM_S32BE, GF_CODECID_RAW, 0},
     340             :         {AV_CODEC_ID_PCM_U32LE, GF_CODECID_RAW, 0},
     341             :         {AV_CODEC_ID_PCM_U32BE, GF_CODECID_RAW, 0},
     342             :         {AV_CODEC_ID_PCM_S24LE, GF_CODECID_RAW, 0},
     343             :         {AV_CODEC_ID_PCM_S24BE, GF_CODECID_RAW, 0},
     344             :         {AV_CODEC_ID_PCM_U24LE, GF_CODECID_RAW, 0},
     345             :         {AV_CODEC_ID_PCM_U24BE, GF_CODECID_RAW, 0},
     346             :         {AV_CODEC_ID_PCM_S24DAUD, GF_CODECID_RAW, 0},
     347             :         {AV_CODEC_ID_PCM_ZORK, GF_CODECID_RAW, 0},
     348             :         {AV_CODEC_ID_PCM_S16LE_PLANAR, GF_CODECID_RAW, 0},
     349             :         {AV_CODEC_ID_PCM_DVD, GF_CODECID_RAW, 0},
     350             :         {AV_CODEC_ID_PCM_F32BE, GF_CODECID_RAW, 0},
     351             :         {AV_CODEC_ID_PCM_F32LE, GF_CODECID_RAW, 0},
     352             :         {AV_CODEC_ID_PCM_F64BE, GF_CODECID_RAW, 0},
     353             :         {AV_CODEC_ID_PCM_F64LE, GF_CODECID_RAW, 0},
     354             :         {AV_CODEC_ID_PCM_BLURAY, GF_CODECID_RAW, 0},
     355             :         {AV_CODEC_ID_PCM_LXF, GF_CODECID_RAW, 0},
     356             :         {AV_CODEC_ID_S302M, GF_CODECID_RAW, 0},
     357             :         {AV_CODEC_ID_PCM_S8_PLANAR, GF_CODECID_RAW, 0},
     358             :         {AV_CODEC_ID_PCM_S24LE_PLANAR, GF_CODECID_RAW, 0},
     359             :         {AV_CODEC_ID_PCM_S32LE_PLANAR, GF_CODECID_RAW, 0},
     360             :         {AV_CODEC_ID_PCM_S16BE_PLANAR, GF_CODECID_RAW, 0},
     361             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     362             :         {AV_CODEC_ID_PCM_S64LE, GF_CODECID_RAW, 0},
     363             :         {AV_CODEC_ID_PCM_S64BE, GF_CODECID_RAW, 0},
     364             :         {AV_CODEC_ID_PCM_F16LE, GF_CODECID_RAW, 0},
     365             :         {AV_CODEC_ID_PCM_F24LE, GF_CODECID_RAW, 0},
     366             : #endif
     367             : 
     368             : #ifdef FFMPEG_ENABLE_VVC
     369             :         {AV_CODEC_ID_VVC, GF_CODECID_VVC, 0},
     370             : #endif
     371             : 
     372             :         {AV_CODEC_ID_V210, GF_CODECID_V210, 0},
     373             : 
     374             :         {AV_CODEC_ID_TRUEHD, GF_CODECID_TRUEHD, 0},
     375             : 
     376             :         {0}
     377             : };
     378             : 
     379         253 : u32 ffmpeg_codecid_from_gpac(u32 codec_id, u32 *ff_codectag)
     380             : {
     381             :         u32 i=0;
     382         253 :         if (ff_codectag) *ff_codectag = 0;
     383             : 
     384        3796 :         while (FF2GPAC_CodecIDs[i].gpac_codec_id) {
     385        3796 :                 if (FF2GPAC_CodecIDs[i].gpac_codec_id == codec_id) {
     386         253 :                         if (ff_codectag) *ff_codectag = FF2GPAC_CodecIDs[i].ff_codectag;
     387         253 :                         return FF2GPAC_CodecIDs[i].ff_codec_id;
     388             :                 }
     389        3543 :                 i++;
     390             :         }
     391           0 :         GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[FFMPEG] Unmapped GPAC codec %s\n", gf_codecid_name(codec_id) ));
     392             :         return 0;
     393             : }
     394             : 
     395       19981 : u32 ffmpeg_codecid_to_gpac(u32 codec_id)
     396             : {
     397             :         u32 i=0;
     398     1268264 :         while (FF2GPAC_CodecIDs[i].ff_codec_id) {
     399     1233806 :                 if (FF2GPAC_CodecIDs[i].ff_codec_id == codec_id)
     400        5504 :                         return FF2GPAC_CodecIDs[i].gpac_codec_id;
     401     1228302 :                 i++;
     402             :         }
     403       14477 :         GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[FFMPEG] Unmapped FFMPEG codec ID %s\n", avcodec_get_name(codec_id) ));
     404             :         return 0;
     405             : }
     406             : 
     407             : 
     408             : typedef struct
     409             : {
     410             :         u32 ff_st;
     411             :         u32 gpac_st;
     412             : } GF_FF_ST;
     413             : 
     414             : static const GF_FF_ST FF2GPAC_StreamTypes[] =
     415             : {
     416             :         {AVMEDIA_TYPE_VIDEO, GF_STREAM_VISUAL},
     417             :         {AVMEDIA_TYPE_AUDIO, GF_STREAM_AUDIO},
     418             :         {AVMEDIA_TYPE_DATA, GF_STREAM_METADATA},
     419             :         {AVMEDIA_TYPE_SUBTITLE, GF_STREAM_TEXT},
     420             :         {AVMEDIA_TYPE_ATTACHMENT, GF_STREAM_METADATA},
     421             :         {AVMEDIA_TYPE_UNKNOWN, GF_STREAM_UNKNOWN},
     422             :         {0},
     423             : };
     424             : 
     425           9 : u32 ffmpeg_stream_type_from_gpac(u32 streamtype)
     426             : {
     427             :         u32 i=0;
     428          19 :         while (FF2GPAC_StreamTypes[i].gpac_st) {
     429          10 :                 if (FF2GPAC_StreamTypes[i].gpac_st == streamtype)
     430           9 :                         return FF2GPAC_StreamTypes[i].ff_st;
     431           1 :                 i++;
     432             :         }
     433           0 :         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[FFMPEG] Unmapped GPAC stream type %s, assuming data\n", gf_stream_type_name(streamtype) ));
     434             :         return AVMEDIA_TYPE_DATA;
     435             : }
     436             : 
     437             : 
     438          62 : u32 ffmpeg_stream_type_to_gpac(u32 streamtype)
     439             : {
     440             :         u32 i=0;
     441         142 :         while (FF2GPAC_StreamTypes[i].gpac_st) {
     442          80 :                 if (FF2GPAC_StreamTypes[i].ff_st == streamtype)
     443             :                         return FF2GPAC_StreamTypes[i].gpac_st;
     444          18 :                 i++;
     445             :         }
     446           0 :         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[FFMPEG] Unmapped FFMPEG stream type %d, assuming data\n", streamtype ));
     447             :         return GF_STREAM_METADATA;
     448             : }
     449             : 
     450             : //static void ff_log_callback(void *avcl, int level, const char *fmt, va_list vl) { }
     451             : 
     452         187 : void ffmpeg_setup_logs(u32 log_class)
     453             : {
     454         187 :         u32 level = gf_log_get_tool_level(log_class);
     455         187 :         switch (level) {
     456           0 :         case GF_LOG_DEBUG:
     457           0 :                 av_log_set_level(AV_LOG_DEBUG);
     458           0 :                 break;
     459           2 :         case GF_LOG_INFO:
     460           2 :                 av_log_set_level(AV_LOG_INFO);
     461           2 :                 break;
     462         185 :         case GF_LOG_WARNING:
     463         185 :                 av_log_set_level(AV_LOG_WARNING);
     464         185 :                 break;
     465           0 :         default:
     466           0 :                 av_log_set_level(AV_LOG_ERROR);
     467           0 :                 break;
     468             :         }
     469             : //      av_log_set_callback(ff_log_callback);
     470         187 : }
     471             : 
     472       14385 : void ffmpeg_initialize()
     473             : {
     474       14385 :         if (ffmpeg_init) return;
     475        2740 :         av_register_all();
     476        2740 :         avformat_network_init();
     477        2740 :         ffmpeg_init = GF_TRUE;
     478             : }
     479             : 
     480         155 : static void ffmpeg_register_free(GF_FilterSession *session, GF_FilterRegister *reg)
     481             : {
     482             :         u32 i;
     483         155 :         GF_FFRegistryExt *ffregext = reg->udta;
     484         155 :         GF_List *all_filters = ffregext->all_filters;
     485         155 :         u32 nb_skip_begin = ffregext->nb_arg_skip;
     486         155 :         gf_free(ffregext);
     487         155 :         reg->udta = NULL;
     488             : 
     489         155 :         if (all_filters) {
     490       34300 :                 while (gf_list_count(all_filters)) {
     491             :                         i=0;
     492       34145 :                         GF_FilterRegister *f = gf_list_pop_back(all_filters);
     493       34145 :                         if (f->caps)
     494       27156 :                                 gf_free((void *)f->caps);
     495             : 
     496       98372 :                         while (f->args) {
     497       74254 :                                 GF_FilterArgs *arg = (GF_FilterArgs *) &f->args[i];
     498       74254 :                                 if (!arg || !arg->arg_name) break;
     499       64227 :                                 i++;
     500       64227 :                                 if (arg->arg_default_val) gf_free((void *) arg->arg_default_val);
     501       64227 :                                 if (arg->min_max_enum) gf_free((void *) arg->min_max_enum);
     502       64227 :                                 if (arg->flags & GF_FS_ARG_META_ALLOC) gf_free((void *) arg->arg_desc);
     503             :                         }
     504       34145 :                         gf_free((void *) f->args);
     505       34145 :                         gf_free((char*) f->name);
     506       34145 :                         gf_fs_remove_filter_register(session, f);
     507       34145 :                         gf_free(f);
     508             :                 }
     509         155 :                 gf_list_del(all_filters);
     510             :         }
     511             :         i=nb_skip_begin;
     512        6975 :         while (reg->args) {
     513        6975 :                 GF_FilterArgs *arg = (GF_FilterArgs *) &reg->args[i];
     514        6975 :                 if (!arg || !arg->arg_name) break;
     515        6820 :                 i++;
     516        6820 :                 if (arg->arg_default_val) gf_free((void *) arg->arg_default_val);
     517        6820 :                 if (arg->min_max_enum) gf_free((void *) arg->min_max_enum);
     518        6820 :                 if (arg->flags & GF_FS_ARG_META_ALLOC) gf_free((void *) arg->arg_desc);
     519             :         }
     520         155 :         if (reg->args) gf_free((void *) reg->args);
     521             : 
     522         155 : }
     523             : 
     524      132942 : GF_FilterArgs ffmpeg_arg_translate(const struct AVOption *opt)
     525             : {
     526             :         char szDef[200];
     527             :         GF_FilterArgs arg;
     528             :         memset(&arg, 0, sizeof(GF_FilterArgs));
     529      132942 :         arg.arg_name = opt->name;
     530      132942 :         arg.arg_desc = opt->help;
     531      132942 :         arg.offset_in_private=-1;
     532      132942 :         arg.flags = GF_FS_ARG_META;
     533             :         if (opt->name[0] == 0)
     534             :                 arg.flags = GF_FS_ARG_META;
     535             : 
     536      132942 :         switch (opt->type) {
     537       42102 :         case AV_OPT_TYPE_INT64:
     538             :         case AV_OPT_TYPE_INT:
     539             :         case AV_OPT_TYPE_CHANNEL_LAYOUT:
     540       42102 :                 if (opt->type==AV_OPT_TYPE_INT64) arg.arg_type = GF_PROP_LSINT;
     541       40921 :                 else if (opt->type==AV_OPT_TYPE_INT) arg.arg_type = GF_PROP_SINT;
     542          31 :                 else arg.arg_type = GF_PROP_UINT; //channel layout, map to int
     543             : 
     544       42102 :                 sprintf(szDef, LLD, opt->default_val.i64);
     545       42102 :                 arg.arg_default_val = gf_strdup(szDef);
     546       42102 :                 if (opt->max>=(Double) GF_INT_MAX)
     547       27148 :                         sprintf(szDef, LLD"-I", (s64) opt->min);
     548             :                 else
     549       14954 :                         sprintf(szDef, LLD"-"LLD, (s64) opt->min, (s64) opt->max);
     550       42102 :                 arg.min_max_enum = gf_strdup(szDef);
     551       42102 :                 break;
     552             : #if LIBAVCODEC_VERSION_MAJOR >= 57
     553          93 :         case AV_OPT_TYPE_UINT64:
     554             : //      case AV_OPT_TYPE_UINT:
     555          93 :                 arg.arg_type = GF_PROP_LUINT;
     556          93 :                 sprintf(szDef, LLU, opt->default_val.i64);
     557          93 :                 arg.arg_default_val = gf_strdup(szDef);
     558          93 :                 if (opt->max>=(Double) GF_INT_MAX)
     559          93 :                         sprintf(szDef, LLU"-I", (s64) opt->min);
     560             :                 else
     561           0 :                         sprintf(szDef, LLU"-"LLU, (u64) opt->min, (u64) opt->max);
     562          93 :                 arg.min_max_enum = gf_strdup(szDef);
     563          93 :                 break;
     564       10882 :         case AV_OPT_TYPE_BOOL:
     565       10882 :                 arg.arg_type = GF_PROP_BOOL;
     566       10882 :                 arg.arg_default_val = gf_strdup(opt->default_val.i64 ? "true" : "false");
     567       10882 :                 break;
     568             : #endif
     569        4402 :         case AV_OPT_TYPE_FLOAT:
     570        4402 :                 arg.arg_type = GF_PROP_FLOAT;
     571        4402 :                 sprintf(szDef, "%g", opt->default_val.dbl);
     572        4402 :                 arg.arg_default_val = gf_strdup(szDef);
     573        4402 :                 break;
     574         155 :         case AV_OPT_TYPE_DOUBLE:
     575         155 :                 arg.arg_type = GF_PROP_DOUBLE;
     576         155 :                 sprintf(szDef, "%g", opt->default_val.dbl);
     577         155 :                 arg.arg_default_val = gf_strdup(szDef);
     578         155 :                 break;
     579        1831 :         case AV_OPT_TYPE_VIDEO_RATE:
     580             :         case AV_OPT_TYPE_RATIONAL:
     581        1831 :                 arg.arg_type = GF_PROP_FRACTION;
     582        1831 :                 sprintf(szDef, "%d/%d", opt->default_val.q.num, opt->default_val.q.den);
     583        1831 :                 arg.arg_default_val = gf_strdup(szDef);
     584        1831 :                 break;
     585        6806 :         case AV_OPT_TYPE_COLOR://color is a string in libavfilter
     586             :         case AV_OPT_TYPE_STRING:
     587             :         case AV_OPT_TYPE_DICT:
     588        6806 :                 arg.arg_type = GF_PROP_STRING;
     589        6806 :                 if (opt->default_val.str)
     590        1062 :                         arg.arg_default_val = gf_strdup(opt->default_val.str);
     591             :                 break;
     592        1210 :         case AV_OPT_TYPE_IMAGE_SIZE:
     593        1210 :                 arg.arg_type = GF_PROP_STRING;
     594        1210 :                 break;
     595       61832 :         case AV_OPT_TYPE_CONST:
     596       61832 :                 arg.arg_type = GF_PROP_BOOL;
     597       61832 :                 arg.arg_default_val = gf_strdup("false");
     598       61832 :                 break;
     599        2574 :         case AV_OPT_TYPE_FLAGS:
     600        2574 :                 arg.arg_type = GF_PROP_UINT;
     601        2574 :                 sprintf(szDef, ""LLD, opt->default_val.i64);
     602        2574 :                 arg.arg_default_val = gf_strdup(szDef);
     603        2574 :                 break;
     604         992 :         case AV_OPT_TYPE_BINARY:
     605             :         case AV_OPT_TYPE_DURATION:
     606         992 :                 arg.arg_type = GF_PROP_UINT;
     607         992 :                 break;
     608          31 :         case AV_OPT_TYPE_SAMPLE_FMT:
     609          31 :                 arg.arg_type = GF_PROP_UINT;
     610          31 :                 arg.arg_default_val = gf_strdup("s16");
     611          31 :                 arg.min_max_enum = gf_strdup("u8|s16|s32|flt|dbl|u8p|s16p|s32p|fltp|dblp");
     612          31 :                 break;
     613          32 :         case AV_OPT_TYPE_PIXEL_FMT:
     614          32 :                 arg.arg_type = GF_PROP_UINT;
     615          32 :                 arg.arg_default_val = gf_strdup(av_get_pix_fmt_name(AV_PIX_FMT_YUV420P) );
     616             :                 {
     617             :                 u32 i, all_len=1, def_size=1000;
     618          32 :                 char *enum_val = gf_malloc(sizeof(char)*def_size);
     619          32 :                 enum_val[0] = 0;
     620       11424 :                 for (i=0; i<AV_PIX_FMT_NB; i++) {
     621             :                         u32 len;
     622       11392 :                         const char *n = av_get_pix_fmt_name(i);
     623       11392 :                         if (!n) continue;
     624             : 
     625        6112 :                         len = (u32) strlen(n)+ (i ? 2 : 1);
     626        6112 :                         if (len+all_len>def_size) {
     627          32 :                                 def_size+=1000;
     628          32 :                                 enum_val = gf_realloc(enum_val, sizeof(char)*def_size);
     629             :                         }
     630        6112 :                         if (i) strcat(enum_val, "|");
     631             :                         strcat(enum_val, n);
     632        6112 :                         all_len+=len-1;
     633             :                 }
     634          32 :                 arg.min_max_enum = enum_val;
     635             :                 }
     636          32 :                 break;
     637           0 :         default:
     638           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[FFMPEG] Unknown ffmpeg option type %d\n", opt->type));
     639             :                 break;
     640             :         }
     641      132942 :         return arg;
     642             : }
     643             : 
     644             : static u32 ff_streamtype(u32 st)
     645             : {
     646             :         switch (st) {
     647             :         case AVMEDIA_TYPE_AUDIO: return GF_STREAM_AUDIO;
     648             :         case AVMEDIA_TYPE_VIDEO: return GF_STREAM_VISUAL;
     649             :         case AVMEDIA_TYPE_DATA: return GF_STREAM_METADATA;
     650             :         case AVMEDIA_TYPE_SUBTITLE: return GF_STREAM_TEXT;
     651             :         }
     652             :         return GF_STREAM_UNKNOWN;
     653             : }
     654             : 
     655             : #if (LIBAVFORMAT_VERSION_MAJOR >= 58) && (LIBAVFORMAT_VERSION_MINOR>=30)
     656             : #else
     657             : #define NO_AVIO_PROTO
     658             : #endif
     659             : 
     660         155 : static void ffmpeg_expand_register(GF_FilterSession *session, GF_FilterRegister *orig_reg, u32 type)
     661             : {
     662             :         u32 i=0, idx=0, flags=0;
     663             : #ifndef NO_AVIO_PROTO
     664             :         Bool protocol_pass = GF_FALSE;
     665             : #endif
     666             :         const struct AVOption *opt;
     667         155 :         GF_List *all_filters = gf_list_new();
     668             :         AVInputFormat *fmt = NULL;
     669             :         const AVOutputFormat *ofmt = NULL;
     670             :         AVCodec *codec = NULL;
     671             : #if (LIBAVFILTER_VERSION_MAJOR > 5)
     672             :         const AVFilter *avf = NULL;
     673             : #endif
     674             : 
     675             : #if !defined(NO_AVIO_PROTO) || (LIBAVFILTER_VERSION_MAJOR > 6)
     676             :         void *av_it;
     677             : #endif
     678             : 
     679             :         const char *fname = "";
     680         155 :         if (type==FF_REG_TYPE_DEMUX) fname = "ffdmx";
     681         124 :         else if (type==FF_REG_TYPE_DECODE) {
     682             :                 fname = "ffdec";
     683             :                 flags=AV_OPT_FLAG_DECODING_PARAM;
     684             :         }
     685          93 :         else if (type==FF_REG_TYPE_DEV_IN) {
     686             :                 fname = "ffavin";
     687          31 :                 avdevice_register_all();
     688             :                 flags=AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_DECODING_PARAM;
     689             :         }
     690          62 :         else if (type==FF_REG_TYPE_ENCODE) {
     691             :                 fname = "ffenc";
     692             :                 flags=AV_OPT_FLAG_ENCODING_PARAM;
     693             :         }
     694          31 :         else if (type==FF_REG_TYPE_MUX) {
     695             :                 fname = "ffmx";
     696             :         }
     697           0 :         else if (type==FF_REG_TYPE_AVF) {
     698             :                 fname = "ffavf";
     699             :         }
     700             :         else return;
     701             : 
     702             : 
     703         155 :         ((GF_FFRegistryExt *)orig_reg->udta)->all_filters = all_filters;
     704             : 
     705             : 
     706             : #ifndef NO_AVIO_PROTO
     707             : second_pass:
     708             : #endif
     709             : 
     710             : #if !defined(NO_AVIO_PROTO) || (LIBAVFILTER_VERSION_MAJOR > 6)
     711             :         av_it = NULL;
     712             : #endif
     713             : 
     714             :         while (1) {
     715             :                 const AVClass *av_class=NULL;
     716             :                 const char *subname = NULL;
     717             : #ifndef GPAC_DISABLE_DOC
     718             :                 const char *description = "description unavailable in ffmpeg";
     719             : #endif
     720             :                 char szDef[100];
     721             :                 GF_FilterRegister *freg;
     722       63068 :                 if (type==FF_REG_TYPE_DEMUX) {
     723             : #ifndef NO_AVIO_PROTO
     724             :                         if (protocol_pass) {
     725             :                                 subname = avio_enum_protocols(&av_it, 0);
     726             :                                 if (!subname) break;
     727             :                                 av_class = avio_protocol_get_class(subname);
     728             : #ifndef GPAC_DISABLE_DOC
     729             :                                 description = "Input protocol";
     730             : #endif
     731             :                         } else
     732             : #endif
     733             :                         {
     734        8756 :                                 fmt = av_iformat_next(fmt);
     735        8756 :                                 if (!fmt) break;
     736        8725 :                                 av_class = fmt->priv_class;
     737        8725 :                                 subname = fmt->name;
     738             : #ifndef GPAC_DISABLE_DOC
     739        8725 :                                 description = fmt->long_name;
     740             : #endif
     741             :                         }
     742       54312 :                 } else if (type==FF_REG_TYPE_DECODE) {
     743       19995 :                         codec = av_codec_next(codec);
     744       19995 :                         if (!codec) break;
     745       19964 :                         if (!av_codec_is_decoder(codec))
     746       34472 :                                 continue;
     747             : 
     748       14260 :                         av_class = codec->priv_class;
     749       14260 :                         subname = codec->name;
     750             : #ifndef GPAC_DISABLE_DOC
     751       14260 :                         description = codec->long_name;
     752             : #endif
     753       34317 :                 } else if (type==FF_REG_TYPE_DEV_IN) {
     754             : #if (LIBAVCODEC_VERSION_MAJOR >= 58) && (LIBAVCODEC_VERSION_MINOR>=20)
     755             :                         fmt = av_input_video_device_next(fmt);
     756             :                         if (!fmt) break;
     757             :                         av_class = fmt->priv_class;
     758             :                         subname = fmt->name;
     759             : #ifndef GPAC_DISABLE_DOC
     760             :                         description = fmt->long_name;
     761             : #endif
     762             :                 if (!av_class || (av_class->category!=AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) ) continue;
     763             : #else
     764        9176 :                         fmt = av_iformat_next(fmt);
     765        9176 :                         if (!fmt) break;
     766        9145 :                         av_class = fmt->priv_class;
     767        9145 :                         subname = fmt->name;
     768             : #ifndef GPAC_DISABLE_DOC
     769        9145 :                         description = fmt->long_name;
     770             : #endif
     771             :                         //brute force ...
     772        9145 :                         if (!strcmp(subname, "dshow")) {}
     773        9145 :                         else if (!strcmp(subname, "avfoundation")) {}
     774        9145 :                         else if (!strcmp(subname, "video4linux2")) {}
     775        9145 :                         else if (!strcmp(subname, "x11grab")) {}
     776        9114 :                         else if (!strcmp(subname, "alsa")) {}
     777        9083 :                         else if (!strcmp(subname, "decklink")) {}
     778        9083 :                         else if (!strcmp(subname, "kmsgrab")) {}
     779        9052 :                         else if (!strcmp(subname, "libndi_newtek")) {}
     780        9052 :                         else if (!strcmp(subname, "fbdev")) {}
     781        9021 :                         else if (!strcmp(subname, "gdigrab")) {}
     782        9021 :                         else if (!strcmp(subname, "iec61883")) {}
     783        8990 :                         else if (!strcmp(subname, "lavfi")) {}
     784        8959 :                         else if (!strcmp(subname, "libcdio")) {}
     785        8928 :                         else if (!strcmp(subname, "openal")) {}
     786        8897 :                         else if (!strcmp(subname, "oss")) {}
     787        8866 :                         else if (!strcmp(subname, "pulse")) {}
     788        8835 :                         else if (!strcmp(subname, "sndio")) {}
     789        8804 :                         else if (!stricmp(subname, "vfw")) {}
     790        8804 :                         else continue;
     791             : #endif
     792       25141 :                 } else if (type==FF_REG_TYPE_ENCODE) {
     793       19995 :                         codec = av_codec_next(codec);
     794       19995 :                         if (!codec) break;
     795       19964 :                         if (!av_codec_is_encoder(codec))
     796       14260 :                                 continue;
     797        5704 :                         av_class = codec->priv_class;
     798        5704 :                         subname = codec->name;
     799             : #ifndef GPAC_DISABLE_DOC
     800        5704 :                         description = codec->long_name;
     801             : #endif
     802        5146 :                 } else if (type==FF_REG_TYPE_MUX) {
     803             : #ifndef NO_AVIO_PROTO
     804             :                         if (protocol_pass) {
     805             :                                 subname = avio_enum_protocols(&av_it, 1);
     806             :                                 if (!subname) break;
     807             :                                 av_class = avio_protocol_get_class(subname);
     808             : #ifndef GPAC_DISABLE_DOC
     809             :                                 description = "Output protocol";
     810             : #endif
     811             :                         } else
     812             : #endif
     813             : 
     814             :                         {
     815             : #if (LIBAVFILTER_VERSION_MAJOR > 6)
     816             :                                 ofmt = av_muxer_iterate(&av_it);
     817             : #else
     818        5146 :                                 ofmt = av_oformat_next(ofmt);
     819             : #endif
     820        5146 :                                 if (!ofmt) break;
     821        5115 :                                 av_class = ofmt->priv_class;
     822        5115 :                                 subname = ofmt->name;
     823             : #ifndef GPAC_DISABLE_DOC
     824        5115 :                                 description = ofmt->long_name;
     825             : #endif
     826             :                         }
     827           0 :                 } else if (type==FF_REG_TYPE_AVF) {
     828             : #if (LIBAVFILTER_VERSION_MAJOR > 5)
     829             : #if (LIBAVFILTER_VERSION_MAJOR > 6)
     830             :                         avf = av_filter_iterate(&av_it);
     831             : #else
     832           0 :                         avf = avfilter_next(avf);
     833             : #endif
     834           0 :                         if (!avf) break;
     835           0 :                         av_class = avf->priv_class;
     836           0 :                         subname = avf->name;
     837             : #ifndef GPAC_DISABLE_DOC
     838           0 :                         description = avf->description;
     839             : #endif
     840             : 
     841             : #else
     842             :                         break;
     843             : 
     844             : #endif
     845             :                 } else {
     846             :                         break;
     847             :                 }
     848       34145 :                 GF_SAFEALLOC(freg, GF_FilterRegister);
     849       34145 :                 if (!freg) continue;
     850             :                 memcpy(freg, orig_reg, sizeof(GF_FilterRegister));
     851       34145 :                 freg->args = NULL;
     852       34145 :                 freg->caps = NULL;
     853       34145 :                 freg->nb_caps = 0;
     854             :                 //no help
     855       34145 :                 freg->help = NULL;
     856             : 
     857       34145 :                 gf_list_add(all_filters, freg);
     858             : 
     859             :                 sprintf(szDef, "%s:%s", fname, subname);
     860       34145 :                 freg->name = gf_strdup(szDef);
     861             : #ifndef GPAC_DISABLE_DOC
     862       34145 :                 freg->description = description;
     863             : #endif
     864       34145 :                  if ((type==FF_REG_TYPE_ENCODE) || (type==FF_REG_TYPE_DECODE)) {
     865             :                         GF_FilterCapability *caps;
     866       19964 :                         u32 cid = ffmpeg_codecid_to_gpac(codec->id);
     867       19964 :                         freg->nb_caps = 3;
     868             : 
     869       19964 :                         caps = gf_malloc(sizeof(GF_FilterCapability)*3);
     870             :                         memset(caps, 0, sizeof(GF_FilterCapability)*3);
     871       19964 :                         caps[0].code = GF_PROP_PID_STREAM_TYPE;
     872       19964 :                         caps[0].val.type = GF_PROP_UINT;
     873       19964 :                         caps[0].val.value.uint = ff_streamtype(codec->type);
     874       19964 :                         caps[0].flags = GF_CAPS_INPUT_OUTPUT;
     875             : 
     876       19964 :                         caps[1].code = GF_PROP_PID_CODECID;
     877       19964 :                         caps[1].val.type = GF_PROP_UINT;
     878       19964 :                         caps[1].val.value.uint = (type==FF_REG_TYPE_DECODE) ? cid : GF_CODECID_RAW;
     879       19964 :                         caps[1].flags = GF_CAPS_INPUT;
     880             : 
     881       19964 :                         caps[2].code = GF_PROP_PID_CODECID;
     882       19964 :                         caps[2].val.type = GF_PROP_UINT;
     883       19964 :                         caps[2].val.value.uint = (type==FF_REG_TYPE_DECODE) ? GF_CODECID_RAW : cid;
     884       19964 :                         caps[2].flags = GF_CAPS_OUTPUT;
     885             : 
     886       19964 :                         freg->caps =  caps;
     887             :                 }
     888       28362 :                 else if ((type==FF_REG_TYPE_DEMUX)
     889       14181 :                         && fmt
     890             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     891             :                         && (fmt->mime_type || fmt->extensions)
     892             : #else
     893        8725 :                         && fmt->extensions
     894             : #endif
     895        3751 :                         ){
     896             :                         GF_FilterCapability *caps;
     897             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     898             :                         freg->nb_caps = (fmt->mime_type && fmt->extensions) ? 4 : 2;
     899             : #else
     900        3751 :                         freg->nb_caps = 2;
     901             : #endif
     902        3751 :                         caps = gf_malloc(sizeof(GF_FilterCapability)*freg->nb_caps);
     903        3751 :                         memset(caps, 0, sizeof(GF_FilterCapability)*freg->nb_caps);
     904        3751 :                         caps[0].code = GF_PROP_PID_STREAM_TYPE;
     905        3751 :                         caps[0].val.type = GF_PROP_UINT;
     906        3751 :                         caps[0].val.value.uint = GF_STREAM_FILE;
     907        3751 :                         caps[0].flags = GF_CAPS_INPUT_STATIC;
     908             : 
     909        3751 :                         caps[1].code = fmt->extensions ? GF_PROP_PID_FILE_EXT : GF_PROP_PID_MIME;
     910        3751 :                         caps[1].val.type = GF_PROP_NAME;
     911             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     912             :                         caps[1].val.value.string = (char *) ( fmt->extensions ? fmt->extensions : fmt->mime_type );
     913             : #else
     914        3751 :                         caps[1].val.value.string = (char *) fmt->extensions;
     915             : #endif
     916        3751 :                         caps[1].flags = GF_CAPS_INPUT;
     917             : 
     918             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     919             :                         if (fmt->mime_type && fmt->extensions) {
     920             :                                 caps[2].flags = 0;
     921             :                                 caps[3].code = GF_PROP_PID_MIME;
     922             :                                 caps[3].val.type = GF_PROP_NAME;
     923             :                                 caps[3].val.value.string = (char *) fmt->mime_type;
     924             :                                 caps[3].flags = GF_CAPS_INPUT;
     925             :                         }
     926             : #endif
     927             :                         //TODO map codec IDs if known ?
     928        3751 :                         freg->caps =  caps;
     929             :                 }
     930       20860 :                 else if ((type==FF_REG_TYPE_MUX)
     931       10430 :                         && ofmt
     932             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     933             :                         && (ofmt->mime_type || ofmt->extensions)
     934             : #else
     935        5115 :                         && ofmt->extensions
     936             : #endif
     937             :                         ){
     938             :                         GF_FilterCapability *caps;
     939             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     940             :                         freg->nb_caps = (ofmt->mime_type && ofmt->extensions) ? 4 : 2;
     941             : #else
     942        3441 :                         freg->nb_caps = 2;
     943             : #endif
     944        3441 :                         caps = gf_malloc(sizeof(GF_FilterCapability)*freg->nb_caps);
     945        3441 :                         memset(caps, 0, sizeof(GF_FilterCapability)*freg->nb_caps);
     946        3441 :                         caps[0].code = GF_PROP_PID_STREAM_TYPE;
     947        3441 :                         caps[0].val.type = GF_PROP_UINT;
     948        3441 :                         caps[0].val.value.uint = GF_STREAM_FILE;
     949        3441 :                         caps[0].flags = GF_CAPS_OUTPUT_STATIC;
     950             : 
     951        3441 :                         caps[1].code = ofmt->extensions ? GF_PROP_PID_FILE_EXT : GF_PROP_PID_MIME;
     952        3441 :                         caps[1].val.type = GF_PROP_NAME;
     953             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     954             :                         caps[1].val.value.string = (char *) ( ofmt->extensions ? ofmt->extensions : ofmt->mime_type );
     955             : #else
     956        3441 :                         caps[1].val.value.string = (char *) ofmt->extensions;
     957             : #endif
     958        3441 :                         caps[1].flags = GF_CAPS_OUTPUT;
     959             : 
     960             : #if LIBAVCODEC_VERSION_MAJOR >= 58
     961             :                         if (ofmt->mime_type && ofmt->extensions) {
     962             :                                 caps[2].flags = 0;
     963             :                                 caps[3].code = GF_PROP_PID_MIME;
     964             :                                 caps[3].val.type = GF_PROP_NAME;
     965             :                                 caps[3].val.value.string = (char *) ofmt->mime_type;
     966             :                                 caps[3].flags = GF_CAPS_OUTPUT;
     967             :                         }
     968             : #endif
     969             :                         //TODO map codec IDs if known ?
     970        3441 :                         freg->caps =  caps;
     971             :                 }
     972             : 
     973             :                 idx=0;
     974             :                 i=0;
     975      181454 :                 while (av_class) {
     976      123439 :                         opt = &av_class->option[idx];
     977      123439 :                         if (!opt || !opt->name) break;
     978      113164 :                         if (!flags || (opt->flags & flags) ) {
     979      112606 :                                 if (!opt->unit)
     980       54579 :                                         i++;
     981             :                                 else {
     982             :                                         u32 k;
     983             :                                         Bool is_first = GF_TRUE;
     984      755913 :                                         for (k=0; k<idx; k++) {
     985      804292 :                                                 const struct AVOption *an_opt = &av_class->option[k];
     986      804292 :                                                 if (an_opt && an_opt->unit && !strcmp(opt->unit, an_opt->unit)) {
     987             :                                                         //patch some broken AVClass where the option name declaring the option unit is not declared first
     988             :                                                         u32 l;
     989      603664 :                                                         for (l=0; l<k; l++) {
     990      603664 :                                                                 const struct AVOption *par_opt = &av_class->option[l];
     991      603664 :                                                                 if (!strcmp(par_opt->name, an_opt->name)) {
     992             :                                                                         is_first=GF_FALSE;
     993             :                                                                         break;
     994             :                                                                 }
     995             :                                                         }
     996             :                                                         break;
     997             :                                                 }
     998             :                                         }
     999       58027 :                                         if (is_first)
    1000       58027 :                                                 i++;
    1001             :                                 }
    1002             :                         }
    1003      113164 :                         idx++;
    1004             :                 }
    1005       34145 :                 if (i) {
    1006       10027 :                         GF_FilterArgs *args = gf_malloc(sizeof(GF_FilterArgs)*(i+1));
    1007             :                         memset(args, 0, sizeof(GF_FilterArgs)*(i+1));
    1008       10027 :                         freg->args = args;
    1009             : 
    1010             :                         i=0;
    1011             :                         idx=0;
    1012      133094 :                         while (av_class) {
    1013      123067 :                                 opt = &av_class->option[idx];
    1014      123067 :                                 if (!opt || !opt->name) break;
    1015      113040 :                                 if (flags && !(opt->flags & flags) ) {
    1016         434 :                                         idx++;
    1017         434 :                                         continue;
    1018             :                                 }
    1019             : 
    1020      112606 :                                 if (opt->unit) {
    1021             :                                         u32 k;
    1022             :                                         const char *opt_name = NULL;
    1023             :                                         GF_FilterArgs *par_arg=NULL;
    1024      755913 :                                         for (k=0; k<idx; k++) {
    1025      804292 :                                                 const struct AVOption *an_opt = &av_class->option[k];
    1026      804292 :                                                 if (an_opt && an_opt->unit && !strcmp(opt->unit, an_opt->unit)) {
    1027       48379 :                                                         opt_name = an_opt->name;
    1028       48379 :                                                         break;
    1029             :                                                 }
    1030             :                                         }
    1031       58027 :                                         if (opt_name) {
    1032      242991 :                                                 for (k=0; k<i; k++) {
    1033      291370 :                                                         par_arg = &args[k];
    1034      291370 :                                                         if (!strcmp(par_arg->arg_name, opt_name))
    1035             :                                                                 break;
    1036             :                                                         par_arg = NULL;
    1037             :                                                 }
    1038             :                                         }
    1039             : 
    1040       48379 :                                         if (par_arg) {
    1041       48379 :                                                 GF_FilterArgs an_arg = ffmpeg_arg_translate(opt);
    1042       48379 :                                                 if (!(par_arg->flags & GF_FS_ARG_META_ALLOC)) {
    1043        9462 :                                                         par_arg->arg_desc = par_arg->arg_desc ? gf_strdup(par_arg->arg_desc) : NULL;
    1044        9462 :                                                         par_arg->flags |= GF_FS_ARG_META_ALLOC;
    1045             :                                                 }
    1046       48379 :                                                 gf_dynstrcat((char **) &par_arg->arg_desc, an_arg.arg_name, "\n - ");
    1047       48379 :                                                 gf_dynstrcat((char **) &par_arg->arg_desc, an_arg.arg_desc, ": ");
    1048             : 
    1049       48379 :                                                 if (an_arg.arg_default_val)
    1050       48379 :                                                         gf_free((void *) an_arg.arg_default_val);
    1051       48379 :                                                 if (an_arg.min_max_enum)
    1052         528 :                                                         gf_free((void *) an_arg.min_max_enum);
    1053             : 
    1054       48379 :                                                 idx++;
    1055       48379 :                                                 continue;
    1056             :                                         }
    1057             :                                 }
    1058             : 
    1059       64227 :                                 args[i] = ffmpeg_arg_translate(opt);
    1060       64227 :                                 i++;
    1061             : 
    1062       64227 :                                 idx++;
    1063             :                         }
    1064             :                 }
    1065       34145 :                 gf_fs_add_filter_register(session, freg);
    1066             :         }
    1067             : 
    1068             : #ifndef NO_AVIO_PROTO
    1069             :         if ((type==FF_REG_TYPE_MUX) || (type==FF_REG_TYPE_DEMUX)) {
    1070             :                 if (!protocol_pass) {
    1071             :                         protocol_pass = GF_TRUE;
    1072             :                         goto second_pass;
    1073             :                 }
    1074             :         }
    1075             : #endif
    1076             : 
    1077             : }
    1078             : 
    1079       14385 : void ffmpeg_build_register(GF_FilterSession *session, GF_FilterRegister *orig_reg, const GF_FilterArgs *default_args, u32 nb_def_args, u32 reg_type)
    1080             : {
    1081             :         GF_FilterArgs *args;
    1082             :         u32 i=0, idx=0, nb_args;
    1083             :         const struct AVOption *opt;
    1084             :         u32 opt_type = AV_OPT_FLAG_DECODING_PARAM;
    1085             :         Bool load_meta_filters = session ? GF_TRUE : GF_FALSE;
    1086             :         AVFormatContext *format_ctx = NULL;
    1087             :         AVCodecContext *codec_ctx = NULL;
    1088             :         const AVClass *av_class = NULL;
    1089             :         GF_FFRegistryExt *ffregext;
    1090             : 
    1091       14385 :         ffmpeg_initialize();
    1092             : 
    1093       14385 :         orig_reg->author = avfilter_configuration();
    1094             :         
    1095             :         //by default no need to load option descriptions, everything is handled by av_set_opt in update_args
    1096       14385 :         if (!load_meta_filters) {
    1097       14230 :                 orig_reg->args = default_args;
    1098       14230 :                 orig_reg->register_free = NULL;
    1099       14230 :                 return;
    1100             :         }
    1101             : 
    1102         155 :         if (reg_type==FF_REG_TYPE_ENCODE) opt_type = AV_OPT_FLAG_ENCODING_PARAM;
    1103         124 :         else if (reg_type==FF_REG_TYPE_MUX) opt_type = AV_OPT_FLAG_ENCODING_PARAM;
    1104          93 :         else if (reg_type==FF_REG_TYPE_AVF) opt_type = 0xFFFFFFFF;
    1105             : 
    1106         155 :         if ((reg_type==FF_REG_TYPE_ENCODE) || (reg_type==FF_REG_TYPE_DECODE)) {
    1107          62 :                 orig_reg->author = avcodec_configuration();
    1108          62 :                 codec_ctx = avcodec_alloc_context3(NULL);
    1109          62 :                 av_class = codec_ctx->av_class;
    1110          93 :         } else if (reg_type==FF_REG_TYPE_AVF) {
    1111             : #if (LIBAVFILTER_VERSION_MAJOR > 5)
    1112           0 :                 av_class = avfilter_get_class();
    1113             : #endif
    1114             :         } else {
    1115          93 :                 format_ctx = avformat_alloc_context();
    1116          93 :                 av_class = format_ctx->av_class;
    1117             :         }
    1118             : 
    1119             :         i=0;
    1120             :         idx=0;
    1121       33604 :         while (av_class && av_class->option) {
    1122       33449 :                 opt = &av_class->option[idx];
    1123       33449 :                 if (!opt || !opt->name) break;
    1124             : 
    1125       33294 :                 if (opt->flags & opt_type) {
    1126       20336 :                         if (!opt->unit) {
    1127        4557 :                                 i++;
    1128             :                         } else {
    1129             :                                 u32 k;
    1130             :                                 Bool is_first = GF_TRUE;
    1131     3168603 :                                 for (k=0; k<idx; k++) {
    1132     3182491 :                                         const struct AVOption *an_opt = &av_class->option[k];
    1133     3182491 :                                         if (an_opt && an_opt->unit && !strcmp(opt->unit, an_opt->unit)) {
    1134             :                                                 //patch some broken AVClass where the option name declaring the option unit is not declared first
    1135             :                                                 u32 l;
    1136     2793999 :                                                 for (l=0; l<k; l++) {
    1137     2793999 :                                                         const struct AVOption *par_opt = &av_class->option[l];
    1138     2793999 :                                                         if (!strcmp(par_opt->name, an_opt->name)) {
    1139             :                                                                 is_first=GF_FALSE;
    1140             :                                                                 break;
    1141             :                                                         }
    1142             :                                                 }
    1143             :                                                 break;
    1144             :                                         }
    1145             :                                 }
    1146       15779 :                                 if (is_first)
    1147       15779 :                                         i++;
    1148             :                         }
    1149             :                 }
    1150       33294 :                 idx++;
    1151             :         }
    1152         155 :         i += nb_def_args;
    1153             : 
    1154         155 :         nb_args = i+1;
    1155         155 :         args = gf_malloc(sizeof(GF_FilterArgs)*nb_args);
    1156             :         memset(args, 0, sizeof(GF_FilterArgs)*nb_args);
    1157         155 :         orig_reg->args = args;
    1158             : 
    1159         868 :         for (i=0; i<nb_def_args-1; i++) {
    1160         713 :                 memcpy(&args[i], &default_args[i], sizeof(GF_FilterArgs));
    1161             :         }
    1162             :         //do not reset i
    1163             : 
    1164             :         idx=0;
    1165       33449 :         while (av_class && av_class->option) {
    1166       33449 :                 opt = &av_class->option[idx];
    1167       33449 :                 if (!opt || !opt->name) break;
    1168             : 
    1169       33294 :                 if (opt->flags & opt_type) {
    1170             : 
    1171       20336 :                         if (opt->unit) {
    1172             :                                 u32 k;
    1173             :                                 const char *opt_name = NULL;
    1174             :                                 GF_FilterArgs *par_arg=NULL;
    1175     3168603 :                                 for (k=0; k<idx; k++) {
    1176     3182491 :                                         const struct AVOption *an_opt = &av_class->option[k];
    1177     3182491 :                                         if (an_opt && an_opt->unit && !strcmp(opt->unit, an_opt->unit)) {
    1178       13888 :                                                 opt_name = an_opt->name;
    1179       13888 :                                                 break;
    1180             :                                         }
    1181             :                                 }
    1182       15779 :                                 if (opt_name) {
    1183      569036 :                                         for (k=0; k<i; k++) {
    1184      582707 :                                                 par_arg = &args[k];
    1185      582707 :                                                 if (!strcmp(par_arg->arg_name, opt_name))
    1186             :                                                         break;
    1187             :                                                 par_arg = NULL;
    1188             :                                         }
    1189             :                                 }
    1190             : 
    1191       13888 :                                 if (par_arg) {
    1192       13671 :                                         GF_FilterArgs an_arg = ffmpeg_arg_translate(opt);
    1193       13671 :                                         if (!(par_arg->flags & GF_FS_ARG_META_ALLOC)) {
    1194             :                                                 //move from const to allocated memory
    1195        1767 :                                                 par_arg->arg_desc = gf_strdup(par_arg->arg_desc ? par_arg->arg_desc : " ");
    1196        1767 :                                                 par_arg->flags |= GF_FS_ARG_META_ALLOC;
    1197             :                                                 /*trash default values and min_max_enum for flags*/
    1198        1767 :                                                 if (par_arg->arg_default_val) {
    1199        1767 :                                                         gf_free((char *) par_arg->arg_default_val);
    1200        1767 :                                                         par_arg->arg_default_val = NULL;
    1201             :                                                 }
    1202        1767 :                                                 if (par_arg->min_max_enum) {
    1203        1023 :                                                         gf_free((char *) par_arg->min_max_enum);
    1204        1023 :                                                         par_arg->min_max_enum = NULL;
    1205             :                                                 }
    1206             :                                         }
    1207       13671 :                                         gf_dynstrcat((char **) &par_arg->arg_desc, an_arg.arg_name, "\n- ");
    1208       13671 :                                         gf_dynstrcat((char **) &par_arg->arg_desc, an_arg.arg_desc ? an_arg.arg_desc : "", ": ");
    1209             : 
    1210       13671 :                                         if (an_arg.arg_default_val)
    1211       13671 :                                                 gf_free((void *) an_arg.arg_default_val);
    1212       13671 :                                         if (an_arg.min_max_enum)
    1213         310 :                                                 gf_free((void *) an_arg.min_max_enum);
    1214             : 
    1215       13671 :                                         idx++;
    1216       13671 :                                         continue;
    1217             :                                 }
    1218             :                         }
    1219             :                         assert(nb_args>i);
    1220        6665 :                         args[i] = ffmpeg_arg_translate(opt);
    1221        6665 :                         i++;
    1222             :                 }
    1223       19623 :                 idx++;
    1224             :         }
    1225         155 :         memcpy(&args[i], &default_args[nb_def_args-1], sizeof(GF_FilterArgs));
    1226             : 
    1227         155 :         if (codec_ctx) {
    1228             : #if (LIBAVCODEC_VERSION_MAJOR >= 58) && (LIBAVCODEC_VERSION_MINOR>=20)
    1229             :                 avcodec_free_context(&codec_ctx);
    1230             : #else
    1231          62 :                 av_free(codec_ctx);
    1232             : #endif
    1233             :         } else {
    1234          93 :                 avformat_free_context(format_ctx);
    1235             :         }
    1236             : 
    1237         155 :         GF_SAFEALLOC(ffregext, GF_FFRegistryExt);
    1238         155 :         if (!ffregext) return;
    1239             :         
    1240         155 :         orig_reg->udta = ffregext;
    1241         155 :         ffregext->nb_arg_skip = nb_def_args-1;
    1242         155 :         orig_reg->register_free = ffmpeg_register_free;
    1243             : 
    1244         155 :         ffmpeg_expand_register(session, orig_reg, reg_type);
    1245             : 
    1246             : }
    1247             : 
    1248         182 : void ffmpeg_set_enc_dec_flags(const AVDictionary *options, AVCodecContext *ctx)
    1249             : {
    1250             :         AVDictionaryEntry *de=NULL;
    1251             : 
    1252         182 :         ctx->flags = 0;
    1253         182 :         ctx->flags2 = 0;
    1254             :         while (1) {
    1255             :                 u32 idx=0;
    1256         262 :                 de = av_dict_get((AVDictionary *)options, "", (const AVDictionaryEntry *) de, AV_DICT_IGNORE_SUFFIX);
    1257         262 :                 if (!de) break;
    1258             : 
    1259       34640 :                 while (ctx->av_class->option) {
    1260       34640 :                         const struct AVOption *opt = &ctx->av_class->option[idx];
    1261       34640 :                         if (!opt || !opt->name) break;
    1262       34560 :                         if (opt->name && !strcmp(opt->name, de->key) && (!stricmp(de->value, "true") || !stricmp(de->value, "yes") || !stricmp(de->value, "1") )) {
    1263           0 :                                 if (opt->unit && !strcmp(opt->unit, "flags"))
    1264           0 :                                         ctx->flags |= (int) opt->default_val.i64;
    1265           0 :                                 else if (opt->unit && !strcmp(opt->unit, "flags2"))
    1266           0 :                                         ctx->flags2 |= (int) opt->default_val.i64;
    1267             :                                 break;
    1268             :                         }
    1269       34560 :                         idx++;
    1270             :                 }
    1271             :         }
    1272         182 : }
    1273             : 
    1274           7 : void ffmpeg_set_mx_dmx_flags(const AVDictionary *options, AVFormatContext *ctx)
    1275             : {
    1276             :         AVDictionaryEntry *de=NULL;
    1277             : 
    1278             :         while (1) {
    1279             :                 u32 idx=0;
    1280           7 :                 de = av_dict_get((AVDictionary *)options, "", de, AV_DICT_IGNORE_SUFFIX);
    1281           7 :                 if (!de) break;
    1282             : 
    1283           0 :                 while (ctx->av_class->option) {
    1284           0 :                         const struct AVOption *opt = &ctx->av_class->option[idx];
    1285           0 :                         if (!opt || !opt->name) break;
    1286           0 :                         if (opt->name && !strcmp(opt->name, de->key)) {
    1287           0 :                                 if (opt->unit && !strcmp(opt->unit, "fflags"))
    1288           0 :                                         ctx->flags |= (int) opt->default_val.i64;
    1289           0 :                                 else if (opt->unit && !strcmp(opt->unit, "avioflags"))
    1290           0 :                                         ctx->avio_flags |= (int) opt->default_val.i64;
    1291             :                                 break;
    1292             :                         }
    1293           0 :                         idx++;
    1294             :                 }
    1295             :         }
    1296           7 : }
    1297             : 
    1298          58 : void ffmpeg_report_unused_options(GF_Filter *filter, AVDictionary *options)
    1299             : {
    1300             :         AVDictionaryEntry *prev_e = NULL;
    1301         190 :         while (options) {
    1302         120 :                 prev_e = av_dict_get(options, "", prev_e, AV_DICT_IGNORE_SUFFIX);
    1303         120 :                 if (!prev_e) break;
    1304          74 :                 gf_filter_report_unused_meta_option(filter, prev_e->key);
    1305             :         }
    1306             : 
    1307          58 : }
    1308             : #endif

Generated by: LCOV version 1.13