LCOV - code coverage report
Current view: top level - filters - dmx_m2ts.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 416 536 77.6 %
Date: 2021-04-29 23:48:07 Functions: 17 18 94.4 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2005-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / M2TS demux 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             : 
      29             : 
      30             : #ifndef GPAC_DISABLE_MPEG2TS
      31             : 
      32             : #include <gpac/mpegts.h>
      33             : #include <gpac/thread.h>
      34             : 
      35             : typedef struct {
      36             :         char *fragment;
      37             :         u32 id;
      38             :         /*if only pid is requested*/
      39             :         u32 pid;
      40             : } GF_M2TSDmxCtx_Prog;
      41             : 
      42             : typedef struct {
      43             :         u32 timeline_id;
      44             :         Bool is_loc;
      45             :         u32 len;
      46             :         u8 *data;
      47             : } GF_TEMIInfo;
      48             : 
      49             : enum
      50             : {
      51             :         DMX_TUNE_DONE=0,
      52             :         DMX_TUNE_INIT,
      53             :         DMX_TUNE_WAIT_PROGS,
      54             :         DMX_TUNE_WAIT_SEEK,
      55             : 
      56             : };
      57             : 
      58             : typedef struct
      59             : {
      60             :         //opts
      61             :         const char *temi_url;
      62             :         Bool dsmcc, seeksrc, sigfrag;
      63             : 
      64             :         GF_Filter *filter;
      65             :         GF_FilterPid *ipid;
      66             : 
      67             :         GF_M2TS_Demuxer *ts;
      68             : 
      69             :         GF_FilterPid *eit_pid;
      70             : 
      71             :         Bool is_file;
      72             :         u64 file_size;
      73             :         Bool in_seek;
      74             :         Bool initial_play_done;
      75             :         u32 nb_playing;
      76             : 
      77             :         //duration estimation
      78             :         GF_Fraction64 duration;
      79             :         u64 first_pcr_found;
      80             :         u16 pcr_pid;
      81             :         u64 nb_pck_at_pcr;
      82             : 
      83             :         u32 map_time_on_prog_id;
      84             :         Double media_start_range;
      85             : 
      86             :         u32 mux_tune_state;
      87             :         u32 wait_for_progs;
      88             : } GF_M2TSDmxCtx;
      89             : 
      90             : 
      91       15004 : static void m2tsdmx_estimate_duration(GF_M2TSDmxCtx *ctx, GF_M2TS_ES *stream)
      92             : {
      93             :         Bool changed;
      94             :         Double pck_dur;
      95             :         const GF_PropertyValue *p;
      96             : 
      97       15004 :         if (ctx->duration.num) return;
      98        2404 :         if (!ctx->file_size) {
      99          31 :                 p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_DOWN_SIZE);
     100          31 :                 if (p) {
     101          31 :                         ctx->file_size = p->value.longuint;
     102             :                 } else {
     103           0 :                         ctx->duration.num = 1;
     104             :                         return;
     105             :                 }
     106             :         }
     107             : 
     108        2404 :         if (!ctx->first_pcr_found) {
     109          31 :                 ctx->first_pcr_found = stream->program->last_pcr_value;
     110          31 :                 ctx->pcr_pid = stream->pid;
     111          31 :                 ctx->nb_pck_at_pcr = ctx->ts->pck_number;
     112             :                 return;
     113             :         }
     114        2373 :         if (ctx->pcr_pid != stream->pid) return;
     115        1485 :         if (stream->program->last_pcr_value < ctx->first_pcr_found) {
     116           0 :                 ctx->first_pcr_found = stream->program->last_pcr_value;
     117           0 :                 ctx->pcr_pid = stream->pid;
     118           0 :                 ctx->nb_pck_at_pcr = ctx->ts->pck_number;
     119             :                 return;
     120             :         }
     121        1485 :         if (stream->program->last_pcr_value - ctx->first_pcr_found <= 2*27000000)
     122             :                 return;
     123             : 
     124             :         changed = GF_FALSE;
     125             : 
     126          31 :         pck_dur = (Double) (stream->program->last_pcr_value - ctx->first_pcr_found);
     127          31 :         pck_dur /= (ctx->ts->pck_number - ctx->nb_pck_at_pcr);
     128          31 :         pck_dur /= 27000;
     129             : 
     130          31 :         pck_dur *= ctx->file_size;
     131          31 :         pck_dur /= ctx->ts->prefix_present ? 192 : 188;
     132          31 :         if ((u32) ctx->duration.num != (u32) pck_dur) {
     133          31 :                 ctx->duration.num = (s32) pck_dur;
     134          31 :                 ctx->duration.den = 1000;
     135             :                 changed = GF_TRUE;
     136             :         }
     137          31 :         ctx->first_pcr_found = stream->program->last_pcr_value;
     138          31 :         ctx->pcr_pid = stream->pid;
     139          31 :         ctx->nb_pck_at_pcr = ctx->ts->pck_number;
     140          31 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TSDmx] Estimated duration based on instant bitrate: %g sec\n", pck_dur/1000));
     141             : 
     142          31 :         if (changed) {
     143          31 :                 u32 i, nb_streams = gf_filter_get_opid_count(ctx->filter);
     144           0 :                 for (i=0; i<nb_streams; i++) {
     145           0 :                         GF_FilterPid *opid = gf_filter_get_opid(ctx->filter, i);
     146           0 :                         gf_filter_pid_set_property(opid, GF_PROP_PID_DURATION, &PROP_FRAC64(ctx->duration) );
     147             :                 }
     148             :         }
     149             : }
     150             : 
     151        5266 : static void m2tsdmx_on_event_duration_probe(GF_M2TS_Demuxer *ts, u32 evt_type, void *param)
     152             : {
     153        5266 :         GF_Filter *filter = (GF_Filter *) ts->user;
     154        5266 :         GF_M2TSDmxCtx *ctx = gf_filter_get_udta(filter);
     155             : 
     156        5266 :         if (evt_type == GF_M2TS_EVT_PES_PCR) {
     157             :                 GF_M2TS_PES_PCK *pck = ((GF_M2TS_PES_PCK *) param);
     158             : 
     159        2424 :                 if (pck->stream) m2tsdmx_estimate_duration(ctx, (GF_M2TS_ES *) pck->stream);
     160             :         }
     161        5266 : }
     162             : 
     163         117 : static void m2tsdmx_declare_pid(GF_M2TSDmxCtx *ctx, GF_M2TS_PES *stream, GF_ESD *esd)
     164             : {
     165             :         u32 i, count, codecid=0, stype=0;
     166             :         GF_FilterPid *opid;
     167             :         Bool m4sys_stream = GF_FALSE;
     168             :         Bool m4sys_iod_stream = GF_FALSE;
     169             :         Bool has_scal_layer = GF_FALSE;
     170             :         Bool unframed = GF_FALSE;
     171             :         char szName[20];
     172             :         const char *stname;
     173         144 :         if (stream->user) return;
     174             : 
     175         117 :         if (stream->flags & GF_M2TS_GPAC_CODEC_ID) {
     176           0 :                 codecid = stream->stream_type;
     177           0 :                 stype = gf_codecid_type(codecid);
     178             :                 unframed = GF_TRUE;
     179           0 :                 if (!stype) {
     180           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[M2TSDmx] Unrecognized gpac codec %s - ignoring pid\n", gf_4cc_to_str(codecid) ));
     181             :                         return;
     182             :                 }
     183             :         } else {
     184             : 
     185         117 :                 switch (stream->stream_type) {
     186             :                 case GF_M2TS_VIDEO_MPEG1:
     187             :                         stype = GF_STREAM_VISUAL;
     188             :                         codecid = GF_CODECID_MPEG1;
     189             :                         unframed = GF_TRUE;
     190             :                         break;
     191          18 :                 case GF_M2TS_VIDEO_MPEG2:
     192             :                 case GF_M2TS_VIDEO_DCII:
     193             :                         stype = GF_STREAM_VISUAL;
     194             :                         codecid = GF_CODECID_MPEG2_MAIN;
     195             :                         unframed = GF_TRUE;
     196          18 :                         break;
     197           0 :                 case GF_M2TS_VIDEO_MPEG4:
     198             :                         stype = GF_STREAM_VISUAL;
     199             :                         codecid = GF_CODECID_MPEG4_PART2;
     200             :                         unframed = GF_TRUE;
     201           0 :                         break;
     202          21 :                 case GF_M2TS_VIDEO_H264:
     203             :                         stype = GF_STREAM_VISUAL;
     204             :                         codecid = GF_CODECID_AVC;
     205             :                         unframed = GF_TRUE;
     206          21 :                         if (stream->program->is_scalable)
     207             :                                 has_scal_layer = GF_TRUE;
     208             :                         break;
     209           0 :                 case GF_M2TS_VIDEO_SVC:
     210             :                         stype = GF_STREAM_VISUAL;
     211             :                         codecid = GF_CODECID_SVC;
     212             :                         has_scal_layer = GF_TRUE;
     213             :                         unframed = GF_TRUE;
     214           0 :                         break;
     215           0 :                 case GF_M2TS_VIDEO_HEVC:
     216             :                 case GF_M2TS_VIDEO_HEVC_TEMPORAL:
     217             :                 case GF_M2TS_VIDEO_HEVC_MCTS:
     218             :                         stype = GF_STREAM_VISUAL;
     219             :                         codecid = GF_CODECID_HEVC;
     220             :                         unframed = GF_TRUE;
     221           0 :                         if (stream->program->is_scalable)
     222             :                                 has_scal_layer = GF_TRUE;
     223             :                         break;
     224           1 :                 case GF_M2TS_VIDEO_SHVC:
     225             :                 case GF_M2TS_VIDEO_SHVC_TEMPORAL:
     226             :                 case GF_M2TS_VIDEO_MHVC:
     227             :                 case GF_M2TS_VIDEO_MHVC_TEMPORAL:
     228             :                         stype = GF_STREAM_VISUAL;
     229             :                         codecid = GF_CODECID_LHVC;
     230             :                         has_scal_layer = GF_TRUE;
     231           1 :                         break;
     232           0 :                 case GF_M2TS_VIDEO_VVC:
     233             :                 case GF_M2TS_VIDEO_VVC_TEMPORAL:
     234             :                         stype = GF_STREAM_VISUAL;
     235             :                         codecid = GF_CODECID_VVC;
     236             :                         unframed = GF_TRUE;
     237           0 :                         break;
     238           0 :                 case GF_M2TS_VIDEO_VC1:
     239             :                         stype = GF_STREAM_VISUAL;
     240             :                         codecid = GF_CODECID_SMPTE_VC1;
     241           0 :                         break;
     242          24 :                 case GF_M2TS_AUDIO_MPEG1:
     243             :                         stype = GF_STREAM_AUDIO;
     244             :                         codecid = GF_CODECID_MPEG_AUDIO;
     245             :                         unframed = GF_TRUE;
     246          24 :                         break;
     247           0 :                 case GF_M2TS_AUDIO_MPEG2:
     248             :                         stype = GF_STREAM_AUDIO;
     249             :                         codecid = GF_CODECID_MPEG2_PART3;
     250             :                         unframed = GF_TRUE;
     251           0 :                         break;
     252          18 :                 case GF_M2TS_AUDIO_LATM_AAC:
     253             :                 case GF_M2TS_AUDIO_AAC:
     254             :                 case GF_CODECID_AAC_MPEG2_MP:
     255             :                 case GF_CODECID_AAC_MPEG2_LCP:
     256             :                 case GF_CODECID_AAC_MPEG2_SSRP:
     257             :                         stype = GF_STREAM_AUDIO;
     258             :                         codecid = GF_CODECID_AAC_MPEG4;
     259             :                         unframed = GF_TRUE;
     260          18 :                         break;
     261           0 :                 case GF_M2TS_MHAS_MAIN:
     262             :                 case GF_M2TS_MHAS_AUX:
     263             :                         stype = GF_STREAM_AUDIO;
     264             :                         codecid = GF_CODECID_MHAS;
     265             :                         unframed = GF_TRUE;
     266           0 :                         break;
     267           2 :                 case GF_M2TS_AUDIO_AC3:
     268             :                         stype = GF_STREAM_AUDIO;
     269             :                         codecid = GF_CODECID_AC3;
     270             :                         unframed = GF_TRUE;
     271           2 :                         break;
     272           0 :                 case GF_M2TS_AUDIO_EC3:
     273             :                         stype = GF_STREAM_AUDIO;
     274             :                         codecid = GF_CODECID_EAC3;
     275           0 :                         break;
     276           2 :                 case GF_M2TS_SYSTEMS_MPEG4_SECTIONS:
     277           2 :                         ((GF_M2TS_ES*)stream)->flags |= GF_M2TS_ES_SEND_REPEATED_SECTIONS;
     278             :                         //fallthrough
     279           2 :                 case GF_M2TS_SYSTEMS_MPEG4_PES:
     280           2 :                         if (!esd) {
     281             :                                 m4sys_iod_stream = GF_TRUE;
     282           2 :                                 count = gf_list_count(stream->program->pmt_iod->ESDescriptors);
     283           3 :                                 for (i=0; i<count; i++) {
     284           3 :                                         esd = gf_list_get(stream->program->pmt_iod->ESDescriptors, i);
     285           3 :                                         if (esd->ESID == stream->mpeg4_es_id) break;
     286             :                                         esd = NULL;
     287             :                                 }
     288             :                         }
     289             :                         m4sys_stream = GF_TRUE;
     290             :                         //cannot setup stream yet
     291           2 :                         if (!esd) return;
     292             :                         break;
     293           4 :                 case GF_M2TS_METADATA_PES:
     294             :                 case GF_M2TS_METADATA_ID3_HLS:
     295             :                         stype = GF_STREAM_METADATA;
     296             :                         codecid = GF_CODECID_SIMPLE_TEXT;
     297           4 :                         break;
     298           0 :                 case 0xA1:
     299             :                         stype = GF_STREAM_AUDIO;
     300             :                         codecid = GF_CODECID_EAC3;
     301           0 :                         break;
     302          27 :                 default:
     303          27 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[M2TSDmx] Stream type 0x%02X not supported - ignoring pid\n", stream->stream_type));
     304             :                         return;
     305             :                 }
     306             :         }
     307             : 
     308          90 :         opid = gf_filter_pid_new(ctx->filter);
     309          90 :         stream->user = opid;
     310          90 :         stream->flags |= GF_M2TS_ES_ALREADY_DECLARED;
     311             : 
     312          90 :         stname = gf_stream_type_name(stype);
     313          90 :         sprintf(szName, "P%d%c%d", stream->program->number, stname[0], 1+gf_list_find(stream->program->streams, stream));
     314          90 :         gf_filter_pid_set_name(opid, szName);
     315             : 
     316          90 :         gf_filter_pid_set_property(opid, GF_PROP_PID_ID, &PROP_UINT(stream->pid) );
     317          90 :         if (stream->mpeg4_es_id)
     318           3 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_ESID, &PROP_UINT(stream->mpeg4_es_id) );
     319             : 
     320          90 :         if (m4sys_stream) {
     321           2 :                 if (stream->slcfg) gf_free(stream->slcfg);
     322             : 
     323           2 :                 stream->slcfg = esd->slConfig;
     324           2 :                 esd->slConfig = NULL;
     325             : 
     326           2 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(esd->decoderConfig ? esd->decoderConfig->streamType : GF_STREAM_SCENE) );
     327           2 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_CODECID, &PROP_UINT(esd->decoderConfig ? esd->decoderConfig->objectTypeIndication : GF_CODECID_BIFS) );
     328           2 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_CLOCK_ID, &PROP_UINT(esd->OCRESID ? esd->OCRESID : esd->ESID) );
     329           2 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_DEPENDENCY_ID, &PROP_UINT(esd->dependsOnESID) );
     330           2 :                 if (esd->decoderConfig && esd->decoderConfig->decoderSpecificInfo  && esd->decoderConfig->decoderSpecificInfo->dataLength)
     331           1 :                         gf_filter_pid_set_property(opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength) );
     332             : 
     333           2 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_IN_IOD, &PROP_BOOL(m4sys_iod_stream) );
     334             : 
     335           2 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(((GF_M2TS_ES*)stream)->slcfg->timestampResolution) );
     336           2 :                 if (esd->decoderConfig && (esd->decoderConfig->streamType==GF_STREAM_OD))
     337           1 :                         stream->flags |= GF_M2TS_ES_IS_MPEG4_OD;
     338             :         } else {
     339          88 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(stype) );
     340          88 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_CODECID, &PROP_UINT(codecid) );
     341          88 :                 if (unframed)
     342          83 :                         gf_filter_pid_set_property(opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL(GF_TRUE) );
     343             : 
     344          88 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(90000) );
     345          88 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_CLOCK_ID, &PROP_UINT(stream->program->pcr_pid) );
     346             :         }
     347          90 :         if (has_scal_layer)
     348           1 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_SCALABLE, &PROP_BOOL(GF_TRUE));
     349             : 
     350          90 :         gf_filter_pid_set_property(opid, GF_PROP_PID_SERVICE_ID, &PROP_UINT(stream->program->number) );
     351             : 
     352          90 :         if (ctx->duration.num>1) {
     353          89 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_DURATION, &PROP_FRAC64(ctx->duration) );
     354          89 :                 gf_filter_pid_set_property(opid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD ) );
     355             :         }
     356             :         /*indicate our coding dependencies if any*/
     357          90 :         if (!m4sys_stream) {
     358          88 :                 if (stream->depends_on_pid) {
     359           0 :                         gf_filter_pid_set_property(opid, GF_PROP_PID_DEPENDENCY_ID, &PROP_UINT(stream->depends_on_pid) );
     360           0 :                         if ((stream->stream_type == GF_M2TS_VIDEO_HEVC_TEMPORAL) || (stream->stream_type == GF_M2TS_VIDEO_HEVC_MCTS)) {
     361           0 :                                 gf_filter_pid_set_property(opid, GF_PROP_PID_SUBLAYER, &PROP_BOOL(GF_TRUE) );
     362             :                         }
     363             :                 }
     364             :         }
     365          90 :         gf_m2ts_set_pes_framing((GF_M2TS_PES *)stream, GF_M2TS_PES_FRAMING_DEFAULT);
     366             : }
     367             : 
     368          50 : static void m2tsdmx_setup_program(GF_M2TSDmxCtx *ctx, GF_M2TS_Program *prog)
     369             : {
     370             :         u32 i, count;
     371             : 
     372          50 :         count = gf_list_count(prog->streams);
     373             : #ifdef FILTER_FIXME
     374             :         if (ctx->ts->tuner) {
     375             :                 Bool found = 0;
     376             :                 for (i=0; i<count; i++) {
     377             :                         GF_M2TS_PES *pes = gf_list_get(prog->streams, i);
     378             :                         if (pes->pid==ctx->ts->tuner->vpid) found = 1;
     379             :                         else if (pes->pid==ctx->ts->tuner->apid) found = 1;
     380             :                 }
     381             :                 if (!found) return;
     382             :         }
     383             : #endif
     384             : 
     385         217 :         for (i=0; i<count; i++) {
     386         167 :                 GF_M2TS_PES *es = gf_list_get(prog->streams, i);
     387         167 :                 if (es->pid==prog->pmt_pid) continue;
     388         117 :                 if (! (es->flags & GF_M2TS_ES_IS_PES)) continue;
     389             : 
     390         112 :                 if (es->stream_type == GF_M2TS_VIDEO_HEVC_TEMPORAL ) continue;
     391         112 :                 if (es->depends_on_pid ) {
     392           0 :                         prog->is_scalable = GF_TRUE;
     393           0 :                         break;
     394             :                 }
     395             :         }
     396             : 
     397         167 :         for (i=0; i<count; i++) {
     398             :                 u32 ncount;
     399         167 :                 GF_M2TS_ES *es = gf_list_get(prog->streams, i);
     400         167 :                 if (es->pid==prog->pmt_pid) continue;
     401             : 
     402         117 :                 if (! (es->flags & GF_M2TS_ES_ALREADY_DECLARED)) {
     403         117 :                         m2tsdmx_declare_pid(ctx, (GF_M2TS_PES *)es, NULL);
     404             :                 }
     405         117 :                 ncount = gf_list_count(prog->streams);
     406         234 :                 while (ncount<count) {
     407           0 :                         i--;
     408           0 :                         count--;
     409             :                 }
     410             :         }
     411          50 : }
     412             : 
     413       20686 : static void m2tdmx_merge_temi(GF_M2TS_ES *stream, GF_FilterPacket *pck)
     414             : {
     415       20686 :         if (stream->props) {
     416             :                 char szID[100];
     417        2782 :                 while (gf_list_count(stream->props)) {
     418        1430 :                         GF_TEMIInfo *t = gf_list_pop_front(stream->props);
     419        1430 :                         snprintf(szID, 100, "%s:%d", t->is_loc ? "temi_l" : "temi_t", t->timeline_id);
     420             : 
     421        1430 :                         gf_filter_pck_set_property_dyn(pck, szID, &PROP_DATA_NO_COPY(t->data, t->len));
     422        1430 :                         gf_free(t);
     423             :                 }
     424        1352 :                 gf_list_del(stream->props);
     425        1352 :                 stream->props = NULL;
     426             :         }
     427       20686 : }
     428             : 
     429       20684 : static void m2tsdmx_send_packet(GF_M2TSDmxCtx *ctx, GF_M2TS_PES_PCK *pck)
     430             : {
     431             :         GF_FilterPid *opid;
     432             :         GF_FilterPacket *dst_pck;
     433             :         u8 * data;
     434             : 
     435             :         /*pcr not initialized, don't send any data*/
     436             : //      if (! pck->stream->program->first_dts) return;
     437       20684 :         if (!pck->stream->user) return;
     438             :         opid = pck->stream->user;
     439             : 
     440       20684 :         dst_pck = gf_filter_pck_new_alloc(opid, pck->data_len, &data);
     441       20684 :         if (!dst_pck) return;
     442             : 
     443       20684 :         memcpy(data, pck->data, pck->data_len);
     444             :         //we don't have end of frame signaling
     445       20684 :         gf_filter_pck_set_framing(dst_pck, (pck->flags & GF_M2TS_PES_PCK_AU_START) ? GF_TRUE : GF_FALSE, GF_FALSE);
     446             : 
     447       20684 :         if (pck->flags & GF_M2TS_PES_PCK_AU_START) {
     448       20682 :                 gf_filter_pck_set_cts(dst_pck, pck->PTS);
     449       20682 :                 if (pck->DTS != pck->PTS) {
     450        3349 :                         gf_filter_pck_set_dts(dst_pck, pck->DTS);
     451             :                 }
     452       20682 :                 gf_filter_pck_set_sap(dst_pck, (pck->flags & GF_M2TS_PES_PCK_RAP) ? GF_FILTER_SAP_1 : GF_FILTER_SAP_NONE);
     453             :         }
     454       20684 :         m2tdmx_merge_temi((GF_M2TS_ES *)pck->stream, dst_pck);
     455             : 
     456       20684 :         if (pck->stream->is_seg_start) {
     457           0 :                 pck->stream->is_seg_start = GF_FALSE;
     458           0 :                 gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_CUE_START, &PROP_BOOL(GF_TRUE));
     459             :         }
     460       20684 :         gf_filter_pck_send(dst_pck);
     461             : }
     462             : 
     463           1 : static GF_M2TS_ES *m2tsdmx_get_m4sys_stream(GF_M2TSDmxCtx *ctx, u32 m4sys_es_id)
     464             : {
     465             :         u32 i, j, count, count2;
     466           1 :         count = gf_list_count(ctx->ts->programs);
     467           0 :         for (i=0; i<count; i++) {
     468           1 :                 GF_M2TS_Program *prog = gf_list_get(ctx->ts->programs, i);
     469           1 :                 count2 = gf_list_count(prog->streams);
     470           1 :                 for (j=0; j<count2; j++) {
     471           2 :                         GF_M2TS_ES *pes = (GF_M2TS_ES *)gf_list_get(prog->streams, j);
     472           2 :                         if (pes->mpeg4_es_id == m4sys_es_id) return pes;
     473             :                 }
     474             :         }
     475             :         return NULL;
     476             : }
     477           2 : static GFINLINE void m2tsdmx_send_sl_packet(GF_M2TSDmxCtx *ctx, GF_M2TS_SL_PCK *pck)
     478             : {
     479           2 :         GF_SLConfig *slc = ((GF_M2TS_ES*)pck->stream)->slcfg;
     480             :         GF_FilterPid *opid;
     481             :         GF_FilterPacket *dst_pck;
     482             :         u8 * data;
     483             :         Bool start, end;
     484             :         GF_SLHeader slh;
     485           2 :         u32 slh_len = 0;
     486             : 
     487           2 :         if (!pck->stream->user) return;
     488             :         opid = pck->stream->user;
     489             : 
     490             :         /*depacketize SL Header*/
     491           2 :         if (((GF_M2TS_ES*)pck->stream)->slcfg) {
     492           2 :                 gf_sl_depacketize(slc, &slh, pck->data, pck->data_len, &slh_len);
     493           2 :                 slh.m2ts_version_number_plus_one = pck->version_number + 1;
     494             :         } else {
     495           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TSDmx] MPEG-4 SL-packetized stream without SLConfig assigned - ignoring packet\n") );
     496             :                 return;
     497             :         }
     498             : 
     499           2 :         dst_pck = gf_filter_pck_new_alloc(opid, pck->data_len - slh_len, &data);
     500           2 :         if (!dst_pck) return;
     501             : 
     502           2 :         memcpy(data, pck->data + slh_len, pck->data_len - slh_len);
     503             :         start = end = GF_FALSE;
     504           2 :         if (slc->useAccessUnitStartFlag && slh.accessUnitStartFlag) start = GF_TRUE;
     505           2 :         if (slc->useAccessUnitEndFlag && slh.accessUnitEndFlag) end = GF_TRUE;
     506           2 :         gf_filter_pck_set_framing(dst_pck, start, end);
     507             : 
     508           2 :         if (slc->useTimestampsFlag && slh.decodingTimeStampFlag)
     509           0 :                 gf_filter_pck_set_dts(dst_pck, slh.decodingTimeStamp);
     510             : 
     511           2 :         if (slc->useTimestampsFlag && slh.compositionTimeStampFlag)
     512           2 :                 gf_filter_pck_set_cts(dst_pck, slh.compositionTimeStamp);
     513             : 
     514           2 :         if (slc->hasRandomAccessUnitsOnlyFlag || slh.randomAccessPointFlag)
     515           2 :                 gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
     516             : 
     517           2 :         gf_filter_pck_set_carousel_version(dst_pck, pck->version_number);
     518             : 
     519           2 :         m2tdmx_merge_temi(pck->stream, dst_pck);
     520           2 :         if (pck->stream->is_seg_start) {
     521           0 :                 pck->stream->is_seg_start = GF_FALSE;
     522           0 :                 gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_CUE_START, &PROP_BOOL(GF_TRUE));
     523             :         }
     524           2 :         gf_filter_pck_send(dst_pck);
     525             : 
     526           2 :         if (pck->version_number + 1 == pck->stream->slcfg->carousel_version)
     527             :                 return;
     528           2 :         pck->stream->slcfg->carousel_version = 1 + pck->version_number;
     529             : 
     530             : 
     531           2 :         if (pck->stream->flags & GF_M2TS_ES_IS_MPEG4_OD) {
     532             :                 /* We need to decode OD streams to get the SL config for other streams :( */
     533             :                 GF_ESD *esd;
     534             :                 GF_ODUpdate* odU;
     535             :                 GF_ESDUpdate* esdU;
     536             :                 u32 com_count, com_index, od_count, od_index, esd_index;
     537           1 :                 GF_ODCodec *od_codec = gf_odf_codec_new();
     538             : 
     539           1 :                 gf_odf_codec_set_au(od_codec, pck->data + slh_len, pck->data_len - slh_len);
     540           1 :                 gf_odf_codec_decode(od_codec);
     541           1 :                 com_count = gf_list_count(od_codec->CommandList);
     542           2 :                 for (com_index = 0; com_index < com_count; com_index++) {
     543             :                         GF_ODCom *com;
     544           1 :                         com = (GF_ODCom *)gf_list_get(od_codec->CommandList, com_index);
     545           1 :                         switch (com->tag) {
     546           1 :                         case GF_ODF_OD_UPDATE_TAG:
     547             :                                 odU = (GF_ODUpdate*)com;
     548           1 :                                 od_count = gf_list_count(odU->objectDescriptors);
     549           2 :                                 for (od_index=0; od_index<od_count; od_index++) {
     550           1 :                                         GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, od_index);
     551           1 :                                         esd_index = 0;
     552           3 :                                         while ( (esd = gf_list_enum(od->ESDescriptors, &esd_index)) ) {
     553           1 :                                                 GF_M2TS_ES *es = m2tsdmx_get_m4sys_stream(ctx, esd->ESID);
     554             : 
     555           1 :                                                 if (es && ! (es->flags & GF_M2TS_ES_ALREADY_DECLARED)) {
     556           0 :                                                         m2tsdmx_declare_pid(ctx, (GF_M2TS_PES *)es, esd);
     557             :                                                 }
     558             :                                         }
     559             :                                 }
     560             :                                 break;
     561           0 :                         case GF_ODF_ESD_UPDATE_TAG:
     562             :                                 esdU = (GF_ESDUpdate*)com;
     563           0 :                                 esd_index = 0;
     564           0 :                                 while ( (esd = gf_list_enum(esdU->ESDescriptors, &esd_index)) ) {
     565           0 :                                         GF_M2TS_ES *es = m2tsdmx_get_m4sys_stream(ctx, esd->ESID);
     566           0 :                                                 if (es && ! (es->flags & GF_M2TS_ES_ALREADY_DECLARED)) {
     567           0 :                                                         m2tsdmx_declare_pid(ctx, (GF_M2TS_PES *)es, esd);
     568             :                                                 }
     569             :                                 }
     570             :                                 break;
     571             :                         }
     572             :                 }
     573           1 :                 gf_odf_codec_del(od_codec);
     574             :         }
     575             : }
     576             : 
     577             : #ifdef FILTER_FIXME
     578             : static void m2tsdmx_declare_epg_pid(GF_M2TSDmxCtx *ctx)
     579             : {
     580             :         assert(ctx->eit_pid == NULL);
     581             :         ctx->eit_pid = gf_filter_pid_new(ctx->filter);
     582             :         gf_filter_pid_set_property(ctx->eit_pid, GF_PROP_PID_ID, &PROP_UINT(GF_M2TS_PID_EIT_ST_CIT) );
     583             :         gf_filter_pid_set_property(ctx->eit_pid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_PRIVATE_SCENE) );
     584             :         gf_filter_pid_set_property(ctx->eit_pid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_DVB_EIT) );
     585             :         gf_filter_pid_set_property(ctx->eit_pid, GF_PROP_PID_TIMESCALE, &PROP_UINT(90000) );
     586             :         gf_filter_pid_set_property(ctx->eit_pid, GF_PROP_PID_CLOCK_ID, &PROP_UINT(GF_M2TS_PID_EIT_ST_CIT) );
     587             : }
     588             : #endif
     589             : 
     590       49216 : static void m2tsdmx_on_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *param)
     591             : {
     592             :         u32 i, count;
     593       49216 :         GF_Filter *filter = (GF_Filter *) ts->user;
     594       49216 :         GF_M2TSDmxCtx *ctx = gf_filter_get_udta(filter);
     595             : 
     596       49216 :         switch (evt_type) {
     597             :         case GF_M2TS_EVT_PAT_UPDATE:
     598             :                 break;
     599             :         case GF_M2TS_EVT_AIT_FOUND:
     600             :                 break;
     601          32 :         case GF_M2TS_EVT_PAT_FOUND:
     602          32 :                 if (ctx->mux_tune_state==DMX_TUNE_INIT) {
     603          31 :                         ctx->mux_tune_state = DMX_TUNE_WAIT_PROGS;
     604          31 :                         ctx->wait_for_progs = gf_list_count(ts->programs);
     605             :                 }
     606             :                 break;
     607             :         case GF_M2TS_EVT_DSMCC_FOUND:
     608             :                 break;
     609          50 :         case GF_M2TS_EVT_PMT_FOUND:
     610          50 :                 m2tsdmx_setup_program(ctx, param);
     611          50 :                 if (ctx->mux_tune_state == DMX_TUNE_WAIT_PROGS) {
     612             :                         assert(ctx->wait_for_progs);
     613          49 :                         ctx->wait_for_progs--;
     614          49 :                         if (!ctx->wait_for_progs) {
     615          31 :                                 ctx->mux_tune_state = DMX_TUNE_WAIT_SEEK;
     616             :                         }
     617             :                 }
     618             :                 break;
     619             :         case GF_M2TS_EVT_PMT_REPEAT:
     620             :                 break;
     621           0 :         case GF_M2TS_EVT_PMT_UPDATE:
     622           0 :                 m2tsdmx_setup_program(ctx, param);
     623           0 :                 break;
     624             : 
     625          13 :         case GF_M2TS_EVT_SDT_FOUND:
     626             :         case GF_M2TS_EVT_SDT_UPDATE:
     627             : //      case GF_M2TS_EVT_SDT_REPEAT:
     628          13 :                 count = gf_list_count(ts->programs);
     629          41 :                 for (i=0; i<count; i++) {
     630          28 :                         GF_M2TS_Program *prog = gf_list_get(ts->programs, i);
     631          28 :                         GF_M2TS_SDT *sdt = gf_m2ts_get_sdt_info(ts, prog->number);
     632          28 :                         if (sdt) {
     633             :                                 u32 j, nb_streams;
     634          25 :                                 nb_streams = gf_list_count(prog->streams);
     635         123 :                                 for (j=0; j<nb_streams; j++) {
     636          98 :                                         GF_M2TS_ES *es = gf_list_get(prog->streams, j);
     637          98 :                                         if (es->user) {
     638             :                                                 //TODO, translate non standard character maps to UTF8
     639             :                                                 //we for now comment in test mode to avoid non UTF characters in text dumps
     640          49 :                                                 if (isalnum(sdt->service[0]) || !gf_sys_is_test_mode())
     641          43 :                                                         gf_filter_pid_set_property((GF_FilterPid *)es->user, GF_PROP_PID_SERVICE_NAME, &PROP_NAME( sdt->service ) );
     642             : 
     643          49 :                                                 if (isalnum(sdt->provider[0]) || !gf_sys_is_test_mode())
     644          45 :                                                         gf_filter_pid_set_property((GF_FilterPid *)es->user, GF_PROP_PID_SERVICE_PROVIDER, &PROP_NAME( sdt->provider ) );
     645             :                                         }
     646             :                                 }
     647             :                         }
     648             :                 }
     649             :                 break;
     650        7200 :         case GF_M2TS_EVT_DVB_GENERAL:
     651        7200 :                 if (ctx->eit_pid) {
     652             :                         GF_M2TS_SL_PCK *pck = (GF_M2TS_SL_PCK *)param;
     653             :                         u8 *data;
     654           0 :                         GF_FilterPacket *dst_pck = gf_filter_pck_new_alloc(ctx->eit_pid, pck->data_len, &data);
     655           0 :                         if (dst_pck) {
     656           0 :                                 memcpy(data, pck->data, pck->data_len);
     657           0 :                                 gf_filter_pck_send(dst_pck);
     658             :                         }
     659             :                 }
     660             :                 break;
     661       20858 :         case GF_M2TS_EVT_PES_PCK:
     662       20858 :                 if (ctx->mux_tune_state) break;
     663       20684 :                 m2tsdmx_send_packet(ctx, param);
     664       20684 :                 break;
     665           4 :         case GF_M2TS_EVT_SL_PCK: /* DMB specific */
     666           4 :                 if (ctx->mux_tune_state) break;
     667           2 :                 m2tsdmx_send_sl_packet(ctx, param);
     668           2 :                 break;
     669       12682 :         case GF_M2TS_EVT_PES_PCR:
     670       12682 :                 if (ctx->mux_tune_state) break;
     671             :         {
     672             :                 u64 pcr;
     673             :                 Bool map_time = GF_FALSE;
     674             :                 GF_M2TS_PES_PCK *pck = ((GF_M2TS_PES_PCK *) param);
     675       12580 :                 Bool discontinuity = ( ((GF_M2TS_PES_PCK *) param)->flags & GF_M2TS_PES_PCK_DISCONTINUITY) ? 1 : 0;
     676             : 
     677             :                 assert(pck->stream);
     678       12580 :                 m2tsdmx_estimate_duration(ctx, (GF_M2TS_ES *) pck->stream);
     679             : 
     680       12580 :                 if (ctx->map_time_on_prog_id && (ctx->map_time_on_prog_id==pck->stream->program->number)) {
     681             :                         map_time = GF_TRUE;
     682             :                 }
     683             : 
     684             :                 //we forward the PCR on each pid
     685       12580 :                 pcr = ((GF_M2TS_PES_PCK *) param)->PTS;
     686       12580 :                 pcr /= 300;
     687       12580 :                 count = gf_list_count(pck->stream->program->streams);
     688       55978 :                 for (i=0; i<count; i++) {
     689             :                         GF_FilterPacket *dst_pck;
     690       43398 :                         GF_M2TS_PES *stream = gf_list_get(pck->stream->program->streams, i);
     691       43398 :                         if (!stream->user) continue;
     692             : 
     693       24341 :                         dst_pck = gf_filter_pck_new_shared(stream->user, NULL, 0, NULL);
     694       24341 :                         if (!dst_pck) continue;
     695             : 
     696       24341 :                         gf_filter_pck_set_cts(dst_pck, pcr);
     697       24341 :                         gf_filter_pck_set_clock_type(dst_pck, discontinuity ? GF_FILTER_CLOCK_PCR_DISC : GF_FILTER_CLOCK_PCR);
     698       24341 :                         if (pck->stream->is_seg_start) {
     699           0 :                                 pck->stream->is_seg_start = GF_FALSE;
     700           0 :                                 gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_CUE_START, &PROP_BOOL(GF_TRUE));
     701             :                         }
     702       24341 :                         gf_filter_pck_send(dst_pck);
     703             : 
     704       24341 :                         if (map_time) {
     705          56 :                                 gf_filter_pid_set_info_str(stream->user, "time:timestamp", &PROP_LONGUINT(pcr) );
     706          56 :                                 gf_filter_pid_set_info_str(stream->user, "time:media", &PROP_DOUBLE(ctx->media_start_range) );
     707             :                         }
     708             :                 }
     709             : 
     710       12580 :                 if (map_time) {
     711          31 :                         ctx->map_time_on_prog_id = 0;
     712             :                 }
     713             :         }
     714             :                 break;
     715             : 
     716           0 :         case GF_M2TS_EVT_TDT:
     717           0 :                 if (ctx->mux_tune_state) break;
     718             :         {
     719             :                 GF_M2TS_TDT_TOT *tdt = (GF_M2TS_TDT_TOT *)param;
     720           0 :                 u64 utc_ts = gf_net_get_utc_ts(tdt->year, tdt->month, tdt->day, tdt->hour, tdt->minute, tdt->second);
     721           0 :                 count = gf_list_count(ts->programs );
     722           0 :                 for (i=0; i<count; i++) {
     723           0 :                         GF_M2TS_Program *prog = gf_list_get(ts->programs, i);
     724           0 :                         u32 j, count2 = gf_list_count(prog->streams);
     725           0 :                         for (j=0; j<count2; j++) {
     726           0 :                                 GF_M2TS_ES * stream = gf_list_get(prog->streams, j);
     727           0 :                                 if (stream->user) {
     728           0 :                                         gf_filter_pid_set_info(stream->user, GF_PROP_PID_UTC_TIME, & PROP_LONGUINT(utc_ts) );
     729           0 :                                         gf_filter_pid_set_info(stream->user, GF_PROP_PID_UTC_TIMESTAMP, & PROP_LONGUINT(prog->last_pcr_value / 300) );
     730             :                                 }
     731             :                         }
     732           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TS In] Mapping TDT Time %04d/%02d/%02d %02d:%02d:%02d and PCR time "LLD" on program %d\n",
     733             :                                                                        tdt->year, tdt->month, tdt->day, tdt->hour, tdt->minute, tdt->second, prog->last_pcr_value/300, prog->number));
     734             :                 }
     735             :         }
     736             :                 break;
     737             :         case GF_M2TS_EVT_TOT:
     738             :                 break;
     739             : 
     740           0 :         case GF_M2TS_EVT_DURATION_ESTIMATED:
     741             :         {
     742           0 :                 u64 duration = ((GF_M2TS_PES_PCK *) param)->PTS;
     743           0 :                 count = gf_list_count(ts->programs);
     744           0 :                 for (i=0; i<count; i++) {
     745           0 :                         GF_M2TS_Program *prog = gf_list_get(ts->programs, i);
     746             :                         u32 j, count2;
     747           0 :                         count2 = gf_list_count(prog->streams);
     748           0 :                         for (j=0; j<count2; j++) {
     749           0 :                                 GF_M2TS_ES * stream = gf_list_get(prog->streams, j);
     750           0 :                                 if (stream->user) {
     751           0 :                                         gf_filter_pid_set_property(stream->user, GF_PROP_PID_DURATION, & PROP_FRAC64_INT(duration, 1000) );
     752             :                                 }
     753             :                         }
     754             :                 }
     755             :         }
     756             :         break;
     757             : 
     758          46 :         case GF_M2TS_EVT_TEMI_LOCATION:
     759             :         {
     760             :                 GF_M2TS_TemiLocationDescriptor *temi_l = (GF_M2TS_TemiLocationDescriptor *)param;
     761             :                 const char *url;
     762             :                 u32 len;
     763             :                 GF_BitStream *bs;
     764             :                 GF_M2TS_ES *es=NULL;
     765             :                 GF_TEMIInfo *t;
     766          46 :                 if ((temi_l->pid<8192) && (ctx->ts->ess[temi_l->pid])) {
     767             :                         es = ctx->ts->ess[temi_l->pid];
     768             :                 }
     769          46 :                 if (!es || !es->user) {
     770           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TSDmx] TEMI location not assigned to a given PID, not supported\n"));
     771             :                         break;
     772             :                 }
     773          46 :                 GF_SAFEALLOC(t, GF_TEMIInfo);
     774          46 :                 if (!t) break;
     775          46 :                 t->timeline_id = temi_l->timeline_id;
     776          46 :                 t->is_loc = GF_TRUE;
     777             : 
     778          46 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     779          46 :                 if (ctx->temi_url)
     780             :                         url = ctx->temi_url;
     781             :                 else
     782          46 :                         url = temi_l->external_URL;
     783          46 :                 len = url ? (u32) strlen(url) : 0;
     784          46 :                 gf_bs_write_data(bs, url, len);
     785          46 :                 gf_bs_write_u8(bs, 0);
     786          46 :                 gf_bs_write_int(bs, temi_l->is_announce, 1);
     787          46 :                 gf_bs_write_int(bs, temi_l->is_splicing, 1);
     788          46 :                 gf_bs_write_int(bs, temi_l->reload_external, 1);
     789          46 :                 gf_bs_write_int(bs, 0, 5);
     790          46 :                 gf_bs_write_double(bs, temi_l->activation_countdown);
     791          46 :                 gf_bs_get_content(bs, &t->data, &t->len);
     792          46 :                 gf_bs_del(bs);
     793             : 
     794          46 :                 if (!es->props) {
     795          42 :                         es->props = gf_list_new();
     796             :                 }
     797          46 :                 gf_list_add(es->props, t);
     798             :         }
     799          46 :         break;
     800        1384 :         case GF_M2TS_EVT_TEMI_TIMECODE:
     801             :         {
     802             :                 GF_M2TS_TemiTimecodeDescriptor *temi_t = (GF_M2TS_TemiTimecodeDescriptor*)param;
     803             :                 GF_BitStream *bs;
     804             :                 GF_TEMIInfo *t;
     805             :                 GF_M2TS_ES *es=NULL;
     806        1384 :                 if ((temi_t->pid<8192) && (ctx->ts->ess[temi_t->pid])) {
     807             :                         es = ctx->ts->ess[temi_t->pid];
     808             :                 }
     809        1384 :                 if (!es || !es->user) {
     810           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TSDmx] TEMI timing not assigned to a given PID, not supported\n"));
     811             :                         break;
     812             :                 }
     813        1384 :                 GF_SAFEALLOC(t, GF_TEMIInfo);
     814        1384 :                 if (!t) break;
     815        1384 :                 t->timeline_id = temi_t->timeline_id;
     816             : 
     817        1384 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     818        1384 :                 gf_bs_write_u32(bs, temi_t->media_timescale);
     819        1384 :                 gf_bs_write_u64(bs, temi_t->media_timestamp);
     820        1384 :                 gf_bs_write_u64(bs, temi_t->pes_pts);
     821        1384 :                 gf_bs_write_int(bs, temi_t->force_reload, 1);
     822        1384 :                 gf_bs_write_int(bs, temi_t->is_paused, 1);
     823        1384 :                 gf_bs_write_int(bs, temi_t->is_discontinuity, 1);
     824        1384 :                 gf_bs_write_int(bs, temi_t->ntp ? 1 : 0, 1);
     825        1384 :                 gf_bs_write_int(bs, 0, 4);
     826        1384 :                 if (temi_t->ntp)
     827           0 :                         gf_bs_write_u64(bs, temi_t->ntp);
     828             : 
     829        1384 :                 gf_bs_get_content(bs, &t->data, &t->len);
     830        1384 :                 gf_bs_del(bs);
     831             : 
     832        1384 :                 if (!es->props) {
     833        1310 :                         es->props = gf_list_new();
     834             :                 }
     835        1384 :                 gf_list_add(es->props, t);
     836             :         }
     837        1384 :         break;
     838             :         }
     839       49216 : }
     840             : 
     841          37 : static GF_Err m2tsdmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     842             : {
     843             :         const GF_PropertyValue *p;;
     844             :         FILE *stream = NULL;
     845          37 :         GF_M2TSDmxCtx *ctx = gf_filter_get_udta(filter);
     846             : 
     847          37 :         if (is_remove) {
     848           0 :                 ctx->ipid = NULL;
     849             : //              gf_filter_pid_remove(ctx->opid);
     850           0 :                 return GF_OK;
     851             :         }
     852          37 :         if (! gf_filter_pid_check_caps(pid))
     853             :                 return GF_NOT_SUPPORTED;
     854             : 
     855             :         //by default for all URLs, send packets as soon as the program is configured
     856          37 :         ctx->mux_tune_state = DMX_TUNE_DONE;
     857             : 
     858          37 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_FILEPATH);
     859          37 :         if (p && p->value.string && !ctx->duration.num && strncmp(p->value.string, "gmem://", 7)) {
     860          31 :                 stream = gf_fopen(p->value.string, "rb");
     861             :         }
     862             : 
     863          31 :         if (stream) {
     864          31 :                 if (ctx->seeksrc) {
     865             :                         //for local file we will send a seek and stop once all programs are configured, and reparse from start
     866          31 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_URL);
     867          31 :                         if (p && p->value.string && gf_file_exists(p->value.string)) {
     868          31 :                                 ctx->mux_tune_state = DMX_TUNE_INIT;
     869             :                         }
     870             :                 }
     871             :                 
     872          31 :                 ctx->ipid = pid;
     873          31 :                 ctx->is_file = GF_TRUE;
     874          31 :                 ctx->ts->seek_mode = GF_TRUE;
     875          31 :                 ctx->ts->on_event = m2tsdmx_on_event_duration_probe;
     876       18594 :                 while (!gf_feof(stream)) {
     877             :                         char buf[1880];
     878       18563 :                         u32 nb_read = (u32) gf_fread(buf, 1880, stream);
     879       18563 :                         gf_m2ts_process_data(ctx->ts, buf, nb_read);
     880       18563 :                         if (ctx->duration.num || (nb_read!=1880)) break;
     881             :                 }
     882          31 :                 gf_m2ts_demux_del(ctx->ts);
     883          31 :                 gf_fclose(stream);
     884          31 :                 ctx->ts = gf_m2ts_demux_new();
     885          31 :                 ctx->ts->on_event = m2tsdmx_on_event;
     886          31 :                 ctx->ts->user = filter;
     887           6 :         } else if (!p) {
     888             :                 GF_FilterEvent evt;
     889           1 :                 ctx->duration.num = 1;
     890             : 
     891             :                 //not-file base TS, we need to start demuxing the first time we see the PID
     892           1 :                 if (!ctx->ipid) {
     893           1 :                         GF_FEVT_INIT(evt, GF_FEVT_PLAY, pid);
     894           1 :                         gf_filter_pid_send_event(pid, &evt);
     895             :                 }
     896             :         }
     897          37 :         ctx->ipid = pid;
     898          37 :         return GF_OK;
     899             : }
     900             : 
     901             : 
     902          96 : static GF_M2TS_PES *m2tsdmx_get_stream(GF_M2TSDmxCtx *ctx, GF_FilterPid *pid)
     903             : {
     904             :         u32 i, j, count, count2;
     905          96 :         count = gf_list_count(ctx->ts->programs);
     906          96 :         for (i=0; i<count; i++) {
     907         192 :                 GF_M2TS_Program *prog = gf_list_get(ctx->ts->programs, i);
     908         192 :                 count2 = gf_list_count(prog->streams);
     909         496 :                 for (j=0; j<count2; j++) {
     910         592 :                         GF_M2TS_PES *pes = (GF_M2TS_PES *)gf_list_get(prog->streams, j);
     911         592 :                         if (pes->user == pid) return pes;
     912             :                 }
     913             :         }
     914             :         return NULL;
     915             : }
     916             : 
     917           0 : static void m2tsdmx_switch_quality(GF_M2TS_Program *prog, GF_M2TS_Demuxer *ts, Bool switch_up)
     918             : {
     919             :         GF_M2TS_ES *es;
     920             :         u32 i, count;
     921             : 
     922           0 :         if (!prog->is_scalable)
     923             :                 return;
     924             : 
     925           0 :         if (switch_up) {
     926           0 :                 for (i = 0; i < GF_M2TS_MAX_STREAMS; i++) {
     927           0 :                         es = ts->ess[i];
     928           0 :                         if (es && (es->flags & GF_M2TS_ES_IS_PES) && (((GF_M2TS_PES *)es)->depends_on_pid == prog->pid_playing)) {
     929           0 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("Turn on ES%d\n", es->pid));
     930           0 :                                 gf_m2ts_set_pes_framing((GF_M2TS_PES *)ts->ess[es->pid], GF_M2TS_PES_FRAMING_DEFAULT);
     931           0 :                                 prog->pid_playing = es->pid;
     932           0 :                                 return;
     933             :                         }
     934             :                 }
     935             :         }
     936             :         else {
     937           0 :                 count = gf_list_count(prog->streams);
     938           0 :                 for (i = 0; i < count; i++) {
     939           0 :                         es = (GF_M2TS_ES *)gf_list_get(prog->streams, i);
     940           0 :                         if (es && (es->pid == prog->pid_playing) && ((GF_M2TS_PES *)es)->depends_on_pid) {
     941           0 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("Turn off ES%d - playing ES%d\n", es->pid, ((GF_M2TS_PES *)es)->depends_on_pid));
     942           0 :                                 gf_m2ts_set_pes_framing((GF_M2TS_PES *)ts->ess[es->pid], GF_M2TS_PES_FRAMING_SKIP);
     943             : 
     944             :                                 //do we want to send a reset ?
     945           0 :                                 prog->pid_playing = ((GF_M2TS_PES *)es)->depends_on_pid;
     946           0 :                                 return;
     947             :                         }
     948             :                 }
     949             :         }
     950             : }
     951             : 
     952       31942 : static Bool m2tsdmx_process_event(GF_Filter *filter, const GF_FilterEvent *com)
     953             : {
     954             :         GF_M2TS_PES *pes;
     955             :         u64 file_pos = 0;
     956             :         GF_FilterEvent fevt;
     957       31942 :         GF_M2TSDmxCtx *ctx = gf_filter_get_udta(filter);
     958       31942 :         GF_M2TS_Demuxer *ts = ctx->ts;
     959             : 
     960       31942 :         if (com->base.type == GF_FEVT_QUALITY_SWITCH) {
     961             :                 u32 i, count;
     962           0 :                 count = gf_list_count(ts->programs);
     963           0 :                 for (i = 0; i < count; i++) {
     964           0 :                         GF_M2TS_Program *prog = (GF_M2TS_Program *)gf_list_get(ts->programs, i);
     965           0 :                         m2tsdmx_switch_quality(prog, ts, com->quality_switch.up);
     966             :                 }
     967             :                 //don't cancel event for RTP source
     968             :                 return GF_FALSE;
     969             :         }
     970             : 
     971             :                 //don't cancel event for RTP source
     972       31942 :         if (!com->base.on_pid) return GF_FALSE;
     973       31942 :         switch (com->base.type) {
     974          90 :         case GF_FEVT_PLAY:
     975          90 :                 pes = m2tsdmx_get_stream(ctx, com->base.on_pid);
     976          90 :                 if (!pes) {
     977             :                         if (com->base.on_pid == ctx->eit_pid) {
     978             :                                 return GF_FALSE;
     979             :                         }
     980             :                         return GF_FALSE;
     981             :                 }
     982             :                 /*mark pcr as not initialized*/
     983          90 :                 if (pes->program->pcr_pid==pes->pid) pes->program->first_dts=0;
     984          90 :                 gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT);
     985          90 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TSDmx] Setting default reframing for PID %d\n", pes->pid));
     986             : 
     987             :                 /*this is a multplex, only trigger the play command for the first stream activated*/
     988          90 :                 ctx->nb_playing++;
     989          90 :                 if (ctx->nb_playing>1) return GF_TRUE;
     990             : 
     991             :                 //not file, don't cancel the event
     992          32 :                 if (!ctx->is_file) {
     993           1 :                         ctx->initial_play_done = GF_TRUE;
     994           1 :                         return GF_FALSE;
     995             :                 }
     996             : 
     997          31 :                 ctx->map_time_on_prog_id = pes->program->number;
     998          31 :                 ctx->media_start_range = com->play.start_range;
     999             : 
    1000             : 
    1001          31 :                 if (ctx->is_file && ctx->duration.num) {
    1002          31 :                         file_pos = (u64) (ctx->file_size * com->play.start_range);
    1003          31 :                         file_pos *= ctx->duration.den;
    1004          31 :                         file_pos /= ctx->duration.num;
    1005          31 :                         if (file_pos > ctx->file_size) return GF_TRUE;
    1006             :                 }
    1007             : 
    1008          31 :                 if (!ctx->initial_play_done) {
    1009          31 :                         ctx->initial_play_done = GF_TRUE;
    1010             :                         //seek will not change the current source state, don't send a seek
    1011          31 :                         if (!file_pos)
    1012             :                                 return GF_TRUE;
    1013             :                 }
    1014             : 
    1015             :                 //file and seek, cancel the event and post a seek event to source
    1016           0 :                 ctx->in_seek = GF_TRUE;
    1017             :                 //we seek so consider the mux tuned in
    1018           0 :                 ctx->mux_tune_state = DMX_TUNE_DONE;
    1019             : 
    1020             :                 //post a seek
    1021           0 :                 GF_FEVT_INIT(fevt, GF_FEVT_SOURCE_SEEK, ctx->ipid);
    1022           0 :                 fevt.seek.start_offset = file_pos;
    1023           0 :                 gf_filter_pid_send_event(ctx->ipid, &fevt);
    1024           0 :                 return GF_TRUE;
    1025             : 
    1026           6 :         case GF_FEVT_STOP:
    1027           6 :                 pes = m2tsdmx_get_stream(ctx, com->base.on_pid);
    1028           6 :                 if (!pes) {
    1029             :                         if (com->base.on_pid == ctx->eit_pid) {
    1030             :                                 return GF_FALSE;
    1031             :                         }
    1032             :                         return GF_FALSE;
    1033             :                 }
    1034             :                 /* In case of EOS, we may receive a stop command after no one is playing */
    1035           6 :                 if (ctx->nb_playing)
    1036           6 :                         ctx->nb_playing--;
    1037             : 
    1038           6 :                 gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_SKIP);
    1039             :                 //don't cancel event if still playing
    1040           6 :                 return ctx->nb_playing ? GF_TRUE : GF_FALSE;
    1041             : 
    1042             :         case GF_FEVT_PAUSE:
    1043             :         case GF_FEVT_RESUME:
    1044             :                 return GF_FALSE;
    1045             :         default:
    1046             :                 return GF_FALSE;
    1047             :         }
    1048             : }
    1049             : 
    1050             : 
    1051             : 
    1052          32 : static GF_Err m2tsdmx_initialize(GF_Filter *filter)
    1053             : {
    1054          32 :         GF_M2TSDmxCtx *ctx = gf_filter_get_udta(filter);
    1055             : 
    1056          32 :         ctx->ts = gf_m2ts_demux_new();
    1057          32 :         if (!ctx->ts) return GF_OUT_OF_MEM;
    1058             : 
    1059          32 :         ctx->ts->on_event = m2tsdmx_on_event;
    1060          32 :         ctx->ts->user = filter;
    1061             : 
    1062          32 :         ctx->filter = filter;
    1063          32 :         if (ctx->dsmcc) {
    1064           1 :                 gf_m2ts_demux_dmscc_init(ctx->ts);
    1065             :         }
    1066             : 
    1067             :         return GF_OK;
    1068             : }
    1069             : 
    1070             : 
    1071          32 : static void m2tsdmx_finalize(GF_Filter *filter)
    1072             : {
    1073          32 :         GF_M2TSDmxCtx *ctx = gf_filter_get_udta(filter);
    1074          32 :         if (ctx->ts) gf_m2ts_demux_del(ctx->ts);
    1075             : 
    1076          32 : }
    1077             : 
    1078       31928 : static GF_Err m2tsdmx_process(GF_Filter *filter)
    1079             : {
    1080       31928 :         GF_M2TSDmxCtx *ctx = gf_filter_get_udta(filter);
    1081       31928 :         GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
    1082             :         const char *data;
    1083             :         u32 size;
    1084             : 
    1085       31928 :         if (!pck) {
    1086          69 :                 if (gf_filter_pid_is_eos(ctx->ipid)) {
    1087          34 :                         u32 i, nb_streams = gf_filter_get_opid_count(filter);
    1088             : 
    1089          34 :                         gf_m2ts_flush_all(ctx->ts);
    1090         129 :                         for (i=0; i<nb_streams; i++) {
    1091          95 :                                 GF_FilterPid *opid = gf_filter_get_opid(filter, i);
    1092          95 :                                 gf_filter_pid_set_eos(opid);
    1093             :                         }
    1094             :                         return GF_EOS;
    1095             :                 }
    1096             :                 return GF_OK;
    1097             :         }
    1098       31859 :         if (ctx->sigfrag) {
    1099             :                 Bool is_start;
    1100           0 :                 gf_filter_pck_get_framing(pck, &is_start, NULL);
    1101           0 :                 if (is_start) {
    1102           0 :                         gf_m2ts_mark_seg_start(ctx->ts);
    1103             :                 }
    1104             :         }
    1105             :         //we process even if no stream playing: since we use unframed dispatch we may need to send packets to configure reframers
    1106             :         //which will in turn connect to the sink which will send the PLAY event marking stream(s) as playing
    1107       31859 :         if (ctx->in_seek) {
    1108           0 :                 gf_m2ts_reset_parsers(ctx->ts);
    1109           0 :                 ctx->in_seek = GF_FALSE;
    1110             :         } else {
    1111             :                 u32 i, nb_streams, would_block = 0;
    1112       31859 :                 nb_streams = gf_filter_get_opid_count(filter);
    1113      281337 :                 for (i=0; i<nb_streams; i++) {
    1114      249478 :                         GF_FilterPid *opid = gf_filter_get_opid(filter, i);
    1115      249478 :                         if ( gf_filter_pid_would_block(opid) ) {
    1116        7257 :                                 would_block++;
    1117             :                         }
    1118             :                 }
    1119       31859 :                 if (would_block && (would_block==nb_streams))
    1120             :                         return GF_OK;
    1121             :         }
    1122             : 
    1123       31859 :         data = gf_filter_pck_get_data(pck, &size);
    1124       31859 :         if (data && size)
    1125       31859 :                 gf_m2ts_process_data(ctx->ts, (char*) data, size);
    1126             : 
    1127       31859 :         gf_filter_pid_drop_packet(ctx->ipid);
    1128             : 
    1129       31859 :         if (ctx->mux_tune_state==DMX_TUNE_WAIT_SEEK) {
    1130             :                 GF_FilterEvent fevt;
    1131          31 :                 GF_FEVT_INIT(fevt, GF_FEVT_SOURCE_SEEK, ctx->ipid);
    1132          31 :                 gf_filter_pid_send_event(ctx->ipid, &fevt);
    1133          31 :                 ctx->mux_tune_state = DMX_TUNE_DONE;
    1134          31 :                 gf_m2ts_reset_parsers(ctx->ts);
    1135             :         }
    1136             :         return GF_OK;
    1137             : }
    1138             : 
    1139        3074 : static const char *m2tsdmx_probe_data(const u8 *data, u32 size, GF_FilterProbeScore *score)
    1140             : {
    1141        3074 :         if (gf_m2ts_probe_data(data, size)) {
    1142          34 :                 *score = GF_FPROBE_SUPPORTED;
    1143          34 :                 return "video/mp2t";
    1144             :         }
    1145             :         return NULL;
    1146             : }
    1147             : 
    1148             : static const GF_FilterCapability M2TSDmxCaps[] =
    1149             : {
    1150             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1151             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "ts|m2t|mts|dmb|trp"),
    1152             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "video/mpeg-2|video/mp2t|video/mpeg"),
    1153             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1154             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1155             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_SCENE),
    1156             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_OD),
    1157             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_PRIVATE_SCENE),
    1158             :         CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1159             : };
    1160             : 
    1161             : #define OFFS(_n)        #_n, offsetof(GF_M2TSDmxCtx, _n)
    1162             : static const GF_FilterArgs M2TSDmxArgs[] =
    1163             : {
    1164             :         { OFFS(temi_url), "force TEMI URL", GF_PROP_NAME, NULL, NULL, GF_FS_ARG_HINT_ADVANCED},
    1165             :         { OFFS(dsmcc), "enable DSMCC receiver", GF_PROP_BOOL, "no", NULL, GF_FS_ARG_HINT_EXPERT},
    1166             :         { OFFS(seeksrc), "seek local source file back to origin once all programs are setup", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_EXPERT},
    1167             :         { OFFS(sigfrag), "signal segment boundaries of source on output packets", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
    1168             :         {0}
    1169             : };
    1170             : 
    1171             : 
    1172             : GF_FilterRegister M2TSDmxRegister = {
    1173             :         .name = "m2tsdmx",
    1174             :         GF_FS_SET_DESCRIPTION("MPEG-2 TS demuxer")
    1175             :         GF_FS_SET_HELP("This filter demultiplexes MPEG-2 Transport Stream files/data into a set of media PIDs and frames.")
    1176             :         .private_size = sizeof(GF_M2TSDmxCtx),
    1177             :         .initialize = m2tsdmx_initialize,
    1178             :         .finalize = m2tsdmx_finalize,
    1179             :         .args = M2TSDmxArgs,
    1180             :         .flags = GF_FS_REG_DYNAMIC_PIDS,
    1181             :         SETCAPS(M2TSDmxCaps),
    1182             :         .configure_pid = m2tsdmx_configure_pid,
    1183             :         .process = m2tsdmx_process,
    1184             :         .process_event = m2tsdmx_process_event,
    1185             :         .probe_data = m2tsdmx_probe_data,
    1186             : };
    1187             : 
    1188             : 
    1189             : #endif
    1190             : 
    1191        2877 : const GF_FilterRegister *m2tsdmx_register(GF_FilterSession *session)
    1192             : {
    1193             : #ifndef GPAC_DISABLE_MPEG2TS
    1194        2877 :         return &M2TSDmxRegister;
    1195             : #else
    1196             :         return NULL;
    1197             : #endif
    1198             : }

Generated by: LCOV version 1.13