LCOV - code coverage report
Current view: top level - filters - write_generic.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 564 646 87.3 %
Date: 2021-04-29 23:48:07 Functions: 15 15 100.0 %

          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 / generic stream to file 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/constants.h>
      28             : #include <gpac/bitstream.h>
      29             : #include <gpac/xml.h>
      30             : #include <gpac/base_coding.h>
      31             : 
      32             : #include <gpac/internal/isomedia_dev.h>
      33             : 
      34             : enum
      35             : {
      36             :         DECINFO_NO=0,
      37             :         DECINFO_FIRST,
      38             :         DECINFO_SAP,
      39             :         DECINFO_AUTO
      40             : };
      41             : 
      42             : typedef struct
      43             : {
      44             :         //opts
      45             :         Bool exporter, frame, split, merge_region;
      46             :         u32 sstart, send;
      47             :         u32 pfmt, afmt, decinfo;
      48             :         GF_Fraction dur;
      49             : 
      50             :         //only one input pid declared
      51             :         GF_FilterPid *ipid;
      52             :         //only one output pid declared
      53             :         GF_FilterPid *opid;
      54             : 
      55             :         u32 codecid;
      56             :         Bool is_mj2k;
      57             :         u32 sample_num;
      58             : 
      59             :         const char *dcfg;
      60             :         u32 dcfg_size;
      61             :         Bool cfg_sent;
      62             : 
      63             :         GF_Fraction64 duration;
      64             :         Bool first;
      65             : 
      66             :         GF_BitStream *bs;
      67             : 
      68             :         u32 target_pfmt, target_afmt;
      69             :         Bool is_bmp;
      70             :         u32 is_wav;
      71             :         u32 w, h, stride;
      72             :         u64 nb_bytes;
      73             :         Bool dash_mode;
      74             :         Bool trunc_audio;
      75             : 
      76             :         u64 first_dts_plus_one;
      77             : 
      78             :         Bool ttml_agg;
      79             :         GF_XMLNode *ttml_root;
      80             : } GF_GenDumpCtx;
      81             : 
      82             : 
      83        1779 : GF_Err writegen_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
      84             : {
      85             :         u32 cid, chan, sr, w, h, stype, pf, sfmt, av1mode, nb_bps;
      86             :         const char *name, *mimetype;
      87             :         char szExt[GF_4CC_MSIZE], szCodecExt[30], *sep;
      88             :         const GF_PropertyValue *p;
      89        1779 :         GF_GenDumpCtx *ctx = gf_filter_get_udta(filter);
      90             : 
      91        1779 :         if (is_remove) {
      92           0 :                 ctx->ipid = NULL;
      93           0 :                 if (ctx->opid) {
      94           0 :                         gf_filter_pid_remove(ctx->opid);
      95           0 :                         ctx->opid = NULL;
      96             :                 }
      97             :                 return GF_OK;
      98             :         }
      99        1779 :         if (! gf_filter_pid_check_caps(pid))
     100             :                 return GF_NOT_SUPPORTED;
     101             : 
     102        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
     103        1778 :         if (!p) return GF_NOT_SUPPORTED;
     104        1778 :         cid = p->value.uint;
     105             : 
     106        1778 :         ctx->codecid = cid;
     107        1778 :         if (!ctx->opid) {
     108         949 :                 ctx->opid = gf_filter_pid_new(filter);
     109         949 :                 ctx->first = GF_TRUE;
     110             :         }
     111             : 
     112        1778 :         ctx->ipid = pid;
     113             : 
     114             :         //copy properties at init or reconfig
     115        1778 :         gf_filter_pid_copy_properties(ctx->opid, pid);
     116        1778 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, NULL);
     117             : 
     118        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
     119        1778 :         stype = p ? p->value.uint : 0;
     120             : 
     121        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAMPLE_RATE);
     122        1778 :         sr = p ? p->value.uint : 0;
     123        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_NUM_CHANNELS);
     124        1778 :         chan = p ? p->value.uint : 0;
     125        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_AUDIO_FORMAT);
     126        1778 :         sfmt = p ? p->value.uint : GF_AUDIO_FMT_S16;
     127        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_AUDIO_BPS);
     128        1778 :         nb_bps = p ? p->value.uint : 0;
     129             : 
     130             : 
     131        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_WIDTH);
     132        1778 :         ctx->w = w = p ? p->value.uint : 0;
     133        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_HEIGHT);
     134        1778 :         ctx->h = h = p ? p->value.uint : 0;
     135             : 
     136        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_PIXFMT);
     137        1778 :         pf = p ? p->value.uint : 0;
     138        1527 :         if (!pf) pf = GF_PIXEL_YUV;
     139             : 
     140        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     141        1778 :         if (p) {
     142          19 :                 ctx->dcfg = p->value.data.ptr;
     143          19 :                 ctx->dcfg_size = p->value.data.size;
     144             :         }
     145        1778 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DASH_MODE);
     146        1778 :         ctx->dash_mode = (p && p->value.uint) ? GF_TRUE : GF_FALSE;
     147             : 
     148        1778 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_FILE) );
     149             : 
     150             :         //special case for xml text, override to xml
     151        1778 :         switch (cid) {
     152             :         case GF_CODECID_META_XML:
     153             :         case GF_CODECID_SUBS_XML:
     154             :                 strcpy(szCodecExt, "xml");
     155             :                 break;
     156        1767 :         default:
     157        1767 :                 strncpy(szCodecExt, gf_codecid_file_ext(cid), 29);
     158        1767 :                 szCodecExt[29]=0;
     159        1767 :                 sep = strchr(szCodecExt, '|');
     160        1767 :                 if (sep) sep[0] = 0;
     161             :                 break;
     162             :         }
     163        1778 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING(szCodecExt) );
     164             : 
     165        1778 :         mimetype = gf_codecid_mime(cid);
     166             : 
     167        1778 :         switch (cid) {
     168          13 :         case GF_CODECID_AAC_MPEG4:
     169             :         case GF_CODECID_AAC_MPEG2_MP:
     170             :         case GF_CODECID_AAC_MPEG2_LCP:
     171             :         case GF_CODECID_AAC_MPEG2_SSRP:
     172             :                 //override extension to latm for aac if unframed latm data - NOT for usac
     173          13 :                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_UNFRAMED_LATM);
     174          13 :                 if (p && p->value.boolean) {
     175           2 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING("latm") );
     176             :                 }
     177             :                 break;
     178          40 :         case GF_CODECID_PNG:
     179             :         case GF_CODECID_JPEG:
     180          40 :                 ctx->split = GF_TRUE;
     181          40 :                 break;
     182           1 :         case GF_CODECID_J2K:
     183           1 :                 ctx->split = GF_TRUE;
     184           1 :                 ctx->is_mj2k = GF_TRUE;
     185           1 :                 break;
     186           3 :         case GF_CODECID_AMR:
     187           3 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     188           3 :                 ctx->dcfg = "#!AMR\n";
     189           3 :                 ctx->dcfg_size = 6;
     190           3 :                 ctx->decinfo = DECINFO_FIRST;
     191           3 :                 break;
     192           2 :         case GF_CODECID_AMR_WB:
     193           2 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     194           2 :                 ctx->dcfg = "#!AMR-WB\n";
     195           2 :                 ctx->dcfg_size = 9;
     196           2 :                 ctx->decinfo = DECINFO_FIRST;
     197           2 :                 break;
     198           0 :         case GF_CODECID_SMV:
     199           0 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     200           0 :                 ctx->dcfg = "#!SMV\n";
     201           0 :                 ctx->dcfg_size = 6;
     202           0 :                 ctx->decinfo = DECINFO_FIRST;
     203           0 :                 break;
     204           0 :         case GF_CODECID_EVRC_PV:
     205             :         case GF_CODECID_EVRC:
     206           0 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     207           0 :                 ctx->dcfg = "#!EVRC\n";
     208           0 :                 ctx->dcfg_size = 7;
     209           0 :                 ctx->decinfo = DECINFO_FIRST;
     210           0 :                 break;
     211             : 
     212           1 :         case GF_CODECID_FLAC:
     213           1 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     214           1 :                 ctx->decinfo = DECINFO_FIRST;
     215           1 :                 break;
     216             : 
     217             : 
     218          18 :         case GF_CODECID_SIMPLE_TEXT:
     219          18 :                 if (!gf_filter_pid_get_property(pid, GF_PROP_PID_MIME))
     220          18 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     221          18 :                 if (ctx->decinfo == DECINFO_AUTO)
     222          18 :                         ctx->decinfo = DECINFO_FIRST;
     223             :                 break;
     224           0 :         case GF_CODECID_META_TEXT:
     225           0 :                 if (!gf_filter_pid_get_property(pid, GF_PROP_PID_MIME))
     226           0 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     227           0 :                 if (ctx->decinfo == DECINFO_AUTO)
     228           0 :                         ctx->decinfo = DECINFO_FIRST;
     229             :                 break;
     230           2 :         case GF_CODECID_META_XML:
     231           2 :                 if (!gf_filter_pid_get_property(pid, GF_PROP_PID_MIME))
     232           2 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     233           2 :                 if (ctx->decinfo == DECINFO_AUTO)
     234           2 :                         ctx->decinfo = DECINFO_FIRST;
     235             :                 break;
     236           0 :         case GF_CODECID_SUBS_TEXT:
     237           0 :                 if (!gf_filter_pid_get_property(pid, GF_PROP_PID_MIME))
     238           0 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     239           0 :                 if (ctx->decinfo == DECINFO_AUTO)
     240           0 :                         ctx->decinfo = DECINFO_FIRST;
     241             :                 break;
     242           9 :         case GF_CODECID_SUBS_XML:
     243           9 :                 if (!gf_filter_pid_get_property(pid, GF_PROP_PID_MIME))
     244           9 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     245             : 
     246           9 :                 if (!ctx->frame) {
     247           7 :                         ctx->ttml_agg = GF_TRUE;
     248             :                 } else {
     249           2 :                         ctx->split = GF_TRUE;
     250             :                 }
     251           9 :                 if (ctx->decinfo == DECINFO_AUTO)
     252           9 :                         ctx->decinfo = DECINFO_FIRST;
     253             :                 break;
     254             : 
     255           4 :         case GF_CODECID_AV1:
     256             :                 av1mode = 0;
     257           4 :                 p = gf_filter_pid_get_property_str(ctx->ipid, "obu:mode");
     258           4 :                 if (p) av1mode = p->value.uint;
     259           4 :                 if (av1mode==1) {
     260           2 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING("av1b") );
     261           2 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING("video/x-av1b") );
     262           2 :                 } else if (av1mode==2) {
     263           1 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING("ivf") );
     264           1 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING("video/x-ivf") );
     265             :                 } else {
     266           1 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING("obu") );
     267           1 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING("video/x-av1") );
     268             :                 }
     269             :                 break;
     270        1592 :         case GF_CODECID_RAW:
     271        1592 :                 ctx->dcfg = NULL;
     272        1592 :                 ctx->dcfg_size = 0;
     273        1592 :                 if (stype==GF_STREAM_VISUAL) {
     274        1487 :                         strcpy(szExt, gf_pixel_fmt_sname(ctx->target_pfmt ? ctx->target_pfmt : pf));
     275        1487 :                         p = gf_filter_pid_caps_query(ctx->opid, GF_PROP_PID_FILE_EXT);
     276        1487 :                         if (p) {
     277        1487 :                                 strncpy(szExt, p->value.string, GF_4CC_MSIZE-1);
     278        1487 :                                 szExt[GF_4CC_MSIZE-1] = 0;
     279        1487 :                                 if (!strcmp(szExt, "bmp")) {
     280           3 :                                         ctx->is_bmp = GF_TRUE;
     281             :                                         //request BGR
     282           3 :                                         ctx->target_pfmt = GF_PIXEL_BGR;
     283           3 :                                         ctx->split = GF_TRUE;
     284             :                                 } else {
     285        1484 :                                         ctx->target_pfmt = gf_pixel_fmt_parse(szExt);
     286        1484 :                                         if (!ctx->target_pfmt) {
     287           0 :                                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Cannot guess pixel format from extension type %s\n", szExt));
     288             :                                                 return GF_NOT_SUPPORTED;
     289             :                                         }
     290        1484 :                                         strcpy(szExt, gf_pixel_fmt_sname(ctx->target_pfmt));
     291             :                                 }
     292             :                                 //forcing pixel format regardless of extension
     293        1487 :                                 if (ctx->pfmt) {
     294          15 :                                         if (pf != ctx->pfmt) {
     295           0 :                                                 gf_filter_pid_negociate_property(ctx->ipid, GF_PROP_PID_PIXFMT, &PROP_UINT(ctx->pfmt));
     296             :                                                 //make sure we reconfigure
     297           0 :                                                 ctx->codecid = 0;
     298           0 :                                                 pf = ctx->pfmt;
     299             :                                         }
     300             :                                 }
     301             :                                 //use extension to derive pixel format
     302        1472 :                                 else if (pf != ctx->target_pfmt) {
     303          80 :                                         gf_filter_pid_negociate_property(ctx->ipid, GF_PROP_PID_PIXFMT, &PROP_UINT(ctx->target_pfmt));
     304          80 :                                         strcpy(szExt, gf_pixel_fmt_sname(ctx->target_pfmt));
     305             :                                         //make sure we reconfigure
     306          80 :                                         ctx->codecid = 0;
     307             :                                 }
     308             :                         }
     309             : 
     310        1487 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_STRIDE);
     311        1487 :                         ctx->stride = p ? p->value.uint : 0;
     312             : 
     313        1487 :                         if (!ctx->stride) {
     314         151 :                                 gf_pixel_get_size_info(ctx->target_pfmt ? ctx->target_pfmt : pf, ctx->w, ctx->h, NULL, &ctx->stride, NULL, NULL, NULL);
     315             :                         }
     316             : 
     317         105 :                 } else if (stype==GF_STREAM_AUDIO) {
     318         105 :                         strcpy(szExt, gf_audio_fmt_sname(ctx->target_afmt ? ctx->target_afmt : sfmt));
     319         105 :                         p = gf_filter_pid_caps_query(ctx->opid, GF_PROP_PID_FILE_EXT);
     320         105 :                         if (p) {
     321         105 :                                 strncpy(szExt, p->value.string, GF_4CC_MSIZE-1);
     322         105 :                                 szExt[GF_4CC_MSIZE-1] = 0;
     323         105 :                                 if (!strcmp(szExt, "wav")) {
     324           2 :                                         ctx->is_wav = GF_TRUE;
     325             :                                         //request PCMs16 ?
     326             : //                                      ctx->target_afmt = GF_AUDIO_FMT_S16;
     327           2 :                                         ctx->target_afmt = sfmt;
     328             :                                 } else {
     329         103 :                                         ctx->target_afmt = gf_audio_fmt_parse(szExt);
     330         103 :                                         strcpy(szExt, gf_audio_fmt_sname(ctx->target_afmt));
     331             :                                 }
     332             :                                 //forcing sample format regardless of extension
     333         105 :                                 if (ctx->afmt) {
     334           0 :                                         if (sfmt != ctx->afmt) {
     335           0 :                                                 gf_filter_pid_negociate_property(ctx->ipid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(ctx->afmt));
     336             :                                                 //make sure we reconfigure
     337           0 :                                                 ctx->codecid = 0;
     338           0 :                                                 sfmt = ctx->afmt;
     339             :                                         }
     340             :                                 }
     341             :                                 //use extension to derive sample format
     342         105 :                                 else if (sfmt != ctx->target_afmt) {
     343          31 :                                         gf_filter_pid_negociate_property(ctx->ipid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(ctx->target_afmt));
     344          31 :                                         strcpy(szExt, gf_audio_fmt_sname(ctx->target_afmt));
     345             :                                         //make sure we reconfigure
     346          31 :                                         ctx->codecid = 0;
     347             :                                 }
     348         105 :                                 if (ctx->dur.num && ctx->dur.den && !gf_audio_fmt_is_planar(ctx->target_afmt ? ctx->target_afmt : ctx->afmt))
     349          29 :                                         ctx->trunc_audio = GF_TRUE;
     350             :                         }
     351             : 
     352             :                 } else {
     353           0 :                         strcpy(szExt, gf_4cc_to_str(cid));
     354             :                 }
     355        1592 :                 if (ctx->is_bmp) strcpy(szExt, "bmp");
     356        1589 :                 else if (ctx->is_wav) {
     357           2 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DISABLE_PROGRESSIVE, &PROP_UINT(GF_PID_FILE_PATCH_REPLACE) );
     358             :                         strcpy(szExt, "wav");
     359        1587 :                 } else if (!strlen(szExt)) strcpy(szExt, "raw");
     360             : 
     361        1592 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING( szExt ) );
     362        1592 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING("application/octet-string") );
     363        1592 :                 if (!ctx->codecid) return GF_OK;
     364             :                 break;
     365             : 
     366          93 :         default:
     367          93 :                 if (!strcmp(szCodecExt, "raw")) {
     368           0 :                         strcpy(szExt, gf_4cc_to_str(cid));
     369           0 :                         if (!strlen(szExt)) strcpy(szExt, "raw");
     370           0 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING( szExt ) );
     371             :                 } else {
     372          93 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING( szCodecExt ) );
     373             :                 }
     374          93 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING(mimetype) );
     375          93 :                 break;
     376             :         }
     377             : 
     378        1667 :         if (ctx->decinfo == DECINFO_AUTO)
     379         916 :                 ctx->decinfo = DECINFO_NO;
     380             : 
     381        1667 :         name = gf_codecid_name(cid);
     382        1667 :         if (ctx->exporter) {
     383          26 :                 if (w && h) {
     384          11 :                         if (cid==GF_CODECID_RAW) name = gf_pixel_fmt_name(pf);
     385          11 :                         GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("Exporting %s - Size %dx%d\n", name, w, h));
     386          15 :                 } else if (sr && chan) {
     387           1 :                         if (cid==GF_CODECID_RAW) {
     388           0 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("Exporting PCM %s SampleRate %d %d channels %d bits per sample\n", gf_audio_fmt_name(sfmt), sr, chan, gf_audio_fmt_bit_depth(sfmt) ));
     389             :                         } else {
     390           1 :                                 if (!nb_bps)
     391           1 :                                         nb_bps = gf_audio_fmt_bit_depth(sfmt);
     392             : 
     393           1 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("Exporting %s - SampleRate %d %d channels %d bits per sample\n", name, sr, chan, nb_bps ));
     394             :                         }
     395             :                 } else {
     396          14 :                         GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("Exporting %s\n", name));
     397             :                 }
     398             :         }
     399             : 
     400             :         //avoid creating a file when dumping individual samples
     401        1667 :         if (ctx->split) {
     402          45 :                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_NB_FRAMES);
     403          45 :                 if (!p || (p->value.uint>1))
     404          25 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PCK_FILENUM, &PROP_UINT(0) );
     405             :                 else
     406          20 :                         ctx->split = GF_FALSE;
     407        1622 :         } else if (ctx->frame) {
     408          12 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PCK_FILENUM, &PROP_UINT(0) );
     409             :         }
     410             : 
     411        1667 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DURATION);
     412        1667 :         if (p) ctx->duration = p->value.lfrac;
     413             : 
     414        1667 :         gf_filter_pid_set_framing_mode(pid, GF_TRUE);
     415        1667 :         return GF_OK;
     416             : }
     417             : 
     418           1 : static GF_FilterPacket *writegen_write_j2k(GF_GenDumpCtx *ctx, char *data, u32 data_size, GF_FilterPacket *in_pck)
     419             : {
     420             :         u32 size;
     421             :         u8 *output;
     422             :         GF_FilterPacket *dst_pck;
     423             :         char sig[8];
     424           1 :         sig[0] = sig[1] = sig[2] = 0;
     425           1 :         sig[3] = 0xC;
     426           1 :         sig[4] = 'j';
     427           1 :         sig[5] = 'P';
     428           1 :         sig[6] = sig[7] = ' ';
     429             : 
     430           1 :         if ((data_size>16) && !memcmp(data, sig, 8)) {
     431           0 :                 return gf_filter_pck_new_ref(ctx->opid, 0, 0, in_pck);
     432             :         }
     433             : 
     434           1 :         size = data_size + 8*4 /*jP%20%20 + ftyp*/ + ctx->dcfg_size + 8;
     435             : 
     436           1 :         dst_pck = gf_filter_pck_new_alloc(ctx->opid, size, &output);
     437           1 :         if (!dst_pck) return NULL;
     438             : 
     439             : 
     440           1 :         if (!ctx->bs) ctx->bs = gf_bs_new(output, size, GF_BITSTREAM_WRITE);
     441           0 :         else gf_bs_reassign_buffer(ctx->bs, output, size);
     442             : 
     443           1 :         gf_bs_write_u32(ctx->bs, 12);
     444           1 :         gf_bs_write_u32(ctx->bs, GF_ISOM_BOX_TYPE_JP);
     445           1 :         gf_bs_write_u32(ctx->bs, 0x0D0A870A);
     446           1 :         gf_bs_write_u32(ctx->bs, 20);
     447           1 :         gf_bs_write_u32(ctx->bs, GF_ISOM_BOX_TYPE_FTYP);
     448           1 :         gf_bs_write_u32(ctx->bs, GF_ISOM_BRAND_JP2);
     449           1 :         gf_bs_write_u32(ctx->bs, 0);
     450           1 :         gf_bs_write_u32(ctx->bs, GF_ISOM_BRAND_JP2);
     451             : 
     452             :         //todo, write colr and other info ?
     453           1 :         if (ctx->dcfg) {
     454           1 :                 gf_bs_write_u32(ctx->bs, 8+ctx->dcfg_size);
     455           1 :                 gf_bs_write_u32(ctx->bs, GF_ISOM_BOX_TYPE_JP2H);
     456           1 :                 gf_bs_write_data(ctx->bs, ctx->dcfg, ctx->dcfg_size);
     457             :         }
     458           1 :         gf_bs_write_data(ctx->bs, data, data_size);
     459             : 
     460           1 :         return dst_pck;
     461             : }
     462             : 
     463             : #ifdef WIN32
     464             : #include <windows.h>
     465             : #else
     466             : typedef struct tagBITMAPFILEHEADER
     467             : {
     468             :         u16     bfType;
     469             :         u32     bfSize;
     470             :         u16     bfReserved1;
     471             :         u16     bfReserved2;
     472             :         u32 bfOffBits;
     473             : } BITMAPFILEHEADER;
     474             : 
     475             : typedef struct tagBITMAPINFOHEADER {
     476             :         u32     biSize;
     477             :         s32     biWidth;
     478             :         s32     biHeight;
     479             :         u16     biPlanes;
     480             :         u16     biBitCount;
     481             :         u32     biCompression;
     482             :         u32     biSizeImage;
     483             :         s32     biXPelsPerMeter;
     484             :         s32     biYPelsPerMeter;
     485             :         u32     biClrUsed;
     486             :         u32     biClrImportant;
     487             : } BITMAPINFOHEADER;
     488             : 
     489             : #define BI_RGB        0L
     490             : 
     491             : #endif
     492             : 
     493           1 : static GF_FilterPacket *writegen_write_bmp(GF_GenDumpCtx *ctx, char *data, u32 data_size)
     494             : {
     495             :         u32 size;
     496             :         u8 *output;
     497             :         BITMAPFILEHEADER fh;
     498             :         BITMAPINFOHEADER fi;
     499             :         GF_FilterPacket *dst_pck;
     500             :         u32 i;
     501             : 
     502           1 :         size = ctx->w*ctx->h*3 + 54; //14 + 40 = size of BMP file header and BMP file info;
     503           1 :         dst_pck = gf_filter_pck_new_alloc(ctx->opid, size, &output);
     504           1 :         if (!dst_pck) return NULL;
     505             : 
     506             :         memset(&fh, 0, sizeof(fh));
     507           1 :         fh.bfType = 19778;
     508           1 :         fh.bfOffBits = 54;
     509             : 
     510           1 :         if (!ctx->bs) ctx->bs = gf_bs_new(output, size, GF_BITSTREAM_WRITE);
     511           0 :         else gf_bs_reassign_buffer(ctx->bs, output, size);
     512             : 
     513           1 :         gf_bs_write_data(ctx->bs, (const char *) &fh.bfType, 2);
     514           1 :         gf_bs_write_data(ctx->bs, (const char *) &fh.bfSize, 4);
     515           1 :         gf_bs_write_data(ctx->bs, (const char *) &fh.bfReserved1, 2);
     516           1 :         gf_bs_write_data(ctx->bs, (const char *) &fh.bfReserved2, 2);
     517           1 :         gf_bs_write_data(ctx->bs, (const char *) &fh.bfOffBits, 4);
     518             : 
     519             :         memset(&fi, 0, sizeof(char)*40);
     520           1 :         fi.biSize = 40;
     521           1 :         fi.biWidth = ctx->w;
     522           1 :         fi.biHeight = ctx->h;
     523           1 :         fi.biPlanes = 1;
     524           1 :         fi.biBitCount = 24;
     525             :         fi.biCompression = BI_RGB;
     526           1 :         fi.biSizeImage = ctx->w * ctx->h * 3;
     527             : 
     528           1 :         memcpy(output+14, &fi, sizeof(char)*40);
     529             :         //reverse lines
     530           1 :         output += sizeof(u8) * 54;
     531         130 :         for (i=ctx->h; i>0; i--) {
     532         128 :                 u8 *ptr = data + (i-1)*ctx->stride;
     533         128 :                 memcpy(output, ptr, sizeof(u8)*3*ctx->w);
     534         128 :                 output += 3*ctx->w;
     535             :         }
     536             :         return dst_pck;
     537             : }
     538             : 
     539           1 : static void writegen_write_wav_header(GF_GenDumpCtx *ctx)
     540             : {
     541             :         u32 size;
     542             :         u8 *output;
     543             :         GF_FilterPacket *dst_pck;
     544             :         const GF_PropertyValue *p;
     545             :         u32 nb_ch, sample_rate, afmt, bps;
     546           1 :         const char chunkID[] = {'R', 'I', 'F', 'F'};
     547           1 :         const char format[] = {'W', 'A', 'V', 'E'};
     548           1 :         const char subchunk1ID[] = {'f', 'm', 't', ' '};
     549           1 :         const char subchunk2ID[] = {'d', 'a', 't', 'a'};
     550             : 
     551           1 :         if (ctx->is_wav!=1) return;
     552           1 :         ctx->is_wav = 2;
     553             : 
     554           1 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_SAMPLE_RATE);
     555           1 :         if (!p) return;
     556           1 :         sample_rate = p->value.uint;
     557           1 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_NUM_CHANNELS);
     558           1 :         if (!p) return;
     559           1 :         nb_ch = p->value.uint;
     560           1 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_AUDIO_FORMAT);
     561           1 :         if (!p) return;
     562           1 :         afmt = p->value.uint;
     563             : 
     564           1 :         bps = gf_audio_fmt_bit_depth(afmt);
     565             : 
     566             :         size = 44;
     567           1 :         dst_pck = gf_filter_pck_new_alloc(ctx->opid, size, &output);
     568           1 :         if (!dst_pck) return;
     569             : 
     570           1 :         if (!ctx->bs) ctx->bs = gf_bs_new(output, size, GF_BITSTREAM_WRITE);
     571           0 :         else gf_bs_reassign_buffer(ctx->bs, output, size);
     572             : 
     573           1 :         gf_bs_write_data(ctx->bs, chunkID, 4);
     574           1 :         gf_bs_write_u32_le(ctx->bs, (u32) ctx->nb_bytes + 36);
     575           1 :         gf_bs_write_data(ctx->bs, format, 4);
     576             : 
     577           1 :         gf_bs_write_data(ctx->bs, subchunk1ID, 4);
     578           1 :         gf_bs_write_u32_le(ctx->bs, 16); //subchunk1 size
     579           1 :         gf_bs_write_u16_le(ctx->bs, 1); //audio format
     580           1 :         gf_bs_write_u16_le(ctx->bs, nb_ch);
     581           1 :         gf_bs_write_u32_le(ctx->bs, sample_rate);
     582           1 :         gf_bs_write_u32_le(ctx->bs, sample_rate * nb_ch * bps / 8); //byte rate
     583           1 :         gf_bs_write_u16_le(ctx->bs, nb_ch * bps / 8); // block align
     584           1 :         gf_bs_write_u16_le(ctx->bs, bps);
     585             : 
     586           1 :         gf_bs_write_data(ctx->bs, subchunk2ID, 4);
     587           1 :         gf_bs_write_u32_le(ctx->bs, (u32) ctx->nb_bytes);
     588             : 
     589           1 :         gf_filter_pck_set_framing(dst_pck, GF_FALSE, GF_FALSE);
     590           1 :         gf_filter_pck_set_byte_offset(dst_pck, 0);
     591           1 :         gf_filter_pck_set_seek_flag(dst_pck, GF_TRUE);
     592           1 :         gf_filter_pck_send(dst_pck);
     593             : }
     594             : 
     595             : 
     596          12 : static GF_XMLAttribute *ttml_get_attr(GF_XMLNode *node, char *name)
     597             : {
     598          12 :         u32 i=0;
     599             :         GF_XMLAttribute *att;
     600          26 :         while (node && (att = gf_list_enum(node->attributes, &i)) ) {
     601          14 :                 if (!strcmp(att->name, name)) return att;
     602             :         }
     603             :         return NULL;
     604             : }
     605          40 : static GF_XMLNode *ttml_locate_div(GF_XMLNode *body, const char *region_name, u32 div_idx)
     606             : {
     607          40 :         u32 i=0, loc_div_idx=0;
     608             :         GF_XMLNode *div;
     609         120 :         while ( (div = gf_list_enum(body->content, &i)) ) {
     610          80 :                 if (div->type) continue;
     611          40 :                 if (strcmp(div->name, "div")) continue;
     612             : 
     613          40 :                 if (!region_name) {
     614          40 :                         if (div_idx==loc_div_idx) return div;
     615           0 :                         loc_div_idx++;
     616             :                 } else {
     617           0 :                         GF_XMLAttribute *att = ttml_get_attr(div, "region");
     618           0 :                         if (att && att->value && !strcmp(att->value, region_name))
     619             :                                 return div;
     620             :                 }
     621             :         }
     622           0 :         if (region_name) {
     623           0 :                 return ttml_locate_div(body, NULL, div_idx);
     624             :         }
     625             :         return NULL;
     626             : }
     627             : 
     628          84 : static GF_XMLNode *ttml_get_body(GF_XMLNode *root)
     629             : {
     630          84 :         u32 i=0;
     631             :         GF_XMLNode *child;
     632         412 :         while (root && (child = gf_list_enum(root->content, &i)) ) {
     633         324 :                 if (child->type) continue;
     634         160 :                 if (!strcmp(child->name, "body")) return child;
     635             :         }
     636             :         return NULL;
     637             : }
     638             : 
     639         206 : static Bool ttml_same_attr(GF_XMLNode *n1, GF_XMLNode *n2)
     640             : {
     641         206 :         u32 i=0;
     642             :         GF_XMLAttribute *att1;
     643         206 :         while ( (att1 = gf_list_enum(n1->attributes, &i))) {
     644             :                 Bool found = GF_FALSE;
     645         206 :                 u32 j=0;
     646             :                 GF_XMLAttribute *att2;
     647        1023 :                 while ( (att2 = gf_list_enum(n2->attributes, &j))) {
     648         817 :                         if (!strcmp(att1->name, att2->name) && !strcmp(att1->value, att2->value)) {
     649             :                                 found = GF_TRUE;
     650             :                                 break;
     651             :                         }
     652             :                 }
     653         206 :                 if (!found) return GF_FALSE;
     654             :         }
     655             :         return GF_TRUE;
     656             : }
     657             : 
     658          69 : static GF_Err ttml_embed_data(GF_XMLNode *node, u8 *aux_data, u32 aux_data_size, u8 *subs_data, u32 subs_data_size)
     659             : {
     660          69 :         u32 i=0;
     661             :         GF_XMLNode *child;
     662             :         u32 subs_idx=0;
     663             :         GF_XMLAttribute *att;
     664             :         Bool is_source = GF_FALSE;
     665             :         Bool has_src_att = GF_FALSE;
     666          69 :         if (!node || node->type) return GF_BAD_PARAM;
     667             : 
     668          69 :         if (!strcmp(node->name, "source")) {
     669             :                 is_source = GF_TRUE;
     670             :         }
     671             : 
     672         187 :         while ((att = gf_list_enum(node->attributes, &i))) {
     673             :                 char *sep, *fext;
     674         126 :                 if (strcmp(att->name, "src")) continue;
     675             :                 has_src_att = GF_TRUE;
     676           9 :                 if (strncmp(att->value, "urn:", 4)) continue;
     677           8 :                 sep = strrchr(att->value, ':');
     678           8 :                 if (!sep) continue;
     679           8 :                 sep++;
     680           8 :                 fext = gf_file_ext_start(sep);
     681           8 :                 if (fext) fext[0] = 0;
     682           8 :                 subs_idx = atoi(sep);
     683           8 :                 if (fext) fext[0] = '.';
     684           8 :                 if (!subs_idx || ((subs_idx-1) * 14 > subs_data_size)) {
     685             :                         subs_idx = 0;
     686           0 :                         continue;
     687             :                 }
     688             :                 break;
     689             :         }
     690          69 :         if (subs_idx) {
     691             :                 GF_XMLNode *data;
     692             :                 u32 subs_offset = 0;
     693             :                 u32 subs_size = 0;
     694             :                 u32 idx = 1;
     695             :                 //fetch subsample info
     696          10 :                 for (i=0; i<subs_data_size; i+=14) {
     697          10 :                         u32 a_subs_size = subs_data[i+4];
     698          10 :                         a_subs_size <<= 8;
     699          10 :                         a_subs_size |= subs_data[i+5];
     700          10 :                         a_subs_size <<= 8;
     701          10 :                         a_subs_size |= subs_data[i+6];
     702          10 :                         a_subs_size <<= 8;
     703          10 :                         a_subs_size |= subs_data[i+7];
     704          10 :                         if (idx==subs_idx) {
     705             :                                 subs_size = a_subs_size;
     706             :                                 break;
     707             :                         }
     708           2 :                         subs_offset += a_subs_size;
     709           2 :                         idx++;
     710             :                 }
     711           8 :                 if (!subs_size || (subs_offset + subs_size > aux_data_size)) {
     712           0 :                         if (!subs_size) {
     713           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("No subsample with index %u in sample\n", subs_idx));
     714             :                         } else {
     715           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Corrupted subsample %u info, size %u offset %u but sample size %u\n", subs_idx, subs_size, subs_offset, aux_data_size));
     716             :                         }
     717             :                         return GF_NON_COMPLIANT_BITSTREAM;
     718             :                 }
     719             : 
     720             :                 //remove src attribute
     721           8 :                 gf_list_del_item(node->attributes, att);
     722           8 :                 if (att->name) gf_free(att->name);
     723           8 :                 if (att->value) gf_free(att->value);
     724           8 :                 gf_free(att);
     725             : 
     726             :                 //create a source node
     727           8 :                 if (!is_source) {
     728             :                         GF_XMLNode *s;
     729           4 :                         GF_SAFEALLOC(s, GF_XMLNode);
     730           4 :                         if (!s) return GF_OUT_OF_MEM;
     731           4 :                         s->attributes = gf_list_new();
     732           4 :                         s->content = gf_list_new();
     733           4 :                         s->name = gf_strdup("source");
     734           4 :                         gf_list_add(node->content, s);
     735           4 :                         if (!s->name || !s->content || !s->attributes) return GF_OUT_OF_MEM;
     736             :                         //move @type to source
     737           4 :                         att = ttml_get_attr(node, "type");
     738           4 :                         if (att) {
     739           4 :                                 gf_list_del_item(node->attributes, att);
     740           4 :                                 gf_list_add(s->attributes, att);
     741             :                         }
     742             :                         node = s;
     743             :                 }
     744             : 
     745             :                 //create a data node
     746           8 :                 GF_SAFEALLOC(data, GF_XMLNode);
     747           8 :                 if (!data) return GF_OUT_OF_MEM;
     748           8 :                 data->attributes = gf_list_new();
     749           8 :                 data->content = gf_list_new();
     750           8 :                 data->name = gf_strdup("data");
     751           8 :                 gf_list_add(node->content, data);
     752           8 :                 if (!data->name || !data->content || !data->attributes) return GF_OUT_OF_MEM;
     753             :                 //move @type to data
     754           8 :                 att = ttml_get_attr(node, "type");
     755           8 :                 if (att) {
     756           8 :                         gf_list_del_item(node->attributes, att);
     757           8 :                         gf_list_add(data->attributes, att);
     758             :                 }
     759             :                 //base64 encode in a child
     760           8 :                 GF_SAFEALLOC(node, GF_XMLNode)
     761           8 :                 if (!node) return GF_OUT_OF_MEM;
     762           8 :                 node->type = GF_XML_TEXT_TYPE;
     763           8 :                 node->name = gf_malloc(sizeof(u8) * subs_size * 2);
     764           8 :                 if (!node->name) {
     765           0 :                         gf_free(node);
     766           0 :                         return GF_OUT_OF_MEM;
     767             :                 }
     768           8 :                 subs_size = gf_base64_encode(aux_data + subs_offset, subs_size, (u8*) node->name, subs_size * 2);
     769           8 :                 node->name[subs_size] = 0;
     770           8 :                 return gf_list_add(data->content, node);
     771             :         }
     772             :         //src was present but not an embedded data, do not recurse
     773          61 :         if (has_src_att) return GF_OK;
     774             : 
     775          60 :         i=0;
     776         294 :         while ((child = gf_list_enum(node->content, &i))) {
     777         174 :                 if (child->type) continue;
     778          63 :                 ttml_embed_data(child, aux_data, aux_data_size, subs_data, subs_data_size);
     779             :         }
     780             :         return GF_OK;
     781             : }
     782             : 
     783          49 : static GF_Err writegen_push_ttml(GF_GenDumpCtx *ctx, char *data, u32 data_size, GF_FilterPacket *in_pck)
     784             : {
     785          49 :         const GF_PropertyValue *subs = gf_filter_pck_get_property(in_pck, GF_PROP_PCK_SUBS);
     786             :         char *ttml_text = NULL;
     787             :         GF_Err e = GF_OK;
     788             :         u32 ttml_text_size;
     789             :         GF_DOMParser *dom;
     790             :         u32 txt_size, nb_children;
     791             :         u32 i, k, div_idx;
     792             :         GF_XMLNode *root_pck, *p_global, *p_pck, *body_pck, *body_global;
     793             : 
     794          49 :         if (subs) {
     795           6 :                 if (subs->value.data.size < 14)
     796             :                         return GF_NON_COMPLIANT_BITSTREAM;
     797           6 :                 txt_size = subs->value.data.ptr[4];
     798           6 :                 txt_size <<= 8;
     799           6 :                 txt_size |= subs->value.data.ptr[5];
     800           6 :                 txt_size <<= 8;
     801           6 :                 txt_size |= subs->value.data.ptr[6];
     802           6 :                 txt_size <<= 8;
     803           6 :                 txt_size |= subs->value.data.ptr[7];
     804           6 :                 if (txt_size>data_size)
     805             :                         return GF_NON_COMPLIANT_BITSTREAM;
     806             :         } else {
     807             :                 txt_size = data_size;
     808             :         }
     809          49 :         ttml_text_size = txt_size + 2;
     810          49 :         ttml_text = gf_malloc(sizeof(char) * ttml_text_size);
     811          49 :         if (!ttml_text) return GF_OUT_OF_MEM;
     812             : 
     813          49 :         memcpy(ttml_text, data, txt_size);
     814          49 :         ttml_text[txt_size] = 0;
     815          49 :         ttml_text[txt_size+1] = 0;
     816             : 
     817          49 :         dom = gf_xml_dom_new();
     818          49 :         if (!dom) return GF_OUT_OF_MEM;
     819          49 :         e = gf_xml_dom_parse_string(dom, ttml_text);
     820          49 :         if (e) {
     821           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[XML] Invalid TTML doc: %s\n\tXML text was:\n%s", gf_xml_dom_get_error(dom), ttml_text));
     822             :                 goto exit;
     823             :         }
     824          49 :         root_pck = gf_xml_dom_get_root(dom);
     825             : 
     826             :         //subsamples, replace all data embedded as subsample with base64 encoding
     827          49 :         if (subs && root_pck) {
     828           6 :                 e = ttml_embed_data(root_pck, data+txt_size, data_size-txt_size, subs->value.data.ptr+14, subs->value.data.size-14);
     829           6 :                 if (e) goto exit;
     830             :         }
     831             : 
     832          49 :         if (!ctx->ttml_root) {
     833           7 :                 ctx->ttml_root = gf_xml_dom_detach_root(dom);
     834             :                 goto exit;
     835             :         }
     836             : 
     837             : 
     838          42 :         body_pck = ttml_get_body(root_pck);
     839          42 :         body_global = ttml_get_body(ctx->ttml_root);
     840             :         div_idx = 0;
     841          42 :         nb_children = body_pck ? gf_list_count(body_pck->content) : 0;
     842         120 :         for (k=0; k<nb_children; k++) {
     843             :                 GF_XMLAttribute *div_reg = NULL;
     844             :                 GF_XMLNode *div_global, *div_pck;
     845         120 :                 div_pck = gf_list_get(body_pck->content, k);
     846         120 :                 if (div_pck->type) continue;
     847          40 :                 if (strcmp(div_pck->name, "div")) continue;
     848             : 
     849          40 :                 if (ctx->merge_region)
     850           0 :                         div_reg = ttml_get_attr(div_pck, "region");
     851             : 
     852             :                 //merge input doc
     853           0 :                 div_global = ttml_locate_div(body_global, div_reg ? div_reg->value : NULL, div_idx);
     854             : 
     855          40 :                 if (!div_global) {
     856           0 :                         gf_list_rem(body_pck->content, k);
     857           0 :                         gf_list_insert(body_global->content, div_pck, div_idx+1);
     858             :                         div_idx++;
     859           0 :                         continue;
     860             :                 }
     861          40 :                 div_idx++;
     862             : 
     863          40 :                 i=0;
     864         160 :                 while ( (p_pck = gf_list_enum(div_pck->content, &i)) ) {
     865             :                         s32 idx;
     866             :                         GF_XMLNode *txt;
     867         120 :                         u32 j=0;
     868             :                         Bool found = GF_FALSE;
     869         200 :                         if (p_pck->type) continue;
     870          40 :                         if (strcmp(p_pck->name, "p")) continue;
     871         492 :                         while ( (p_global = gf_list_enum(div_global->content, &j)) ) {
     872         452 :                                 if (p_global->type) continue;
     873         206 :                                 if (strcmp(p_global->name, "p")) continue;
     874             : 
     875         206 :                                 if (ttml_same_attr(p_pck, p_global)) {
     876             :                                         found = GF_TRUE;
     877             :                                         break;
     878             :                                 }
     879             :                         }
     880          40 :                         if (found) continue;
     881             : 
     882             :                         //insert this p - if last entry in global div is text, insert before
     883          40 :                         txt = gf_list_last(div_global->content);
     884          40 :                         if (txt && txt->type) {
     885          40 :                                 idx = gf_list_count(div_global->content) - 1;
     886             :                         } else {
     887           0 :                                 idx = gf_list_count(div_global->content);
     888             :                         }
     889             : 
     890          40 :                         i--;
     891          40 :                         gf_list_rem(div_pck->content, i);
     892          40 :                         if (i) {
     893          40 :                                 txt = gf_list_get(div_pck->content, i-1);
     894          40 :                                 if (txt->type) {
     895          40 :                                         i--;
     896          40 :                                         gf_list_rem(div_pck->content, i);
     897          40 :                                         gf_list_insert(div_global->content, txt, idx);
     898          40 :                                         idx++;
     899             :                                 }
     900             :                         }
     901          40 :                         gf_list_insert(div_global->content, p_pck, idx);
     902             : 
     903             :                 }
     904             :         }
     905             : 
     906          49 : exit:
     907          49 :         if (ttml_text) gf_free(ttml_text);
     908          49 :         gf_xml_dom_del(dom);
     909             :         return e;
     910             : }
     911             : 
     912           7 : static GF_Err writegen_flush_ttml(GF_GenDumpCtx *ctx)
     913             : {
     914             :         char *data;
     915             :         u8 *output;
     916             :         u32 size;
     917             :         GF_FilterPacket *pck;
     918           7 :         if (!ctx->ttml_root) return GF_OK;
     919             : 
     920           7 :         if (ctx->merge_region) {
     921             :                 u32 i, count;
     922           0 :                 GF_XMLNode *body_global = ttml_get_body(ctx->ttml_root);
     923           0 :                 count = body_global ? gf_list_count(body_global->content) : 0;
     924           0 :                 for (i=0; i<count; i++) {
     925             :                         GF_XMLNode *child;
     926           0 :                         GF_XMLNode *div = gf_list_get(body_global->content, i);
     927           0 :                         if (div->type) continue;
     928           0 :                         if (strcmp(div->name, "div")) continue;
     929           0 :                         if (gf_list_count(div->content) > 1) continue;;
     930             : 
     931           0 :                         child = gf_list_get(div->content, 0);
     932           0 :                         if (child && !child->type) continue;;
     933             : 
     934           0 :                         gf_list_rem(body_global->content, i);
     935           0 :                         i--;
     936           0 :                         count--;
     937           0 :                         gf_xml_dom_node_del(div);
     938             :                 }
     939             :         }
     940             : 
     941           7 :         data = gf_xml_dom_serialize_root(ctx->ttml_root, GF_FALSE, GF_FALSE);
     942           7 :         if (!data) return GF_OK;
     943           7 :         size = (u32) strlen(data);
     944           7 :         pck = gf_filter_pck_new_alloc(ctx->opid, size, &output);
     945           7 :         if (!pck) return GF_OUT_OF_MEM;
     946             : 
     947           7 :         memcpy(output, data, size);
     948           7 :         gf_free(data);
     949           7 :         gf_filter_pck_set_framing(pck, GF_TRUE, GF_TRUE);
     950           7 :         gf_xml_dom_node_del(ctx->ttml_root);
     951           7 :         ctx->ttml_root = NULL;
     952           7 :         return gf_filter_pck_send(pck);
     953             : }
     954             : 
     955      121890 : GF_Err writegen_process(GF_Filter *filter)
     956             : {
     957      121890 :         GF_GenDumpCtx *ctx = gf_filter_get_udta(filter);
     958             :         GF_FilterPacket *pck, *dst_pck = NULL;
     959             :         char *data;
     960             :         u32 pck_size;
     961             :         Bool do_abort = GF_FALSE;
     962      121890 :         Bool split = ctx->split;
     963      121890 :         if (!ctx->ipid) return GF_EOS;
     964             : 
     965      121890 :         pck = gf_filter_pid_get_packet(ctx->ipid);
     966      121890 :         if (!pck || !ctx->codecid) {
     967       42588 :                 if (gf_filter_pid_is_eos(ctx->ipid)) {
     968         942 :                         if (ctx->is_wav) writegen_write_wav_header(ctx);
     969         941 :                         else if (ctx->ttml_agg) writegen_flush_ttml(ctx);
     970         942 :                         gf_filter_pid_set_eos(ctx->opid);
     971         942 :                         return GF_EOS;
     972             :                 }
     973             :                 return GF_OK;
     974             :         }
     975       79302 :         ctx->sample_num++;
     976             : 
     977       79302 :         if (ctx->sstart) {
     978         725 :                 if (ctx->sstart > ctx->sample_num) {
     979          84 :                         gf_filter_pid_drop_packet(ctx->ipid);
     980          84 :                         return GF_OK;
     981             :                 }
     982         641 :                 if ((ctx->sstart <= ctx->send) && (ctx->sample_num>ctx->send) ) {
     983             :                         do_abort = GF_TRUE;
     984             :                 }
     985       78577 :         } else if (ctx->dur.num && ctx->dur.den) {
     986       23940 :                 u64 dts = gf_filter_pck_get_dts(pck);
     987       23940 :                 if (dts==GF_FILTER_NO_TS)
     988          17 :                 dts = gf_filter_pck_get_cts(pck);
     989             : 
     990       23940 :                 if (!ctx->first_dts_plus_one) {
     991         403 :                         ctx->first_dts_plus_one = dts+1;
     992             :                 } else {
     993       23537 :                         if (ctx->dur.den * (dts + 1 - ctx->first_dts_plus_one) > ctx->dur.num * gf_filter_pck_get_timescale(pck)) {
     994             :                                 do_abort = GF_TRUE;
     995             :                         }
     996             :                 }
     997             :         }
     998             :         if (do_abort) {
     999             :                 GF_FilterEvent evt;
    1000         365 :                 gf_filter_pid_drop_packet(ctx->ipid);
    1001         365 :                 GF_FEVT_INIT(evt, GF_FEVT_STOP, ctx->ipid);
    1002         365 :                 gf_filter_pid_send_event(ctx->ipid, &evt);
    1003             :                 return GF_OK;
    1004             :         }
    1005             : 
    1006             :         //except in dash mode, force a new file if GF_PROP_PCK_FILENUM is set
    1007       78853 :         if (!ctx->dash_mode && (gf_filter_pck_get_property(pck, GF_PROP_PCK_FILENUM) != NULL)) {
    1008           0 :                 ctx->cfg_sent = GF_FALSE;
    1009           0 :                 ctx->first = GF_TRUE;
    1010             :         }
    1011             : 
    1012       78853 :         if (ctx->frame) {
    1013             :                 split = GF_TRUE;
    1014       78624 :         } else if (ctx->dcfg_size && gf_filter_pck_get_sap(pck) && !ctx->is_mj2k && (ctx->decinfo!=DECINFO_NO) && !ctx->cfg_sent) {
    1015           6 :                 dst_pck = gf_filter_pck_new_shared(ctx->opid, ctx->dcfg, ctx->dcfg_size, NULL);
    1016           6 :                 if (!dst_pck) return GF_OUT_OF_MEM;
    1017             : 
    1018           6 :                 gf_filter_pck_merge_properties(pck, dst_pck);
    1019           6 :                 gf_filter_pck_set_framing(dst_pck, ctx->first, GF_FALSE);
    1020           6 :                 ctx->first = GF_FALSE;
    1021           6 :                 gf_filter_pck_set_readonly(dst_pck);
    1022           6 :                 gf_filter_pck_send(dst_pck);
    1023           6 :                 if ((ctx->decinfo==DECINFO_FIRST) && !ctx->split) {
    1024           6 :                         ctx->dcfg_size = 0;
    1025           6 :                         ctx->dcfg = NULL;
    1026             :                 }
    1027           6 :                 ctx->cfg_sent = GF_TRUE;
    1028           6 :                 return GF_OK;
    1029             :         }
    1030       78847 :         ctx->cfg_sent = GF_FALSE;
    1031       78847 :         data = (char *) gf_filter_pck_get_data(pck, &pck_size);
    1032             : 
    1033       78847 :         if (ctx->is_mj2k) {
    1034           1 :                 dst_pck = writegen_write_j2k(ctx, data, pck_size, pck);
    1035       78846 :         } else if (ctx->is_bmp) {
    1036           1 :                 dst_pck = writegen_write_bmp(ctx, data, pck_size);
    1037       78845 :         } else if (ctx->is_wav && ctx->first) {
    1038             :                 u8 * output;
    1039           1 :                 dst_pck = gf_filter_pck_new_alloc(ctx->opid, 44, &output);
    1040           1 :                 if (!dst_pck) return GF_OUT_OF_MEM;
    1041             : 
    1042           1 :                 gf_filter_pck_merge_properties(pck, dst_pck);
    1043           1 :                 gf_filter_pck_set_byte_offset(dst_pck, GF_FILTER_NO_BO);
    1044           1 :                 gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_FALSE);
    1045           1 :                 gf_filter_pck_set_corrupted(dst_pck, GF_TRUE);
    1046           1 :                 ctx->first = GF_FALSE;
    1047           1 :                 gf_filter_pck_send(dst_pck);
    1048           1 :                 ctx->nb_bytes += 44;
    1049           1 :                 return GF_OK;
    1050       78844 :         } else if (ctx->ttml_agg) {
    1051          49 :                 GF_Err e = writegen_push_ttml(ctx, data, pck_size, pck);
    1052          49 :                 ctx->first = GF_FALSE;
    1053          49 :                 if (e) {
    1054           0 :                         gf_filter_pid_drop_packet(ctx->ipid);
    1055           0 :                         return e;
    1056             :                 }
    1057             :                 goto no_output;
    1058       78795 :         } else if (ctx->trunc_audio) {
    1059        2375 :                 u64 dts = gf_filter_pck_get_dts(pck);
    1060        2375 :                 if (dts==GF_FILTER_NO_TS)
    1061          14 :                         dts = gf_filter_pck_get_cts(pck);
    1062             : 
    1063        2375 :                 if (!ctx->first_dts_plus_one) {
    1064          14 :                         ctx->first_dts_plus_one = dts+1;
    1065             :                 } else {
    1066        2361 :                         u32 timescale = gf_filter_pck_get_timescale(pck);
    1067        2361 :                         u32 dur = gf_filter_pck_get_duration(pck);
    1068        2361 :                         if (ctx->dur.den * (dts + dur + 1 - ctx->first_dts_plus_one) > ctx->dur.num * timescale) {
    1069             :                                 u32 bpp;
    1070             :                                 u8 *odata;
    1071             :                                 const GF_PropertyValue *p;
    1072           7 :                                 dur = ctx->dur.num * timescale / ctx->dur.den;
    1073           7 :                                 dur -= (u32) (dts + 1 - ctx->first_dts_plus_one);
    1074             : 
    1075           7 :                                 bpp = gf_audio_fmt_bit_depth(ctx->target_afmt);
    1076           7 :                                 p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_NUM_CHANNELS);
    1077           7 :                                 if (p) bpp *= p->value.uint;
    1078           7 :                                 bpp/= 8;
    1079             : 
    1080           7 :                                 p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_SAMPLE_RATE);
    1081           7 :                                 if (p && (p->value.uint != timescale)) {
    1082           0 :                                         dur *= p->value.uint;
    1083           0 :                                         dur /= timescale;
    1084             :                                 }
    1085             :                                 assert(pck_size >= bpp * dur);
    1086           7 :                                 pck_size = bpp * dur;
    1087             : 
    1088           7 :                                 dst_pck = gf_filter_pck_new_alloc(ctx->opid, pck_size, &odata);
    1089           7 :                                 if (dst_pck)
    1090           7 :                                         memcpy(odata, data, pck_size);
    1091             :                         }
    1092             :                 }
    1093             : 
    1094           7 :                 if (!dst_pck) {
    1095        2368 :                         dst_pck = gf_filter_pck_new_ref(ctx->opid, 0, 0, pck);
    1096             :                 }
    1097             : 
    1098             :         } else {
    1099       76420 :                 dst_pck = gf_filter_pck_new_ref(ctx->opid, 0, 0, pck);
    1100             :         }
    1101       78797 :         if (!dst_pck) return GF_OUT_OF_MEM;
    1102             :         
    1103       78797 :         gf_filter_pck_merge_properties(pck, dst_pck);
    1104             :         //don't keep byte offset
    1105       78797 :         gf_filter_pck_set_byte_offset(dst_pck, GF_FILTER_NO_BO);
    1106             : 
    1107       78797 :         if (split) {
    1108         252 :                 gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_FILENUM, &PROP_UINT(ctx->sample_num) );
    1109         252 :                 gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
    1110             :         } else {
    1111       78545 :                 gf_filter_pck_set_framing(dst_pck, ctx->first, GF_FALSE);
    1112       78545 :                 ctx->first = GF_FALSE;
    1113             :         }
    1114             : 
    1115       78797 :         gf_filter_pck_set_seek_flag(dst_pck, 0);
    1116       78797 :         gf_filter_pck_send(dst_pck);
    1117       78797 :         ctx->nb_bytes += pck_size;
    1118             : 
    1119       78846 : no_output:
    1120       78846 :         if (ctx->exporter) {
    1121        1155 :                 u32 timescale = gf_filter_pck_get_timescale(pck);
    1122        1155 :                 u64 ts = gf_filter_pck_get_dts(pck);
    1123        1155 :                 if (ts==GF_FILTER_NO_TS)
    1124           0 :                         ts = gf_filter_pck_get_cts(pck);
    1125        1155 :                 if (ts!=GF_FILTER_NO_TS) {
    1126        1155 :                         ts += gf_filter_pck_get_duration(pck);
    1127        1155 :                         ts *= ctx->duration.den;
    1128        1155 :                         ts /= timescale;
    1129        1155 :                         gf_set_progress("Exporting", ts, ctx->duration.num);
    1130             :                 }
    1131             :         }
    1132             : 
    1133       78846 :         gf_filter_pid_drop_packet(ctx->ipid);
    1134             : 
    1135       78846 :         return GF_OK;
    1136             : }
    1137             : 
    1138             : /*
    1139             :         We list capabilities per codec type, associating the codec type to the file extension. This allows,
    1140             :         when matching to an output filter accepting a given file extension to match the codec type in write_gen caps, and
    1141             :         setup the right filter chain
    1142             : */
    1143             : static GF_FilterCapability GenDumpCaps[] =
    1144             : {
    1145             :         //raw color dump YUV and RGB - keep it as first for field extension assignment
    1146             :         //cf below
    1147             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1148             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1149             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1150             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "gpac"),
    1151             :         {0},
    1152             :         //raw audio dump - keep it as second for field extension assignment
    1153             :         //cf below
    1154             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1155             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1156             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1157             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "gpac" ),
    1158             :         {0},
    1159             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1160             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1161             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1162             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "bmp"),
    1163             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "image/bmp"),
    1164             :         {0},
    1165             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1166             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1167             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1168             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "wav"),
    1169             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/wav|audio/wave"),
    1170             :         {0},
    1171             : 
    1172             :         //we accept unframed AVC (annex B format)
    1173             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1174             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC),
    1175             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC_PS),
    1176             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_SVC),
    1177             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MVC),
    1178             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
    1179             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1180             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "264|h264|avc|svc|mvc"),
    1181             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/avc|video/h264|video/svc|video/mvc"),
    1182             :         {0},
    1183             : 
    1184             :         //we accept unframed HEVC (annex B format)
    1185             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1186             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC),
    1187             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_LHVC),
    1188             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
    1189             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1190             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "265|h265|hvc|hevc|shvc|lhvc"),
    1191             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/hevc|video/lhvc|video/shvc|video/mhvc"),
    1192             :         {0},
    1193             : 
    1194             :         //we accept unframed OBU (without size field)
    1195             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1196             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AV1),
    1197             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_VP8),
    1198             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_VP9),
    1199             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_VP10),
    1200             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
    1201             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1202             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "obu|av1|av1b|ivf"),
    1203             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/x-ivf|video/av1"),
    1204             :         {0},
    1205             : 
    1206             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1207             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG4_PART2),
    1208             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1209             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
    1210             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "cmp|m4ve|m4v"),
    1211             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/mp4v-es"),
    1212             :         {0},
    1213             : 
    1214             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1215             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_H263),
    1216             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_S263),
    1217             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1218             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "h263|263|s263"),
    1219             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/h263"),
    1220             :         {0},
    1221             : 
    1222             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1223             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG1),
    1224             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1225             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "m1v"),
    1226             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/mpgv-es"),
    1227             :         {0},
    1228             : 
    1229             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1230             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_422),
    1231             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_SNR),
    1232             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_HIGH),
    1233             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_MAIN),
    1234             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_SIMPLE),
    1235             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_SPATIAL),
    1236             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1237             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "m2v"),
    1238             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/mpgv-es"),
    1239             :         {0},
    1240             : 
    1241             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1242             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AP4H),
    1243             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AP4X),
    1244             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_APCH),
    1245             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_APCO),
    1246             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_APCS),
    1247             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_APCN),
    1248             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1249             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "prores"),
    1250             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/prores"),
    1251             :         {0},
    1252             : 
    1253             :         //we accept unframed AAC + ADTS
    1254             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1255             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
    1256             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
    1257             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
    1258             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
    1259             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
    1260             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED,GF_PROP_PID_UNFRAMED_LATM, GF_TRUE),
    1261             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1262             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "aac|adts"),
    1263             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/x-m4a|audio/aac|audio/aacp|audio/x-aac"),
    1264             :         {0},
    1265             : 
    1266             :         //we accept unframed AAC + LATM
    1267             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1268             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
    1269             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
    1270             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
    1271             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
    1272             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED_LATM, GF_TRUE),
    1273             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1274             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "latm"),
    1275             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/aac+latm"),
    1276             :         {0},
    1277             : 
    1278             :         //we accept unframed USAC + LATM
    1279             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1280             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_USAC),
    1281             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED_LATM, GF_TRUE),
    1282             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1283             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "usac|xheaac|latm"),
    1284             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/xheaac+latm"),
    1285             :         {0},
    1286             : 
    1287             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1288             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_PNG),
    1289             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1290             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "png"),
    1291             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "image/png"),
    1292             :         {0},
    1293             : 
    1294             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1295             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_JPEG),
    1296             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1297             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "jpg|jpeg"),
    1298             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "image/jpg"),
    1299             :         {0},
    1300             : 
    1301             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1302             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_J2K),
    1303             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1304             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "jp2|j2k"),
    1305             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "image/jp2"),
    1306             :         {0},
    1307             : 
    1308             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1309             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_V210),
    1310             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1311             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "v210"),
    1312             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/x-raw-v210"),
    1313             :         {0},
    1314             : 
    1315             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1316             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG_AUDIO),
    1317             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_PART3),
    1318             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1319             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "mp3|mp1|mp2"),
    1320             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/mp3|audio/x-mp3"),
    1321             :         {0},
    1322             : 
    1323             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1324             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AMR),
    1325             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AMR_WB),
    1326             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1327             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "amr"),
    1328             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/amr"),
    1329             :         {0},
    1330             : 
    1331             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1332             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_SMV),
    1333             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1334             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "smv"),
    1335             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/smv"),
    1336             :         {0},
    1337             : 
    1338             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1339             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_EVRC_PV),
    1340             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_EVRC),
    1341             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1342             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "evc"),
    1343             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/evrc"),
    1344             :         {0},
    1345             : 
    1346             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1347             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AC3),
    1348             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1349             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "ac3"),
    1350             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/x-ac3|audio/ac3"),
    1351             :         {0},
    1352             : 
    1353             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1354             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_EAC3),
    1355             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1356             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "eac3"),
    1357             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/x-eac3|audio/eac3"),
    1358             :         {0},
    1359             : 
    1360             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_SIMPLE_TEXT),
    1361             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_META_TEXT),
    1362             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_SUBS_TEXT),
    1363             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "txt"),
    1364             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "x-subtitle/srt|subtitle/srt|text/srt"),
    1365             :         {0},
    1366             : 
    1367             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_META_XML),
    1368             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_SUBS_XML),
    1369             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "xml|txml|ttml"),
    1370             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "subtitle/ttml|text/ttml|application/xml+ttml"),
    1371             :         {0},
    1372             : 
    1373             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1374             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_QCELP),
    1375             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "qcelp"),
    1376             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/qcelp"),
    1377             :         {0},
    1378             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1379             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_THEORA),
    1380             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "theo"),
    1381             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/x-theora"),
    1382             :         {0},
    1383             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1384             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_VORBIS),
    1385             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "vorb"),
    1386             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/x-vorbis"),
    1387             :         {0},
    1388             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1389             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_SPEEX),
    1390             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "spx"),
    1391             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/x-speex"),
    1392             :         {0},
    1393             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1394             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_FLAC),
    1395             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "flac"),
    1396             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/flac"),
    1397             :         {0},
    1398             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1399             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPHA),
    1400             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MHAS),
    1401             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
    1402             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "mhas"),
    1403             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/mpegh"),
    1404             :         {0},
    1405             : 
    1406             :         //we accept unframed VVC (annex B format)
    1407             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1408             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_VVC),
    1409             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
    1410             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1411             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "266|h266|vvc|lvvc"),
    1412             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "video/vvc|video/lvvc"),
    1413             :         {0},
    1414             : 
    1415             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1416             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_TRUEHD),
    1417             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1418             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "mlp"),
    1419             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "audio/truehd"),
    1420             :         {0},
    1421             : 
    1422             : 
    1423             :         //anything else: only for explicit dump (filter loaded on purpose), otherwise don't load for filter link resolution
    1424             :         CAP_UINT(GF_CAPS_OUTPUT_LOADED_FILTER, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1425             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_FILE_EXT, "*"),
    1426             :         CAP_STRING(GF_CAPS_OUTPUT, GF_PROP_PID_MIME, "*"),
    1427             :         //for the rest, we include everything, only specifies excluded ones from above and non-handled ones
    1428             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1429             : 
    1430             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_AVC),
    1431             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_AVC_PS),
    1432             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_SVC),
    1433             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_MVC),
    1434             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_HEVC),
    1435             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_LHVC),
    1436             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_MPEG4_PART2),
    1437             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_VVC),
    1438             : 
    1439             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_MPEG2_PART3),
    1440             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_MPEG_AUDIO),
    1441             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
    1442             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
    1443             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
    1444             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
    1445             : //      CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1446             : 
    1447             :         //WebVTT needs rewrite
    1448             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_WEBVTT),
    1449             :         //systems streams not dumpable to file
    1450             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_BIFS),
    1451             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_BIFS_V2),
    1452             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_OD_V1),
    1453             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_OD_V2),
    1454             :         //this one need QCP
    1455             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_QCELP),
    1456             : 
    1457             :         //other not supported (yet)
    1458             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_THEORA),
    1459             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_VORBIS)
    1460             : };
    1461             : 
    1462             : 
    1463             : #define OFFS(_n)        #_n, offsetof(GF_GenDumpCtx, _n)
    1464             : static GF_FilterArgs GenDumpArgs[] =
    1465             : {
    1466             :         { OFFS(exporter), "compatibility with old exporter, displays export results", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
    1467             :         { OFFS(pfmt), "pixel format for raw extract. If not set, derived from extension", GF_PROP_PIXFMT, "none", NULL, 0},
    1468             :         { OFFS(afmt), "audio format for raw extract. If not set, derived from extension", GF_PROP_PCMFMT, "none", NULL, 0},
    1469             :         { OFFS(decinfo), "decoder config insert mode\n"
    1470             :         "- no: never inserted\n"
    1471             :         "- first: inserted on first packet\n"
    1472             :         "- sap: inserted at each SAP\n"
    1473             :         "- auto: selects between no and first based on media type", GF_PROP_UINT, "auto", "no|first|sap|auto", GF_FS_ARG_HINT_ADVANCED},
    1474             :         { OFFS(split), "force one file per decoded frame", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
    1475             :         { OFFS(frame), "force single frame dump with no rewrite. In this mode, all codecids are supported", GF_PROP_BOOL, "false", NULL, 0},
    1476             :         { OFFS(sstart), "start number of frame to forward. If 0, all samples are forwarded", GF_PROP_UINT, "0", NULL, 0},
    1477             :         { OFFS(send), "end number of frame to forward. If less than start frame, all samples after start are forwarded", GF_PROP_UINT, "0", NULL, 0},
    1478             :         { OFFS(dur), "duration of media to forward after first sample. If 0, all samples are forwarded", GF_PROP_FRACTION, "0", NULL, 0},
    1479             :         { OFFS(merge_region), "merge TTML regions with same ID while reassembling TTML doc", GF_PROP_BOOL, "false", NULL, 0},
    1480             :         {0}
    1481             : };
    1482             : 
    1483             : static GF_Err writegen_initialize(GF_Filter *filter);
    1484             : 
    1485         951 : void writegen_finalize(GF_Filter *filter)
    1486             : {
    1487         951 :         GF_GenDumpCtx *ctx = gf_filter_get_udta(filter);
    1488         951 :         if (ctx->bs) gf_bs_del(ctx->bs);
    1489         951 :         if (ctx->ttml_root)
    1490           0 :                 gf_xml_dom_node_del(ctx->ttml_root);
    1491         951 : }
    1492             : 
    1493             : GF_FilterRegister GenDumpRegister = {
    1494             :         .name = "writegen",
    1495             :         GF_FS_SET_DESCRIPTION("Stream to file")
    1496             :         GF_FS_SET_HELP("Generic single stream to file converter, used when extracting/converting PIDs.\n"
    1497             :         "The writegen filter should usually not be explicetly loaded without a source ID specified, since the filter would likely match any pid connection.")
    1498             :         .private_size = sizeof(GF_GenDumpCtx),
    1499             :         .args = GenDumpArgs,
    1500             :         .initialize = writegen_initialize,
    1501             :         .finalize = writegen_finalize,
    1502             :         SETCAPS(GenDumpCaps),
    1503             :         .configure_pid = writegen_configure_pid,
    1504             :         .process = writegen_process
    1505             : };
    1506             : 
    1507             : static const GF_FilterCapability FrameDumpCaps[] =
    1508             : {
    1509             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
    1510             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_NONE),
    1511             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_UNKNOWN),
    1512             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1513             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE)
    1514             : };
    1515             : 
    1516         951 : static GF_Err writegen_initialize(GF_Filter *filter)
    1517             : {
    1518         951 :         GF_GenDumpCtx *ctx = gf_filter_get_udta(filter);
    1519         951 :         if (ctx->frame) {
    1520          14 :                 return gf_filter_override_caps(filter, (const GF_FilterCapability *) FrameDumpCaps, sizeof(FrameDumpCaps) / sizeof(GF_FilterCapability));
    1521             :         }
    1522             :         return GF_OK;
    1523             : }
    1524             : 
    1525             : 
    1526        2877 : const GF_FilterRegister *writegen_register(GF_FilterSession *session)
    1527             : {
    1528             : 
    1529             :         //assign runtime caps on first load
    1530        2877 :         if (!strcmp(GenDumpCaps[3].val.value.string, "gpac")) {
    1531        2740 :                 GenDumpCaps[3].val.value.string = (char *) gf_pixel_fmt_all_shortnames();
    1532        2740 :                 GenDumpCaps[8].val.value.string = (char *) gf_audio_fmt_all_shortnames();
    1533        2740 :                 GenDumpArgs[1].min_max_enum = gf_pixel_fmt_all_names();
    1534        2740 :                 GenDumpArgs[2].min_max_enum = gf_audio_fmt_all_names();
    1535             :         }
    1536             : 
    1537        2877 :         return &GenDumpRegister;
    1538             : }
    1539             : 

Generated by: LCOV version 1.13