LCOV - code coverage report
Current view: top level - filters - dmx_gsf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 506 632 80.1 %
Date: 2021-04-29 23:48:07 Functions: 19 20 95.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2018-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / GPAC stream format reader 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/network.h>
      30             : #include <gpac/internal/media_dev.h>
      31             : #include <gpac/crypt.h>
      32             : 
      33             : 
      34             : typedef struct
      35             : {
      36             :         u32 offset;
      37             :         u32 size;
      38             : } GSF_PacketFragment;
      39             : 
      40             : typedef struct
      41             : {
      42             :         GF_FilterPacket *pck;
      43             :         u8 *output;
      44             :         u32 full_block_size, nb_bytes, recv_bytes;
      45             :         Bool corrupted;
      46             :         u16 frame_sn;
      47             :         u8 pck_type;
      48             :         u8 crypted;
      49             : 
      50             :         u32 nb_frags, nb_alloc_frags, nb_recv_frags;
      51             :         Bool complete;
      52             :         GSF_PacketFragment *frags;
      53             : 
      54             : } GSF_Packet;
      55             : 
      56             : 
      57             : typedef struct
      58             : {
      59             :         GF_FilterPid *opid;
      60             :         GF_List *packets;
      61             : 
      62             :         u32 idx;
      63             :         u16 nb_pck;
      64             :         u8 config_version;
      65             : 
      66             :         u16 last_frame_sn;
      67             : } GSF_Stream;
      68             : 
      69             : typedef struct
      70             : {
      71             :         //opts
      72             :         const char *magic;
      73             :         GF_PropData key;
      74             :         u32 pad, mq;
      75             : 
      76             : 
      77             :         //only one output pid declared
      78             :         GF_FilterPid *ipid;
      79             : 
      80             :         GF_List *streams;
      81             : 
      82             :         bin128 crypt_IV;
      83             :         GF_Crypt *crypt;
      84             :         u16 crypt_blocks, skip_blocks;
      85             : 
      86             :         u32 nb_playing;
      87             :         Double start_range;
      88             :         Bool is_file;
      89             :         u64 file_pos, file_size;
      90             :         GF_Fraction64 duration;
      91             :         Bool initial_play_done;
      92             : 
      93             :         GF_BitStream *bs_r;
      94             :         GF_BitStream *bs_pck;
      95             : 
      96             :         //signaling stream
      97             :         GSF_Stream *signal_st;
      98             : 
      99             :         //where we store incoming packets
     100             :         char *buffer;
     101             :         u32 alloc_size, buf_size;
     102             : 
     103             :         u32 missing_bytes;
     104             :         Bool tuned;
     105             :         Bool tune_error;
     106             :         Bool use_seq_num;
     107             :         Bool wait_for_play;
     108             : 
     109             :         GF_List *pck_res;
     110             :         Bool buffer_too_small;
     111             : 
     112             :         Bool corrupted;
     113             :         Bool file_pids;
     114             : } GSF_DemuxCtx;
     115             : 
     116             : 
     117             : typedef enum
     118             : {
     119             :         GFS_PCKTYPE_HDR=0,
     120             :         GFS_PCKTYPE_PID_CONFIG,
     121             :         GFS_PCKTYPE_PID_INFO_UPDATE,
     122             :         GFS_PCKTYPE_PID_REMOVE,
     123             :         GFS_PCKTYPE_PID_EOS,
     124             :         GFS_PCKTYPE_PCK,
     125             : 
     126             :         GFS_PCKTYPE_UNDEF1,
     127             :         GFS_PCKTYPE_UNDEF2,
     128             :         GFS_PCKTYPE_UNDEF3,
     129             :         GFS_PCKTYPE_UNDEF4,
     130             :         GFS_PCKTYPE_UNDEF5,
     131             :         GFS_PCKTYPE_UNDEF6,
     132             :         GFS_PCKTYPE_UNDEF7,
     133             :         GFS_PCKTYPE_UNDEF8,
     134             :         GFS_PCKTYPE_UNDEF9,
     135             :         GFS_PCKTYPE_UNDEF10,
     136             : 
     137             :         /*NO MORE PACKET TYPE AVAILABLE*/
     138             : 
     139             : } GSF_PacketType;
     140             : 
     141             : 
     142             : 
     143         253 : GF_Err gsfdmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     144             : {
     145         253 :         GSF_DemuxCtx *ctx = gf_filter_get_udta(filter);
     146             : 
     147         253 :         if (is_remove) {
     148           0 :                 ctx->ipid = NULL;
     149             : 
     150           0 :                 while (gf_list_count(ctx->streams)) {
     151           0 :                         GSF_Stream *st = gf_list_pop_back(ctx->streams);
     152           0 :                         if (st->opid)
     153           0 :                                 gf_filter_pid_remove(st->opid);
     154           0 :                         gf_free(st);
     155             :                 }
     156             :                 return GF_OK;
     157             :         }
     158         253 :         if (! gf_filter_pid_check_caps(pid))
     159             :                 return GF_NOT_SUPPORTED;
     160             : 
     161         253 :         ctx->ipid = pid;
     162         253 :         return GF_OK;
     163             : }
     164             : 
     165         166 : static Bool gsfdmx_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
     166             : {
     167             :         GF_FilterEvent fevt;
     168         166 :         GSF_DemuxCtx *ctx = gf_filter_get_udta(filter);
     169             : 
     170         166 :         switch (evt->base.type) {
     171          15 :         case GF_FEVT_PLAY:
     172          15 :                 if (ctx->nb_playing && (ctx->start_range == evt->play.start_range)) {
     173             :                         return GF_TRUE;
     174             :                 }
     175          12 :                 ctx->nb_playing++;
     176          12 :                 ctx->wait_for_play = GF_FALSE;
     177             : 
     178          12 :                 if (! ctx->is_file) {
     179          12 :                         gf_filter_post_process_task(filter);
     180          12 :                         return GF_FALSE;
     181             :                 }
     182             : //              safdmx_check_dur(ctx);
     183             : 
     184           0 :                 ctx->start_range = evt->play.start_range;
     185           0 :                 ctx->file_pos = 0;
     186           0 :                 if (ctx->duration.num) {
     187           0 :                         ctx->file_pos = (u64) (ctx->file_size * ctx->start_range);
     188           0 :                         ctx->file_pos *= ctx->duration.den;
     189           0 :                         ctx->file_pos /= ctx->duration.num;
     190           0 :                         if (ctx->file_pos>ctx->file_size) return GF_TRUE;
     191             :                 }
     192             : 
     193           0 :                 if (!ctx->initial_play_done) {
     194           0 :                         ctx->initial_play_done = GF_TRUE;
     195             :                         //seek will not change the current source state, don't send a seek
     196           0 :                         if (!ctx->file_pos)
     197             :                                 return GF_TRUE;
     198             :                 }
     199             :                 //post a seek to 0 - we would need to build an index of AUs to find the next place to seek
     200           0 :                 GF_FEVT_INIT(fevt, GF_FEVT_SOURCE_SEEK, ctx->ipid);
     201             :                 fevt.seek.start_offset = 0;
     202           0 :                 gf_filter_pid_send_event(ctx->ipid, &fevt);
     203             : 
     204             :                 //cancel event
     205           0 :                 return GF_TRUE;
     206             : 
     207           0 :         case GF_FEVT_STOP:
     208           0 :                 ctx->nb_playing--;
     209           0 :                 if (ctx->file_pids) return GF_TRUE;
     210             :                 //cancel
     211           0 :                 return ctx->nb_playing ? GF_TRUE : GF_FALSE;
     212             : 
     213             :         case GF_FEVT_SET_SPEED:
     214             :                 //cancel event
     215             :                 return GF_TRUE;
     216             :         default:
     217             :                 break;
     218             :         }
     219             :         //by default don't cancel event - to rework once we have downloading in place
     220         151 :         return GF_FALSE;
     221             : }
     222             : 
     223         674 : static void gsfdmx_decrypt(GSF_DemuxCtx *ctx, char *data, u32 size)
     224             : {
     225             : #ifndef GPAC_DISABLE_CRYPTO
     226             :         u32 pos=0;
     227             :         u32 clear_tail = size%16;
     228             :         u32 bytes_crypted = size - clear_tail;
     229             : 
     230         674 :         if (!bytes_crypted) return;
     231             : 
     232         672 :         gf_crypt_set_IV(ctx->crypt, ctx->crypt_IV, 16);
     233         672 :         if (ctx->crypt_blocks && ctx->skip_blocks) {
     234         336 :                 u32 pattern_length = 16 * (ctx->crypt_blocks + ctx->skip_blocks);
     235         336 :                 u32 cryp_len = 16 * ctx->crypt_blocks;
     236        1078 :                 while (bytes_crypted) {
     237         732 :                         gf_crypt_decrypt(ctx->crypt, data+pos, bytes_crypted >= cryp_len ? cryp_len : bytes_crypted);
     238         732 :                         if (bytes_crypted >= pattern_length) {
     239         406 :                                 pos += pattern_length;
     240         406 :                                 bytes_crypted -= pattern_length;
     241             :                         } else {
     242             :                                 bytes_crypted = 0;
     243             :                         }
     244             :                 }
     245             :         } else {
     246         336 :                 gf_crypt_decrypt(ctx->crypt, data, bytes_crypted);
     247             :         }
     248             : #endif
     249             : }
     250             : 
     251       33255 : static GFINLINE u32 gsfdmx_read_vlen(GF_BitStream *bs)
     252             : {
     253       33255 :         if (!gf_bs_read_int(bs, 1))
     254       23972 :                 return gf_bs_read_int(bs, 7);
     255        9283 :         if (!gf_bs_read_int(bs, 1))
     256        6145 :                 return gf_bs_read_int(bs, 14);
     257        3138 :         if (!gf_bs_read_int(bs, 1))
     258        1177 :                 return gf_bs_read_int(bs, 21);
     259        1961 :         if (!gf_bs_read_int(bs, 1))
     260        1956 :                 return gf_bs_read_int(bs, 28);
     261             : 
     262           5 :         return (u32) gf_bs_read_long_int(bs, 36);
     263             : }
     264             : 
     265       18270 : static GF_Err gsfdmx_read_prop(GF_BitStream *bs, GF_PropertyValue *p)
     266             : {
     267             :         u32 len, len2, i;
     268             : 
     269       18270 :         switch (p->type) {
     270        7791 :         case GF_PROP_SINT:
     271             :         case GF_PROP_UINT:
     272        7791 :                 p->value.uint = gsfdmx_read_vlen(bs);
     273        7791 :                 break;
     274         913 :         case GF_PROP_LSINT:
     275             :         case GF_PROP_LUINT:
     276         913 :                 p->value.longuint = gf_bs_read_u64(bs);
     277         913 :                 break;
     278           0 :         case GF_PROP_4CC:
     279           0 :                 p->value.uint = gf_bs_read_u32(bs);
     280           0 :                 break;
     281        1104 :         case GF_PROP_BOOL:
     282        1104 :                 p->value.boolean = gf_bs_read_u8(bs) ? 1 : 0;
     283        1104 :                 break;
     284        1141 :         case GF_PROP_FRACTION:
     285        1141 :                 p->value.frac.num = gsfdmx_read_vlen(bs);
     286        1141 :                 p->value.frac.den = gsfdmx_read_vlen(bs);
     287        1141 :                 break;
     288        1074 :         case GF_PROP_FRACTION64:
     289        1074 :                 p->value.lfrac.num = gf_bs_read_u64(bs);
     290        1074 :                 p->value.lfrac.den = gf_bs_read_u64(bs);
     291        1074 :                 break;
     292           1 :         case GF_PROP_FLOAT:
     293           1 :                 p->value.fnumber = FLT2FIX( gf_bs_read_float(bs) );
     294           1 :                 break;
     295           1 :         case GF_PROP_DOUBLE:
     296           1 :                 p->value.number = gf_bs_read_double(bs);
     297           1 :                 break;
     298           1 :         case GF_PROP_VEC2I:
     299           1 :                 p->value.vec2i.x = gsfdmx_read_vlen(bs);
     300           1 :                 p->value.vec2i.y = gsfdmx_read_vlen(bs);
     301           1 :                 break;
     302           1 :         case GF_PROP_VEC2:
     303           1 :                 p->value.vec2.x = gf_bs_read_double(bs);
     304           1 :                 p->value.vec2.y = gf_bs_read_double(bs);
     305           1 :                 break;
     306           1 :         case GF_PROP_VEC3I:
     307           1 :                 p->value.vec3i.x = gsfdmx_read_vlen(bs);
     308           1 :                 p->value.vec3i.y = gsfdmx_read_vlen(bs);
     309           1 :                 p->value.vec3i.z = gsfdmx_read_vlen(bs);
     310           1 :                 break;
     311           1 :         case GF_PROP_VEC4I:
     312           1 :                 p->value.vec4i.x = gsfdmx_read_vlen(bs);
     313           1 :                 p->value.vec4i.y = gsfdmx_read_vlen(bs);
     314           1 :                 p->value.vec4i.z = gsfdmx_read_vlen(bs);
     315           1 :                 p->value.vec4i.w = gsfdmx_read_vlen(bs);
     316           1 :                 break;
     317        5161 :         case GF_PROP_STRING:
     318             :         case GF_PROP_STRING_NO_COPY:
     319             :         case GF_PROP_NAME:
     320        5161 :                 p->type = GF_PROP_STRING_NO_COPY;
     321        5161 :                 len = gsfdmx_read_vlen(bs);
     322        5161 :                 p->value.string = gf_malloc(sizeof(char)*(len+1));
     323        5161 :                 gf_bs_read_data(bs, p->value.string, len);
     324        5161 :                 p->value.string[len]=0;
     325        5161 :                 break;
     326             : 
     327        1076 :         case GF_PROP_DATA:
     328             :         case GF_PROP_DATA_NO_COPY:
     329             :         case GF_PROP_CONST_DATA:
     330        1076 :                 p->type = GF_PROP_DATA_NO_COPY;
     331        1076 :                 p->value.data.size = gsfdmx_read_vlen(bs);
     332        1076 :                 p->value.data.ptr = gf_malloc(sizeof(char) * p->value.data.size);
     333        1076 :                 gf_bs_read_data(bs, p->value.data.ptr, p->value.data.size);
     334        1076 :                 break;
     335             : 
     336           1 :         case GF_PROP_STRING_LIST:
     337           1 :                 len2 = gsfdmx_read_vlen(bs);
     338           1 :                 p->value.string_list.nb_items = len2;
     339           1 :                 p->value.string_list.vals = gf_malloc(sizeof(char*) * len2);
     340           2 :                 for (i=0; i<len2; i++) {
     341           1 :                         len = gsfdmx_read_vlen(bs);
     342           1 :                         char *str = gf_malloc(sizeof(char)*(len+1));
     343           1 :                         gf_bs_read_data(bs, str, len);
     344           1 :                         str[len] = 0;
     345           1 :                         p->value.string_list.vals[i] = str;
     346             :                 }
     347             :                 break;
     348             : 
     349           1 :         case GF_PROP_UINT_LIST:
     350             :         case GF_PROP_SINT_LIST:
     351           1 :                 p->value.uint_list.nb_items = len = gsfdmx_read_vlen(bs);
     352           1 :                 p->value.uint_list.vals = gf_malloc(sizeof(u32)*len);
     353           2 :                 for (i=0; i<len; i++) {
     354           1 :                         p->value.uint_list.vals[i] = gsfdmx_read_vlen(bs);
     355             :                 }
     356             :                 break;
     357           0 :         case GF_PROP_4CC_LIST:
     358           0 :                 p->value.uint_list.nb_items = len = gsfdmx_read_vlen(bs);
     359           0 :                 p->value.uint_list.vals = gf_malloc(sizeof(u32)*len);
     360           0 :                 for (i=0; i<len; i++) {
     361           0 :                         p->value.uint_list.vals[i] = gf_bs_read_u32(bs);
     362             :                 }
     363             :                 break;
     364           0 :         case GF_PROP_VEC2I_LIST:
     365           0 :                 p->value.v2i_list.nb_items = len = gsfdmx_read_vlen(bs);
     366           0 :                 p->value.v2i_list.vals = gf_malloc(sizeof(GF_PropVec2i)*len);
     367           0 :                 for (i=0; i<len; i++) {
     368           0 :                         p->value.v2i_list.vals[i].x = gsfdmx_read_vlen(bs);
     369           0 :                         p->value.v2i_list.vals[i].y = gsfdmx_read_vlen(bs);
     370             :                 }
     371             :                 break;
     372           0 :         case GF_PROP_POINTER:
     373           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] pointer property found in serialized stream, illegal\n"));
     374             :                 return GF_NON_COMPLIANT_BITSTREAM;
     375           2 :         default:
     376           2 :                 if (gf_props_type_is_enum(p->type)) {
     377           2 :                         p->value.uint = gsfdmx_read_vlen(bs);
     378           2 :                         break;
     379             :                 }
     380           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] Cannot read property of unknown type\n"));
     381             :                 return GF_NON_COMPLIANT_BITSTREAM;
     382             :         }
     383             :         return GF_OK;
     384             : }
     385             : 
     386        5401 : static GSF_Stream *gsfdmx_get_stream(GF_Filter *filter, GSF_DemuxCtx *ctx, u32 idx, u32 pkt_type)
     387             : {
     388             :         GSF_Stream *gst;
     389             :         u32 i, count;
     390             : 
     391        5401 :         count = gf_list_count(ctx->streams);
     392         694 :         for (i=0; i<count; i++) {
     393        6080 :                 gst = gf_list_get(ctx->streams, i);
     394        6080 :                 if (gst->idx == idx) return gst;
     395             :         }
     396             : 
     397          15 :         if ((pkt_type==GFS_PCKTYPE_PID_CONFIG) || (pkt_type==GFS_PCKTYPE_PID_INFO_UPDATE) ) {
     398          15 :                 GF_SAFEALLOC(gst, GSF_Stream);
     399          15 :                 if (!gst) return NULL;
     400          15 :                 gst->packets = gf_list_new();
     401          15 :                 gst->idx = idx;
     402          15 :                 gf_list_add(ctx->streams, gst);
     403          15 :                 gst->opid = gf_filter_pid_new(filter);
     404             :                 return gst;
     405             :         }
     406             : 
     407           0 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[GSFDemux] no stream found for idx %d\n", idx));
     408             :         return NULL;
     409             : }
     410        1081 : static GF_Err gsfdmx_parse_pid_info(GF_Filter *filter, GSF_DemuxCtx *ctx, GSF_Stream *gst, GSF_Packet *pck, Bool is_info_update)
     411             : {
     412             :         GF_Err e;
     413             :         u32 nb_4cc_props=0;
     414             :         u32 nb_str_props=0;
     415             :         u32 i;
     416             :         u8 cfg_version;
     417             :         GF_BitStream *bs=NULL;
     418             :         Bool pid_is_file = GF_FALSE;
     419             : 
     420        1081 :         if (pck->crypted) {
     421         326 :                 gsfdmx_decrypt(ctx, pck->output, pck->full_block_size);
     422             :         }
     423        1081 :         e = gf_bs_reassign_buffer(ctx->bs_pck, pck->output, pck->full_block_size);
     424        1081 :         if (e) return e;
     425        1081 :         bs = ctx->bs_pck;
     426             : 
     427        1081 :         cfg_version = gf_bs_read_u8(bs);
     428        1081 :         if ((gst->config_version == 1 + cfg_version) && !is_info_update)
     429             :                 return GF_OK;
     430        1081 :         gst->config_version = 1 + cfg_version;
     431             : 
     432        1081 :         nb_4cc_props = gsfdmx_read_vlen(bs);
     433        1081 :         nb_str_props = gsfdmx_read_vlen(bs);
     434             : 
     435       35543 :         for (i=0; i<nb_4cc_props; i++) {
     436             :                 GF_PropertyValue p;
     437       17231 :                 u32 p4cc = gf_bs_read_u32(bs);
     438             : 
     439             :                 memset(&p, 0, sizeof(GF_PropertyValue));
     440       17231 :                 p.type = gf_props_4cc_get_type(p4cc);
     441       17231 :                 if (p.type==GF_PROP_FORBIDEN) {
     442           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] Wrong GPAC property type for property 4CC %s\n", gf_4cc_to_str(p4cc) ));
     443           0 :                         return GF_NON_COMPLIANT_BITSTREAM;
     444             :                 }
     445             : 
     446       17231 :                 e = gsfdmx_read_prop(bs, &p);
     447       17231 :                 if (e) return e;
     448             : 
     449             : #ifndef GPAC_DISABLE_LOG
     450       17231 :                 if (gf_log_tool_level_on(GF_LOG_PARSER, GF_LOG_DEBUG)) {
     451             :                         char dump[GF_PROP_DUMP_ARG_SIZE];
     452           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[GSFDemux] Set pid %d %s %s to %s\n", gst->idx, gf_props_4cc_get_name(p4cc), is_info_update ? "info" : "property", gf_props_dump(p4cc, &p, dump, GF_PROP_DUMP_DATA_NONE) ) );
     453             :                 }
     454             : #endif
     455             : 
     456       17231 :                 if (is_info_update) gf_filter_pid_set_info(gst->opid, p4cc, &p);
     457         209 :                 else gf_filter_pid_set_property(gst->opid, p4cc, &p);
     458             : 
     459       17231 :                 if (p4cc==GF_PROP_PID_STREAM_TYPE) {
     460        1081 :                         if (p.value.uint==GF_STREAM_FILE)
     461             :                                 pid_is_file = GF_TRUE;
     462             :                 }
     463             :         }
     464             : 
     465             :         //PID is a file, we must start dispatch asap for demuxers to work
     466        1081 :         if (pid_is_file) {
     467           6 :                 const GF_PropertyValue *url = gf_filter_pid_get_property(gst->opid, GF_PROP_PID_URL);
     468           6 :                 if (url) {
     469           6 :                         const char *base_name = gf_file_basename(url->value.string);
     470           6 :                         if (base_name) gf_filter_pid_set_name(gst->opid, base_name);
     471             :                 }
     472           6 :                 gf_filter_pid_set_property(gst->opid, GF_PROP_PID_FILE_CACHED, NULL);
     473           6 :                 gf_filter_pid_set_property(gst->opid, GF_PROP_PID_FILEPATH, NULL);
     474           6 :                 gf_filter_pid_set_property(gst->opid, GF_PROP_PID_DOWN_SIZE, NULL);
     475           6 :                 gf_filter_pid_set_property(gst->opid, GF_PROP_PID_DOWN_BYTES, NULL);
     476             : 
     477           6 :                 ctx->wait_for_play = GF_FALSE;
     478           6 :                 if (!ctx->file_pids) {
     479             :                         GF_FilterEvent evt;
     480           2 :                         ctx->file_pids = GF_TRUE;
     481           2 :                         GF_FEVT_INIT(evt, GF_FEVT_PLAY, ctx->ipid);
     482           2 :                         gf_filter_pid_send_event(ctx->ipid, &evt);
     483             :                 }
     484             :         }
     485             : 
     486             : 
     487           9 :         for (i=0; i<nb_str_props; i++) {
     488             :                 GF_PropertyValue p;
     489             : 
     490           9 :                 u32 len = gsfdmx_read_vlen(bs);
     491           9 :                 char *pname = gf_malloc(sizeof(char)*(len+1));
     492           9 :                 gf_bs_read_data(bs, pname, len);
     493           9 :                 pname[len]=0;
     494             : 
     495             :                 memset(&p, 0, sizeof(GF_PropertyValue));
     496           9 :                 p.type = gf_bs_read_u8(bs);
     497             : 
     498           9 :                 e = gsfdmx_read_prop(bs, &p);
     499           9 :                 if (e) {
     500           0 :                         gf_free(pname);
     501           0 :                         return e;
     502             :                 }
     503           9 :                 if (is_info_update) gf_filter_pid_set_info_dyn(gst->opid, pname, &p);
     504           9 :                 else gf_filter_pid_set_property_dyn(gst->opid, pname, &p);
     505           9 :                 gf_free(pname);
     506             :         }
     507             :         return GF_OK;
     508             : }
     509             : 
     510          12 : static GF_Err gsfdmx_tune(GF_Filter *filter, GSF_DemuxCtx *ctx, char *pck_data, u32 pck_size, Bool is_crypted)
     511             : {
     512             :         u32 len;
     513             :         GF_BitStream *bs;
     514          12 :         GF_Err e = gf_bs_reassign_buffer(ctx->bs_pck, pck_data, pck_size);
     515          12 :         if (e) return e;
     516          12 :         bs = ctx->bs_pck;
     517             : 
     518          12 :         u32 sig = gf_bs_read_u32(bs);
     519          12 :         if (sig != GF_4CC('G','S','5','F') ) {
     520           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] Wrong GPAC serialized signature %s, expecting \"GS5F\"\n", gf_4cc_to_str(sig) ));
     521           0 :                 ctx->tune_error = GF_TRUE;
     522             :                 return GF_NOT_SUPPORTED;
     523             :         }
     524          12 :         sig = gf_bs_read_u8(bs);
     525          12 :         if (sig != GF_GSF_VERSION) {
     526           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] Wrong GPAC serialized version %d\n", sig ));
     527           0 :                 ctx->tune_error = GF_TRUE;
     528             :                 return GF_NOT_SUPPORTED;
     529             :         }
     530          12 :         if (is_crypted) {
     531             : #ifdef GPAC_DISABLE_CRYPTO
     532             :                 return GF_NOT_SUPPORTED;
     533             : #else
     534           2 :                 if (pck_size<25) {
     535           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] Wrong serialized header size %d, should be at least 25 bytes for encrypted streams\n", pck_size ));
     536           0 :                         ctx->tune_error = GF_TRUE;
     537             :                         return GF_NOT_SUPPORTED;
     538             :                 }
     539           2 :                 gf_bs_read_data(bs, ctx->crypt_IV, 16);
     540           2 :                 ctx->crypt_blocks = gf_bs_read_u16(bs);
     541           2 :                 ctx->skip_blocks = gf_bs_read_u16(bs);
     542             : 
     543           2 :                 if (!ctx->key.size) {
     544           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] stream is encrypted but no key provided\n" ));
     545           0 :                         ctx->tune_error = GF_TRUE;
     546             :                         return GF_BAD_PARAM;
     547             :                 }
     548           2 :                 ctx->crypt = gf_crypt_open(GF_AES_128, GF_CBC);
     549           2 :                 if (!ctx->crypt) {
     550           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] failed to create decryptor\n" ));
     551           0 :                         ctx->tune_error = GF_TRUE;
     552             :                         return GF_IO_ERR;
     553             :                 }
     554           2 :                 gf_crypt_init(ctx->crypt, ctx->key.ptr, ctx->crypt_IV);
     555             : 
     556           2 :                 gsfdmx_decrypt(ctx, pck_data+25, pck_size - 25);
     557             : #endif
     558             :         }
     559          12 :         ctx->use_seq_num = gf_bs_read_int(bs, 1);
     560          12 :         gf_bs_read_int(bs, 7);
     561             : 
     562             :         //header:magic
     563          12 :         len = gsfdmx_read_vlen(bs);
     564          12 :         if (len) {
     565             :                 Bool wrongm=GF_FALSE;
     566           1 :                 char *magic = gf_malloc(sizeof(char)*len);
     567           1 :                 gf_bs_read_data(bs, magic, len);
     568             : 
     569           1 :                 if (ctx->magic && !memcmp(ctx->magic, magic, len)) wrongm = GF_TRUE;
     570             :                 if (!wrongm) {
     571           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] wrong magic word in stream config\n" ));
     572           0 :                         ctx->tune_error = GF_TRUE;
     573           0 :                         gf_free(magic);
     574             :                         return GF_NOT_SUPPORTED;
     575             :                 }
     576           1 :                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[GSFDemux] tuning in stream, magic %s\n", magic));
     577           1 :                 gf_free(magic);
     578             :         } else {
     579          11 :                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[GSFDemux] tuning in stream\n"));
     580             :         }
     581             : 
     582          12 :         ctx->tuned = GF_TRUE;
     583             :         return GF_OK;
     584             : }
     585             : 
     586             : 
     587             : static GFINLINE void gsfdmx_pck_reset(GSF_Packet *pck)
     588             : {
     589        4776 :         u32 alloc_frags = pck->nb_alloc_frags;
     590        4776 :         GSF_PacketFragment *frags = pck->frags;
     591             :         memset(pck, 0, sizeof(GSF_Packet));
     592        4776 :         pck->nb_alloc_frags = alloc_frags;
     593        4776 :         pck->frags = frags;
     594             : }
     595             : 
     596        5401 : static GFINLINE GSF_Packet *gsfdmx_get_packet(GSF_DemuxCtx *ctx, GSF_Stream *gst, Bool pck_frag, s32 frame_sn, u8 pkt_type, u32 frame_size)
     597             : {
     598        5401 :         u32 i=0, count;
     599             :         GSF_Packet *gpck = NULL;
     600             : 
     601        5401 :         if ((frame_sn>=0) || pck_frag) {
     602        5401 :                 while (( gpck = gf_list_enum(gst->packets, &i))) {
     603         625 :                         if (gpck->frame_sn == frame_sn) {
     604             :                                 assert(gpck->pck_type == pkt_type);
     605             :                                 assert(gpck->full_block_size == frame_size);
     606             : 
     607             :                                 break;
     608             :                         }
     609             :                         gpck = NULL;
     610             :                 }
     611             :         }
     612        5401 :         if (!gpck) {
     613             :                 Bool inserted = GF_FALSE;
     614        4776 :                 gpck = gf_list_pop_back(ctx->pck_res);
     615        4776 :                 if (!gpck) {
     616          12 :                         GF_SAFEALLOC(gpck, GSF_Packet);
     617          12 :                         if (!gpck) return NULL;
     618          12 :                         gpck->nb_alloc_frags = 10;
     619          12 :                         gpck->frags = gf_malloc(sizeof(GSF_PacketFragment) * gpck->nb_alloc_frags);
     620             :                 }
     621        4776 :                 gpck->frame_sn = frame_sn;
     622        4776 :                 gpck->pck_type = pkt_type;
     623        4776 :                 gpck->full_block_size = frame_size;
     624        4776 :                 gpck->pck = gf_filter_pck_new_alloc(gst->opid, frame_size, &gpck->output);
     625        4776 :                 if (!gpck->pck) {
     626             :                         gsfdmx_pck_reset(gpck);
     627           0 :                         gf_list_add(ctx->pck_res, gpck);
     628           0 :                         return NULL;
     629             :                 }
     630        4776 :                 memset(gpck->output, (u8) ctx->pad, sizeof(char) * gpck->full_block_size);
     631             : 
     632        4776 :                 count = gf_list_count(gst->packets);
     633        4776 :                 for (i=0; i<count; i++) {
     634           0 :                         GSF_Packet *apck = gf_list_get(gst->packets, i);
     635             : 
     636           0 :                         if ( ( (apck->frame_sn > frame_sn) && (apck->frame_sn - frame_sn <= 32768) )
     637           0 :                                 || ( (apck->frame_sn < frame_sn ) && (frame_sn - apck->frame_sn > 32768) )
     638             :                         ) {
     639             :                                 inserted = GF_TRUE;
     640           0 :                                 gf_list_insert(gst->packets, gpck, i);
     641             :                         }
     642             :                 }
     643        4776 :                 if (!inserted) gf_list_add(gst->packets, gpck);
     644             :         }
     645             :         return gpck;
     646             : }
     647             : 
     648        5401 : static void gsfdmx_packet_append_frag(GSF_Packet *pck, u32 size, u32 offset)
     649             : {
     650             :         u32 i;
     651             :         Bool inserted = GF_FALSE;
     652        5401 :         pck->recv_bytes += size;
     653        5401 :         pck->nb_recv_frags++;
     654             : 
     655             :         assert(offset + size <= pck->full_block_size);
     656             : 
     657        5401 :         for (i=0; i<pck->nb_frags; i++) {
     658         625 :                 if ((pck->frags[i].offset <= offset) && (pck->frags[i].offset + pck->frags[i].size >= offset + size) ) {
     659             :                         return;
     660             :                 }
     661             : 
     662             :                 //insert fragment
     663         625 :                 if (pck->frags[i].offset > offset) {
     664           0 :                         if (pck->nb_frags==pck->nb_alloc_frags) {
     665           0 :                                 pck->nb_alloc_frags *= 2;
     666           0 :                                 pck->frags = gf_realloc(pck->frags, sizeof(GSF_PacketFragment)*pck->nb_alloc_frags);
     667             :                         }
     668           0 :                         memmove(&pck->frags[i+1], &pck->frags[i], sizeof(GSF_PacketFragment) * (pck->nb_frags - i)  );
     669           0 :                         pck->frags[i].offset = offset;
     670           0 :                         pck->frags[i].size = size;
     671           0 :                         pck->nb_bytes += size;
     672           0 :                         pck->nb_frags++;
     673             :                         inserted = GF_TRUE;
     674             :                         break;
     675             :                 }
     676             :                 //expand fragment
     677         625 :                 if (pck->frags[i].offset + pck->frags[i].size == offset) {
     678         625 :                         pck->frags[i].size += size;
     679         625 :                         pck->nb_bytes += size;
     680             :                         inserted = GF_TRUE;
     681             :                         break;
     682             :                 }
     683             :         }
     684             : 
     685             :         if (!inserted) {
     686        4776 :                 if (pck->nb_frags==pck->nb_alloc_frags) {
     687           0 :                         pck->nb_alloc_frags *= 2;
     688           0 :                         pck->frags = gf_realloc(pck->frags, sizeof(GSF_PacketFragment)*pck->nb_alloc_frags);
     689             :                 }
     690        4776 :                 pck->frags[pck->nb_frags].offset = offset;
     691        4776 :                 pck->frags[pck->nb_frags].size = size;
     692        4776 :                 pck->nb_frags++;
     693        4776 :                 pck->nb_bytes += size;
     694             :         }
     695        5401 :         if (pck->nb_bytes >= pck->full_block_size) {
     696        4776 :                 if (pck->nb_bytes>pck->full_block_size) pck->corrupted=GF_TRUE;
     697        4776 :                 pck->complete = GF_TRUE;
     698             :         }
     699             : }
     700             : 
     701        3695 : GF_Err gsfdmx_read_data_pck(GSF_DemuxCtx *ctx, GSF_Stream *gst, GSF_Packet *gpck, u32 pck_len, Bool full_pck, GF_BitStream *bs)
     702             : {
     703             :         u64 dts=GF_FILTER_NO_TS, cts=GF_FILTER_NO_TS, bo=GF_FILTER_NO_BO;
     704             :         u32 copy_size, consumed, dur, dep_flags=0, tsmodebits, durmodebits, spos;
     705             :         s16 roll=0;
     706             :         u8 carv=0;
     707             : 
     708             :         //not yet setup
     709        3695 :         if (!gst || !gpck) return GF_NOT_FOUND;
     710             : 
     711             : 
     712             : //      gsfdmx_flush_dst_pck(gst, GF_TRUE);
     713             : 
     714        3695 :         spos = (u32) gf_bs_get_position(bs);
     715             : 
     716             :         //flags first byte: 1(has_dts) 1(has_cts) 1(has_dur) 1(cts_diff_neg) 2(ts_mode) 2(ts_diff_mode)
     717             :         //flags second byte: 3(sap) 2(encrypted) 1(has_sample_deps) 1(has builtin props) 1(has_ext)
     718             :         //if (ext) {
     719             :         //      flags third byte: 1(has_byteoffset) 1(corrupted) 1(seek) 1(has_carousel) 2(ilaced) 2(cktype)
     720             :         //      flags fourth byte: 1(au start) 1(au end) 1(has props) reserved(5)
     721             :         //}
     722             :         //if has_dts, dts on tsmodebits
     723             :         //if has_cts, has_dts ? cts_diff on ts_diff_mode : cts on tsmodebits
     724             :         //if durmode>0, dur on ts_diff_mode
     725             :         //if sap==4, roll on signed 16 bits
     726             :         //if (has sample deps) sample_deps_flags on 8 bits
     727             :         //if has_carousel, carousel version on 8 bits
     728             :         //if has_byteoffset, byte offset on 64 bits
     729             :         //if (has builtin) vlen nb builtin_props then props[builtin_props]
     730             :         //if (has props) vlen nb_str_props then props[nb_str_props]
     731             : 
     732             :         //first flags byte
     733        3695 :         u8 has_dts = gf_bs_read_int(bs, 1);
     734        3695 :         u8 has_cts = gf_bs_read_int(bs, 1);
     735        3695 :         u8 has_dur = gf_bs_read_int(bs, 1);
     736        3695 :         u8 cts_diff_neg = gf_bs_read_int(bs, 1);
     737        3695 :         u8 tsmode = gf_bs_read_int(bs, 2);
     738        3695 :         u8 tsdiffmode = gf_bs_read_int(bs, 2);
     739             : 
     740        3695 :         u8 sap = gf_bs_read_int(bs, 3);
     741        3695 :         u8 crypt = gf_bs_read_int(bs, 2);
     742        3695 :         u8 has_dep = gf_bs_read_int(bs, 1);
     743        3695 :         u8 has_4cc_props = gf_bs_read_int(bs, 1);
     744        3695 :         u8 has_ext = gf_bs_read_int(bs, 1);
     745             : 
     746             :         //default field values without ext
     747             :         u8 has_bo = 0, corr = 0, seek = 0, has_carv = 0, interl = 0, cktype = 0, has_str_props = 0;
     748             :         u8 is_start = 1, is_end = 1;
     749        3695 :         if (has_ext) {
     750        1007 :                 has_bo = gf_bs_read_int(bs, 1);
     751        1007 :                 corr = gf_bs_read_int(bs, 1);
     752        1007 :                 seek = gf_bs_read_int(bs, 1);
     753        1007 :                 has_carv = gf_bs_read_int(bs, 1);
     754        1007 :                 interl = gf_bs_read_int(bs, 2);
     755        1007 :                 cktype = gf_bs_read_int(bs, 2);
     756             : 
     757        1007 :                 is_start = gf_bs_read_int(bs, 1);
     758        1007 :                 is_end = gf_bs_read_int(bs, 1);
     759        1007 :                 has_str_props = gf_bs_read_int(bs, 1);
     760        1007 :                 gf_bs_read_int(bs, 5); //reserved
     761             :         }
     762             : 
     763        3695 :         if (tsmode==3) tsmodebits = 64;
     764        3695 :         else if (tsmode==2) tsmodebits = 32;
     765        3287 :         else if (tsmode==1) tsmodebits = 24;
     766             :         else tsmodebits = 16;
     767             : 
     768        3695 :         if (tsdiffmode==3) durmodebits = 32;
     769        3695 :         else if (tsdiffmode==2) durmodebits = 24;
     770        2830 :         else if (tsdiffmode==1) durmodebits = 16;
     771             :         else durmodebits = 8;
     772             : 
     773        3695 :         if (has_dts) {
     774         590 :                 if (tsmode==3) dts = gf_bs_read_long_int(bs, tsmodebits);
     775         590 :                 else dts = gf_bs_read_int(bs, tsmodebits);
     776             :         }
     777        3695 :         if (has_cts) {
     778        3692 :                 if (has_dts) {
     779         590 :                         s32 cts_diff = gf_bs_read_int(bs, durmodebits);
     780         590 :                         if (cts_diff_neg) {
     781         375 :                                 cts = dts - cts_diff;
     782             :                         } else {
     783         215 :                                 cts = dts + cts_diff;
     784             :                         }
     785             :                 } else {
     786        3102 :                         if (tsmode==3) cts = gf_bs_read_long_int(bs, tsmodebits);
     787        3102 :                         else cts = gf_bs_read_int(bs, tsmodebits);
     788             :                 }
     789             :         }
     790             : 
     791        3695 :         if (has_dur) {
     792        3518 :                 dur = gf_bs_read_int(bs, durmodebits);
     793             :         }
     794             : 
     795        3695 :         if ((sap==GF_FILTER_SAP_4) || (sap==GF_FILTER_SAP_4_PROL)) {
     796           1 :                 roll = gf_bs_read_u16(bs);
     797             :         }
     798        3695 :         if (has_dep)
     799           2 :                 dep_flags = gf_bs_read_u8(bs);
     800             : 
     801        3695 :         if (has_carv) {
     802           2 :                 carv = gf_bs_read_u8(bs);
     803             :         }
     804        3695 :         if (has_bo) {
     805           1 :                 bo = gf_bs_read_u64(bs);
     806             :         }
     807             : 
     808        3695 :         if (has_4cc_props) {
     809           6 :                 u32 nb_4cc = gsfdmx_read_vlen(bs);
     810           6 :                 while (nb_4cc) {
     811             :                         GF_Err e;
     812             :                         GF_PropertyValue p;
     813             :                         memset(&p, 0, sizeof(GF_PropertyValue));
     814          10 :                         u32 p4cc = gf_bs_read_u32(bs);
     815          10 :                         p.type = gf_props_4cc_get_type(p4cc);
     816          10 :                         if (p.type==GF_PROP_FORBIDEN) {
     817           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] Wrong GPAC property type for property 4CC %s\n", gf_4cc_to_str(p4cc) ));
     818           0 :                                 gf_filter_pck_discard(gpck->pck);
     819           0 :                                 gpck->pck = NULL;
     820           0 :                                 return GF_NON_COMPLIANT_BITSTREAM;
     821             :                         }
     822          10 :                         nb_4cc--;
     823             : 
     824          10 :                         e = gsfdmx_read_prop(bs, &p);
     825          10 :                         if (e) {
     826           0 :                                 gf_filter_pck_discard(gpck->pck);
     827           0 :                                 gpck->pck = NULL;
     828           0 :                                 return e;
     829             :                         }
     830          10 :                         gf_filter_pck_set_property(gpck->pck, p4cc, &p);
     831             :                 }
     832             :         }
     833        3695 :         if (has_str_props) {
     834        1000 :                 u32 nb_props = gsfdmx_read_vlen(bs);
     835        1000 :                 while (nb_props) {
     836             :                         GF_Err e;
     837             :                         GF_PropertyValue p;
     838             :                         char *pname;
     839             :                         memset(&p, 0, sizeof(GF_PropertyValue));
     840        1020 :                         u32 len = gsfdmx_read_vlen(bs);
     841        1020 :                         pname = gf_malloc(sizeof(char)*(len+1) );
     842        1020 :                         gf_bs_read_data(bs, pname, len);
     843        1020 :                         pname[len] = 0;
     844        1020 :                         p.type = gf_bs_read_u8(bs);
     845        1020 :                         if (p.type==GF_PROP_FORBIDEN) {
     846           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] Wrong GPAC property type for property %s\n", pname ));
     847           0 :                                 gf_free(pname);
     848           0 :                                 gf_filter_pck_discard(gpck->pck);
     849           0 :                                 gpck->pck = NULL;
     850           0 :                                 return GF_NON_COMPLIANT_BITSTREAM;
     851             :                         }
     852        1020 :                         nb_props--;
     853             : 
     854        1020 :                         e = gsfdmx_read_prop(bs, &p);
     855        1020 :                         if (e) {
     856           0 :                                 gf_filter_pck_discard(gpck->pck);
     857           0 :                                 gf_free(pname);
     858           0 :                                 gpck->pck = NULL;
     859           0 :                                 return e;
     860             :                         }
     861        1020 :                         gf_filter_pck_set_property_dyn(gpck->pck, pname, &p);
     862        1020 :                         gf_free(pname);
     863        1020 :                         if ((p.type==GF_PROP_UINT_LIST) || (p.type==GF_PROP_4CC_LIST) || (p.type==GF_PROP_SINT_LIST) || (p.type==GF_PROP_VEC2I_LIST) ) {
     864           1 :                                 if (p.value.uint_list.vals)
     865           1 :                                         gf_free(p.value.uint_list.vals);
     866             :                         }
     867             :                 }
     868             :         }
     869             : 
     870        3695 :         consumed = (u32) gf_bs_get_position(bs) - spos;
     871        3695 :         pck_len -= consumed;
     872        3695 :         if (full_pck) {
     873             :                 assert(gpck->full_block_size > consumed);
     874        3600 :                 gpck->full_block_size -= consumed;
     875             :                 assert(gpck->full_block_size == pck_len);
     876        3600 :                 gf_filter_pck_truncate(gpck->pck, gpck->full_block_size);
     877             :         }
     878        3695 :         copy_size = gpck->full_block_size;
     879        3695 :         if (copy_size > pck_len)
     880             :                 copy_size = pck_len;
     881        3695 :         gf_bs_read_data(bs, gpck->output, copy_size);
     882        3695 :         gsfdmx_packet_append_frag(gpck, copy_size, 0);
     883             : 
     884        3695 :         gf_filter_pck_set_framing(gpck->pck, is_start, is_end);
     885        3695 :         if (has_dts) gf_filter_pck_set_dts(gpck->pck, dts);
     886        3695 :         if (has_cts) gf_filter_pck_set_cts(gpck->pck, cts);
     887        3695 :         if (has_dur) gf_filter_pck_set_duration(gpck->pck, dur);
     888        3695 :         if (has_bo) gf_filter_pck_set_byte_offset(gpck->pck, bo);
     889        3695 :         if (corr) gf_filter_pck_set_corrupted(gpck->pck, corr);
     890        3695 :         if (interl) gf_filter_pck_set_interlaced(gpck->pck, interl);
     891        3695 :         if (has_carv) gf_filter_pck_set_carousel_version(gpck->pck, carv);
     892        3695 :         if (has_dep) gf_filter_pck_set_dependency_flags(gpck->pck, dep_flags);
     893        3695 :         if (cktype) gf_filter_pck_set_clock_type(gpck->pck, cktype);
     894        3695 :         if (seek) gf_filter_pck_set_seek_flag(gpck->pck, seek);
     895        3695 :         if (crypt) gf_filter_pck_set_crypt_flags(gpck->pck, crypt);
     896        3695 :         if (sap) gf_filter_pck_set_sap(gpck->pck, sap);
     897        3695 :         if ((sap==GF_FILTER_SAP_4) || (sap==GF_FILTER_SAP_4_PROL))
     898           1 :                 gf_filter_pck_set_roll_info(gpck->pck, roll);
     899             :         return GF_OK;
     900             : }
     901             : 
     902             : #ifndef GPAC_DISABLE_LOG
     903             : static const char *gsfdmx_pck_name(u32 pck_type)
     904             : {
     905         337 :         switch (pck_type) {
     906             :         case GFS_PCKTYPE_HDR: return "TUNE";
     907           1 :         case GFS_PCKTYPE_PID_CONFIG: return "CONFIG";
     908         162 :         case GFS_PCKTYPE_PID_INFO_UPDATE: return "INFO";
     909           0 :         case GFS_PCKTYPE_PID_REMOVE: return "PIDREM";
     910           0 :         case GFS_PCKTYPE_PID_EOS: return "PIDEOS";
     911         173 :         case GFS_PCKTYPE_PCK: return "PCK";
     912           0 :         default: return "FORBIDDEN";
     913             :         }
     914             : }
     915             : #endif
     916             : 
     917             : 
     918          15 : static void gsfdmx_stream_del(GSF_DemuxCtx *ctx, GSF_Stream *gst, Bool is_flush)
     919             : {
     920          15 :         while (gf_list_count(gst->packets)) {
     921           0 :                 GSF_Packet *gpck = gf_list_pop_front(gst->packets);
     922             : 
     923           0 :                 if (gpck->pck) {
     924           0 :                         if (is_flush && (gpck->pck_type == GFS_PCKTYPE_PCK)) {
     925           0 :                                 gf_filter_pck_set_corrupted(gpck->pck, GF_TRUE);
     926           0 :                                 gf_filter_pck_send(gpck->pck);
     927             :                         } else {
     928           0 :                                 gf_filter_pck_discard(gpck->pck);
     929             :                         }
     930             :                 }
     931             :                 gsfdmx_pck_reset(gpck);
     932           0 :                 gf_list_add(ctx->pck_res, gpck);
     933             :         }
     934          15 :         if (is_flush && gst->opid)
     935           0 :                 gf_filter_pid_remove(gst->opid);
     936             : 
     937          15 :         gf_list_del(gst->packets);
     938          15 :         gf_list_del_item(ctx->streams, gst);
     939          15 :         gf_free(gst);
     940          15 : }
     941             : 
     942        5401 : static GF_Err gsfdmx_process_packets(GF_Filter *filter, GSF_DemuxCtx *ctx, GSF_Stream *gst)
     943             : {
     944             :         GSF_Packet *gpck;
     945             :         GF_Err e;
     946             : 
     947        5401 :         if (ctx->tune_error) {
     948             :                 return GF_SERVICE_ERROR;
     949             :         }
     950             :         while (1) {
     951       10177 :                 gpck = gf_list_get(gst->packets, 0);
     952             : 
     953       10177 :                 if (!gpck)
     954             :                         return GF_OK;
     955             : 
     956        5401 :                 if (!gpck->complete) {
     957         625 :                         u32 pck_count = gf_list_count(gst->packets);
     958         625 :                         if (ctx->mq && (pck_count > ctx->mq + 1)) {
     959           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[GSFDemux] packets queue too large (%d vs %d max), processing incomplete packet size %d receive %d\n", pck_count, ctx->mq, gpck->full_block_size, gpck->nb_bytes));
     960           0 :                                 gpck->corrupted = 1;
     961             :                         } else {
     962             :                                 return GF_OK;
     963             :                         }
     964             :                 }
     965             :                 assert(gpck->pck);
     966        4776 :                 if (ctx->use_seq_num) {
     967             :                         u32 frame_sn;
     968         336 :                         if (!gst->last_frame_sn) frame_sn = gpck->frame_sn;
     969             :                         else {
     970         335 :                                 frame_sn = gst->last_frame_sn;
     971             :                                 if (frame_sn>0xFFFF) frame_sn=0;
     972             :                         }
     973         336 :                         if (gpck->frame_sn != frame_sn) {
     974           0 :                                 u32 pck_count = gf_list_count(gst->packets);
     975           0 :                                 if (ctx->mq && (pck_count > 2*ctx->mq + 1)) {
     976           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[GSFDemux] packets queue too large (%d vs %d max), missed one full packet\n", pck_count, 2*ctx->mq));
     977             :                                 } else {
     978             :                                         return GF_OK;
     979             :                                 }
     980             :                         }
     981         336 :                         gst->last_frame_sn = gpck->frame_sn+1;
     982             :                 }
     983             : 
     984        4776 :                 switch (gpck->pck_type) {
     985        1081 :                 case GFS_PCKTYPE_PID_CONFIG:
     986             :                 case GFS_PCKTYPE_PID_INFO_UPDATE:
     987        1081 :                         if (!gpck->corrupted)
     988        1081 :                                 e = gsfdmx_parse_pid_info(filter, ctx, gst, gpck, (gpck->pck_type==GFS_PCKTYPE_PID_INFO_UPDATE) ? GF_TRUE : GF_FALSE);
     989             :                         else
     990             :                                 e = GF_CORRUPTED_DATA;
     991        1081 :                         if (gpck->pck) gf_filter_pck_discard(gpck->pck);
     992             :                         break;
     993           0 :                 case GFS_PCKTYPE_PID_REMOVE:
     994           0 :                         if (gpck->pck) gf_filter_pck_discard(gpck->pck);
     995           0 :                         gsfdmx_stream_del(ctx, gst, GF_TRUE);
     996             :                         return GF_OK;
     997             : 
     998           0 :                 case GFS_PCKTYPE_PID_EOS:
     999           0 :                         if (gpck->pck) gf_filter_pck_discard(gpck->pck);
    1000           0 :                         gf_filter_pid_set_eos(gst->opid);
    1001             :                         e = GF_EOS;
    1002             :                         break;
    1003        3695 :                 case GFS_PCKTYPE_PCK:
    1004        3695 :                         if (gpck->corrupted) gf_filter_pck_set_corrupted(gpck->pck, GF_TRUE);
    1005        3695 :                         e = gf_filter_pck_send(gpck->pck);
    1006             :                         break;
    1007             :                 default:
    1008             :                         e = GF_OK;
    1009             :                         break;
    1010             :                 }
    1011        4776 :                 gf_list_rem(gst->packets, 0);
    1012             :                 gsfdmx_pck_reset(gpck);
    1013        4776 :                 gf_list_add(ctx->pck_res, gpck);
    1014        4776 :                 if (e>GF_OK) e = GF_OK;
    1015        4765 :                 if (e) return e;
    1016             :         }
    1017             :         return GF_OK;
    1018             : }
    1019             : 
    1020         422 : static GF_Err gsfdmx_demux(GF_Filter *filter, GSF_DemuxCtx *ctx, char *data, u32 data_size)
    1021             : {
    1022             :         u32 last_pck_end=0;
    1023             : 
    1024             :         //always reset input buffer if not tuned - since in reliable (pipe/file/...) this is the first packet and it is less than 40 bytes at max whe should be fine
    1025         422 :         if (!ctx->tuned)
    1026          12 :                 ctx->buf_size = 0;
    1027             : 
    1028         422 :         if (ctx->alloc_size < ctx->buf_size + data_size) {
    1029          43 :                 ctx->buffer = (char*)gf_realloc(ctx->buffer, sizeof(char)*(ctx->buf_size + data_size) );
    1030          43 :                 ctx->alloc_size = ctx->buf_size + data_size;
    1031             :         }
    1032             : 
    1033         422 :         memcpy(ctx->buffer + ctx->buf_size, data, sizeof(char)*data_size);
    1034         422 :         ctx->buf_size += data_size;
    1035             : 
    1036         422 :         gf_bs_reassign_buffer(ctx->bs_r, ctx->buffer, ctx->buf_size);
    1037        6257 :         while (gf_bs_available(ctx->bs_r) > 4) { //1 byte header + 3 vlen field at least 1 bytes
    1038             :                 GF_Err e = GF_OK;
    1039             :                 u32 pck_len, block_size, block_offset;
    1040             : #ifndef GPAC_DISABLE_LOG
    1041        5596 :                 u32 hdr_pos = (u32) gf_bs_get_position(ctx->bs_r);
    1042             : #endif
    1043        5596 :                 /*Bool reserved =*/ gf_bs_read_int(ctx->bs_r, 1);
    1044        5596 :                 u32 frag_flags = gf_bs_read_int(ctx->bs_r, 2);
    1045        5596 :                 Bool is_crypted = gf_bs_read_int(ctx->bs_r, 1);
    1046        5596 :                 u32 pck_type = gf_bs_read_int(ctx->bs_r, 4);
    1047             : #ifndef GPAC_DISABLE_LOG
    1048             :                 u16 sn = 0;
    1049             : #endif
    1050             :                 u32 st_idx;
    1051             :                 Bool needs_agg = GF_FALSE;
    1052             :                 u16 frame_sn = 0;
    1053        5596 :                 Bool has_sn = (pck_type==GFS_PCKTYPE_HDR) ? GF_FALSE : ctx->use_seq_num;
    1054             : 
    1055        5596 :                 Bool full_pck = (frag_flags==0) ? GF_TRUE : GF_FALSE;
    1056        5596 :                 Bool pck_frag = (frag_flags>=2) ? GF_TRUE : GF_FALSE;
    1057             : 
    1058             :                 //reset buffer too small flag, and blindly parse the following vlen fields
    1059        5596 :                 ctx->buffer_too_small = GF_FALSE;
    1060             : 
    1061        5596 :                 st_idx = gsfdmx_read_vlen(ctx->bs_r);
    1062        5596 :                 if (has_sn) {
    1063         974 :                         frame_sn = gf_bs_read_u16(ctx->bs_r);
    1064             :                 }
    1065             : 
    1066             :                 block_size = block_offset = 0;
    1067        5596 :                 if (!full_pck) {
    1068         896 :                         block_size = gsfdmx_read_vlen(ctx->bs_r);
    1069         896 :                         if (pck_frag) block_offset = gsfdmx_read_vlen(ctx->bs_r);
    1070             :                 }
    1071             : 
    1072        5596 :                 pck_len = gsfdmx_read_vlen(ctx->bs_r);
    1073        5596 :                 if (pck_len > gf_bs_available(ctx->bs_r)) {
    1074             :                         break;
    1075             :                 }
    1076             :                 //buffer was not big enough to contain all the vlen fields, we need more data
    1077        5423 :                 if (ctx->buffer_too_small)
    1078             :                         break;
    1079             :                         
    1080        5423 :                 if (full_pck) {
    1081             :                         block_size = pck_len;
    1082             :                         block_offset = 0;
    1083             :                 }
    1084             : 
    1085        5423 :                 if (!ctx->corrupted && (pck_type==GFS_PCKTYPE_PCK) && !ctx->nb_playing && ctx->tuned && !ctx->file_pids && gf_list_count(ctx->streams) ) {
    1086          10 :                         ctx->wait_for_play = GF_TRUE;
    1087          10 :                         break;
    1088             :                 }
    1089             : 
    1090        5750 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[GSFDemux] found %s on stream %d type %s cryped %d sn %d size %d block_offset %d, hdr size %d at position %d\n",
    1091             :                                         (pck_len==block_size) ? "full packet" : (pck_frag ? "packet fragment" : "packet start"),
    1092             :                                         st_idx,
    1093             :                                         gsfdmx_pck_name(pck_type),
    1094             :                                         is_crypted, sn, pck_len, block_offset, gf_bs_get_position(ctx->bs_r)-hdr_pos, hdr_pos));
    1095             : 
    1096             :                 e = GF_OK;
    1097             : 
    1098        5413 :                 if ((pck_type != GFS_PCKTYPE_PCK) && (pck_frag || (pck_len < block_size)))
    1099             :                         needs_agg = GF_TRUE;
    1100             : 
    1101             :                 //tunein, we don't care about the seq num (for now, might chenge if we want key roll or other order-dependent features)
    1102        5413 :                 if (!st_idx) {
    1103          12 :                         if (ctx->tuned) {
    1104          12 :                         } else if (needs_agg) {
    1105           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] tune-in packet shall not be fragmented\n"));
    1106             :                                 e = GF_NON_COMPLIANT_BITSTREAM;
    1107             :                         } else {
    1108          12 :                                 u32 pos = (u32) gf_bs_get_position(ctx->bs_r);
    1109          12 :                                 e = gsfdmx_tune(filter, ctx, ctx->buffer + pos, pck_len, is_crypted);
    1110             :                         }
    1111             :                 }
    1112             :                 //stream signaling or packet
    1113             :                 else {
    1114        5401 :                         u32 cur_pos = (u32) gf_bs_get_position(ctx->bs_r);
    1115             : 
    1116        5401 :                         GSF_Stream *gst = gsfdmx_get_stream(filter, ctx, st_idx, pck_type);
    1117        5401 :                         if (!gst) {
    1118             :                                 e = GF_OK;
    1119           0 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[GSFDemux] cannot find stream idx %d\n", st_idx));
    1120             :                         } else {
    1121        5401 :                                 GSF_Packet *gpck = gsfdmx_get_packet(ctx, gst, pck_frag, frame_sn, pck_type, block_size);
    1122             : 
    1123             :                                 //aggregate data
    1124        5401 :                                 if (!gpck) {
    1125             :                                         e = GF_OUT_OF_MEM;
    1126           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] cannot allocate packet\n"));
    1127        5401 :                                 } else if (!gpck->pck) {
    1128             :                                         e = GF_CORRUPTED_DATA;
    1129           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] lost first packet in frame, cannot reaggregate fragment\n"));
    1130             :                                 } else {
    1131             :                                         Bool append = GF_TRUE;
    1132             : 
    1133             :                                         //packet: decrypt on per-packet base, and decode if not first fragment
    1134        5401 :                                         if (pck_type==GFS_PCKTYPE_PCK) {
    1135        4157 :                                                 if (is_crypted) {
    1136         346 :                                                         gsfdmx_decrypt(ctx, ctx->buffer + cur_pos, pck_len);
    1137             :                                                 }
    1138        4157 :                                                 if (!pck_frag) {
    1139        3695 :                                                         gf_bs_reassign_buffer(ctx->bs_pck, ctx->buffer + cur_pos, pck_len);
    1140        3695 :                                                         e = gsfdmx_read_data_pck(ctx, gst, gpck, pck_len, full_pck, ctx->bs_pck);
    1141             :                                                         append = GF_FALSE;
    1142             :                                                 }
    1143             :                                         } else {
    1144             :                                                 //otherwise decryption will happen upon decoding the complete packet
    1145        1244 :                                                 if (is_crypted) gpck->crypted = 1;
    1146             :                                         }
    1147             : 
    1148             :                                         if (append) {
    1149        1706 :                                                 if (block_offset + pck_len > gpck->full_block_size) {
    1150           0 :                                                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] packet fragment out of bounds of current frame (offset %d size %d max size %d)\n", block_offset,  pck_len, gpck->full_block_size));
    1151             :                                                         e = GF_NON_COMPLIANT_BITSTREAM;
    1152             :                                                 } else {
    1153             :                                                         //append fragment
    1154        1706 :                                                         memcpy(gpck->output + block_offset, ctx->buffer + cur_pos, pck_len);
    1155             : 
    1156        1706 :                                                         gsfdmx_packet_append_frag(gpck, pck_len, block_offset);
    1157             :                                                 }
    1158             :                                         }
    1159        5401 :                                         if (!e)
    1160        5401 :                                                 e = gsfdmx_process_packets(filter, ctx, gst);
    1161             :                                 }
    1162             :                         }
    1163             :                 }
    1164             : 
    1165        5413 :                 if (e) {
    1166           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] error decoding packet: %s\n", gf_error_to_string(e) ));
    1167           0 :                         if (ctx->tune_error) return e;
    1168           0 :                         ctx->corrupted = GF_TRUE;
    1169             :                 }
    1170        5413 :                 gf_bs_skip_bytes(ctx->bs_r, pck_len);
    1171        5413 :                 last_pck_end = (u32) gf_bs_get_position(ctx->bs_r);
    1172             :         }
    1173             : 
    1174         422 :         if (last_pck_end) {
    1175             :                 assert(ctx->buf_size>=last_pck_end);
    1176         414 :                 memmove(ctx->buffer, ctx->buffer+last_pck_end, sizeof(char) * (ctx->buf_size-last_pck_end));
    1177         414 :                 ctx->buf_size -= last_pck_end;
    1178             :         }
    1179             :         return GF_OK;
    1180             : }
    1181             : 
    1182         868 : GF_Err gsfdmx_process(GF_Filter *filter)
    1183             : {
    1184             :         GF_Err e;
    1185         868 :         GSF_DemuxCtx *ctx = gf_filter_get_udta(filter);
    1186             :         GF_FilterPacket *pck;
    1187             :         GSF_Stream *st;
    1188         868 :         u32 i=0, pkt_size;
    1189             :         const char *data;
    1190             :         u32 would_block = 0;
    1191             :         Bool is_eos = GF_FALSE;
    1192             : 
    1193         868 :         if (ctx->wait_for_play) return GF_OK;
    1194         851 :         if (ctx->tune_error) return GF_SERVICE_ERROR;
    1195             : 
    1196         851 :         pck = gf_filter_pid_get_packet(ctx->ipid);
    1197         851 :         if (!pck) {
    1198         429 :                 if (gf_filter_pid_is_eos(ctx->ipid)) is_eos = GF_TRUE;
    1199             :                 else {
    1200         417 :                         gf_filter_post_process_task(filter);
    1201         417 :                         return GF_OK;
    1202             :                 }
    1203             :         }
    1204             : 
    1205             :         //check if all the streams are in block state, if so return.
    1206             :         //we need to check for all output since one pid could still be buffering
    1207         926 :         while ((st = gf_list_enum(ctx->streams, &i))) {
    1208         492 :                 if (st->opid) {
    1209         492 :                         if (is_eos) {
    1210          15 :                                 gf_filter_pid_set_eos(st->opid);
    1211         477 :                         } else if (gf_filter_pid_would_block(st->opid)) {
    1212          42 :                                 would_block++;
    1213             :                         }
    1214             :                 }
    1215             :         }
    1216         434 :         if (is_eos)
    1217             :                 return GF_EOS;
    1218             : 
    1219         422 :         if (would_block && (would_block+1==i))
    1220             :                 return GF_OK;
    1221             : 
    1222         422 :         data = gf_filter_pck_get_data(pck, &pkt_size);
    1223         422 :         e = gsfdmx_demux(filter, ctx, (char *) data, pkt_size);
    1224         422 :         gf_filter_pid_drop_packet(ctx->ipid);
    1225         422 :         if (ctx->tune_error)
    1226           0 :                 gf_filter_pid_set_discard(ctx->ipid, GF_TRUE);
    1227             : 
    1228             :         return e;
    1229             : }
    1230             : 
    1231        3065 : static const char *gsfdmx_probe_data(const u8 *data, u32 data_size, GF_FilterProbeScore *score)
    1232             : {
    1233             :         u32 avail = data_size;
    1234        3065 :         if (data_size < 10) return NULL;
    1235             :         char *buf = (char *) data;
    1236       37109 :         while (buf) {
    1237       37109 :                 char *start_sig = memchr(buf, 'G', avail);
    1238       37109 :                 if (!start_sig) return NULL;
    1239             :                 //signature found and version is 2
    1240       34060 :                 if (!strncmp(start_sig, "GS5F", 4) && (start_sig[4] == GF_GSF_VERSION)) {
    1241          12 :                         *score = GF_FPROBE_SUPPORTED;
    1242          12 :                         return "application/x-gpac-sf";
    1243             :                 }
    1244       34048 :                 buf = start_sig+1;
    1245       34048 :                 avail = data_size - (u32) ( buf - (char *) data);
    1246             :         }
    1247             :         return NULL;
    1248             : }
    1249             : 
    1250           0 : static void gsfdmx_not_enough_bytes(void *par)
    1251             : {
    1252             :         GSF_DemuxCtx *ctx = (GSF_DemuxCtx *)par;
    1253           0 :         if (ctx)
    1254           0 :                 ctx->buffer_too_small = GF_TRUE;
    1255           0 : }
    1256             : 
    1257          12 : static GF_Err gsfdmx_initialize(GF_Filter *filter)
    1258             : {
    1259          12 :         GSF_DemuxCtx *ctx = gf_filter_get_udta(filter);
    1260          12 :         ctx->streams = gf_list_new();
    1261          12 :         if (!ctx->streams) return GF_OUT_OF_MEM;
    1262          12 :         ctx->bs_r = gf_bs_new((char *) ctx, 1, GF_BITSTREAM_READ);
    1263          12 :         gf_bs_set_eos_callback(ctx->bs_r, gsfdmx_not_enough_bytes, ctx);
    1264             : 
    1265             : #ifdef GPAC_ENABLE_COVERAGE
    1266          12 :         if (gf_sys_is_cov_mode())
    1267             :                 gsfdmx_not_enough_bytes(NULL);
    1268             : #endif
    1269             : 
    1270          12 :         ctx->bs_pck = gf_bs_new((char *) ctx, 1, GF_BITSTREAM_READ);
    1271          12 :         ctx->pck_res = gf_list_new();
    1272          12 :         return GF_OK;
    1273             : }
    1274             : 
    1275          12 : static void gsfdmx_finalize(GF_Filter *filter)
    1276             : {
    1277          12 :         GSF_DemuxCtx *ctx = gf_filter_get_udta(filter);
    1278          39 :         while (gf_list_count(ctx->streams)) {
    1279          15 :                 GSF_Stream *gst = gf_list_pop_back(ctx->streams);
    1280          15 :                 gsfdmx_stream_del(ctx, gst, GF_FALSE);
    1281             :         }
    1282          12 :         gf_list_del(ctx->streams);
    1283             : 
    1284          36 :         while (gf_list_count(ctx->pck_res)) {
    1285          12 :                 GSF_Packet *gsp = gf_list_pop_back(ctx->pck_res);
    1286          12 :                 if (gsp->frags) gf_free(gsp->frags);
    1287          12 :                 gf_free(gsp);
    1288             :         }
    1289          12 :         gf_list_del(ctx->pck_res);
    1290             : 
    1291             : #ifndef GPAC_DISABLE_CRYPTO
    1292          12 :         if (ctx->crypt) gf_crypt_close(ctx->crypt);
    1293             : #endif
    1294          12 :         if (ctx->buffer) gf_free(ctx->buffer);
    1295          12 :         if (ctx->bs_r) gf_bs_del(ctx->bs_r);
    1296          12 :         if (ctx->bs_pck) gf_bs_del(ctx->bs_pck);
    1297          12 : }
    1298             : 
    1299             : static const GF_FilterCapability GSFDemuxCaps[] =
    1300             : {
    1301             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1302             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "gsf"),
    1303             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "application/x-gpac-sf"),
    1304             :         //we deliver more than these two but this make the filter chain loading stop until we declare a pid
    1305             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1306             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1307             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1308             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_TEXT),
    1309             :         CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_NONE),
    1310             : };
    1311             : 
    1312             : 
    1313             : 
    1314             : #define OFFS(_n)        #_n, offsetof(GSF_DemuxCtx, _n)
    1315             : static const GF_FilterArgs GSFDemuxArgs[] =
    1316             : {
    1317             : #ifndef GPAC_DISABLE_CRYPTO
    1318             :         { OFFS(key), "key for decrypting packets", GF_PROP_DATA, NULL, NULL, GF_FS_ARG_HINT_ADVANCED},
    1319             : #endif
    1320             :         { OFFS(magic), "magic string to check in setup packet", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED},
    1321             :         { OFFS(mq), "set max packet queue length for loss detection. 0 will flush incomplete packet when a new one starts", GF_PROP_UINT, "4", NULL, GF_FS_ARG_HINT_ADVANCED},
    1322             :         { OFFS(pad), "byte value used to pad lost packets", GF_PROP_UINT, "0", "0-255", GF_FS_ARG_HINT_ADVANCED},
    1323             :         {0}
    1324             : };
    1325             : 
    1326             : 
    1327             : GF_FilterRegister GSFDemuxRegister = {
    1328             :         .name = "gsfdmx",
    1329             :         GF_FS_SET_DESCRIPTION("GSF Demuxer")
    1330             : #ifndef GPAC_DISABLE_DOC
    1331             :         .help = "This filter provides GSF (__GPAC Serialized Format__) demultiplexing.\n"
    1332             :                         "It unserializes the stream states (config/reconfig/info update/remove/eos) and packets of input PIDs.\n"
    1333             :                         "This allows either reading a session saved to file, or receiving the state/data of streams from another instance of GPAC using either pipes or sockets\n"
    1334             :                         "\n"
    1335             : #ifndef GPAC_DISABLE_CRYPTO
    1336             :                         "The stream format can be encrypted in AES 128 CBC mode, in which case the demux filters must be given a 128 bit key."
    1337             : #endif
    1338             :                 ,
    1339             : #endif
    1340             :         
    1341             :         .private_size = sizeof(GSF_DemuxCtx),
    1342             :         .max_extra_pids = (u32) -1,
    1343             :         .args = GSFDemuxArgs,
    1344             :         .flags = GF_FS_REG_DYNAMIC_PIDS,
    1345             :         SETCAPS(GSFDemuxCaps),
    1346             :         .initialize = gsfdmx_initialize,
    1347             :         .finalize = gsfdmx_finalize,
    1348             :         .configure_pid = gsfdmx_configure_pid,
    1349             :         .process = gsfdmx_process,
    1350             :         .process_event = gsfdmx_process_event,
    1351             :         .probe_data = gsfdmx_probe_data,
    1352             : };
    1353             : 
    1354             : 
    1355        2877 : const GF_FilterRegister *gsfdmx_register(GF_FilterSession *session)
    1356             : {
    1357        2877 :         return &GSFDemuxRegister;
    1358             : }

Generated by: LCOV version 1.13