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

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2005-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / MPEG Program Stream demuxer 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/thread.h>
      29             : #include <gpac/list.h>
      30             : #include <gpac/bitstream.h>
      31             : 
      32             : #ifndef GPAC_DISABLE_MPEG2PS
      33             : #include "../media_tools/mpeg2_ps.h"
      34             : #include <gpac/media_tools.h>
      35             : 
      36             : typedef struct
      37             : {
      38             :         GF_FilterPid *opid;
      39             :         u32 stream_type;
      40             :         u32 stream_num;
      41             :         Bool in_use;
      42             :         u64 last_dts;
      43             : } M2PSStream;
      44             : 
      45             : 
      46             : typedef struct
      47             : {
      48             :         GF_FilterPid *ipid;
      49             : 
      50             :         const char *src_url;
      51             :         mpeg2ps_t *ps;
      52             : 
      53             :         Double start_range;
      54             :         u64 first_dts;
      55             : 
      56             :         u32 nb_playing;
      57             :         GF_Fraction64 duration;
      58             :         Bool in_seek;
      59             : 
      60             :         GF_List *streams;
      61             :         Bool initial_play_done;
      62             : } GF_M2PSDmxCtx;
      63             : 
      64           7 : static void m2psdmx_setup(GF_Filter *filter, GF_M2PSDmxCtx *ctx)
      65             : {
      66             :         u32 i, nb_streams;
      67             :         u32 sync_id = 0;
      68             :         Double fps;
      69             :         GF_Fraction64 dur;
      70             : 
      71             :         dur.den = 1000;
      72           7 :         dur.num = (s32) mpeg2ps_get_max_time_msec(ctx->ps);
      73             : 
      74           7 :         ctx->first_dts = mpeg2ps_get_first_cts(ctx->ps);
      75             : 
      76           7 :         nb_streams = mpeg2ps_get_video_stream_count(ctx->ps);
      77          12 :         for (i=0; i<nb_streams; i++) {
      78             :                 u32 par;
      79             :                 u32 id;
      80             :                 GF_Fraction frac;
      81             :                 M2PSStream *st = NULL;
      82           5 :                 u32 j, count = gf_list_count(ctx->streams);
      83           5 :                 for (j=0; j<count; j++) {
      84           0 :                         st = gf_list_get(ctx->streams, j);
      85           0 :                         if ((st->stream_type==GF_STREAM_VISUAL) && !st->in_use) break;
      86             :                         st = NULL;
      87             :                 }
      88           5 :                 if (!st) {
      89           5 :                         GF_SAFEALLOC(st, M2PSStream);
      90           5 :                         if (!st) continue;
      91           5 :                         st->opid = gf_filter_pid_new(filter);
      92           5 :                         st->stream_type = GF_STREAM_VISUAL;
      93           5 :                         gf_list_add(ctx->streams, st);
      94             :                 }
      95           5 :                 st->in_use = GF_TRUE;
      96           5 :                 st->stream_num = i;
      97           5 :                 id = 0x100 | mpeg2ps_get_video_stream_id(ctx->ps, st->stream_num);
      98           5 :                 if (!sync_id) sync_id = id;
      99             : 
     100           5 :                 gf_filter_pid_copy_properties(st->opid, ctx->ipid);
     101           5 :                 gf_filter_pid_set_name(st->opid, "Video");
     102           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(st->stream_type) );
     103           5 :                 switch (mpeg2ps_get_video_stream_type(ctx->ps, st->stream_num)) {
     104           5 :                 case MPEG_VIDEO_MPEG1:
     105           5 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_MPEG1) );
     106           5 :                         break;
     107           0 :                 case MPEG_VIDEO_MPEG2:
     108           0 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_MPEG2_MAIN) );
     109           0 :                         break;
     110             :                 default:
     111             :                         break;
     112             :                 }
     113           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(90000) );
     114           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_ID, &PROP_UINT( id) );
     115           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_CLOCK_ID, &PROP_UINT( sync_id ) );
     116             : 
     117           5 :                 fps = mpeg2ps_get_video_stream_framerate(ctx->ps, i);
     118           5 :                 if (fps) {
     119           5 :                         gf_media_get_video_timing(fps, &frac.num, &frac.den);
     120           5 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_FPS, &PROP_FRAC( frac ) );
     121             :                 }
     122           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_WIDTH, &PROP_UINT( mpeg2ps_get_video_stream_width(ctx->ps, i) ) );
     123           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_HEIGHT, &PROP_UINT( mpeg2ps_get_video_stream_height(ctx->ps, i) ) );
     124           5 :                 par = mpeg2ps_get_video_stream_aspect_ratio(ctx->ps, i);
     125           5 :                 if (par) {
     126           0 :                         frac.num = par>>16;
     127           0 :                         frac.den = (par&0xffff);
     128           0 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_SAR, &PROP_FRAC( frac ) );
     129             :                 }
     130           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_DURATION, &PROP_FRAC64( dur ) );
     131           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL( GF_TRUE ) );
     132           5 :                 gf_filter_pid_set_property_str(st->opid, "nocts", &PROP_BOOL(GF_TRUE ));
     133             : 
     134           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_BITRATE, &PROP_UINT((u32) mpeg2ps_get_video_stream_bitrate(ctx->ps, i) ) );
     135             : 
     136           5 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD ) );
     137             :         }
     138             : 
     139           7 :         nb_streams = mpeg2ps_get_audio_stream_count(ctx->ps);
     140          14 :         for (i=0; i<nb_streams; i++) {
     141             :                 u32 id;
     142             :                 char szName[20];
     143             :                 M2PSStream *st = NULL;
     144           7 :                 u32 j, count = gf_list_count(ctx->streams);
     145             : 
     146           7 :                 if (mpeg2ps_get_audio_stream_type(ctx->ps, i) == MPEG_AUDIO_UNKNOWN) {
     147           0 :                         continue;
     148             :                 }
     149             : 
     150           5 :                 for (j=0; j<count; j++) {
     151           5 :                         st = gf_list_get(ctx->streams, j);
     152           5 :                         if ((st->stream_type==GF_STREAM_AUDIO) && !st->in_use) break;
     153             :                         st = NULL;
     154             :                 }
     155           7 :                 if (!st) {
     156           7 :                         GF_SAFEALLOC(st, M2PSStream);
     157           7 :                         if (!st) continue;
     158           7 :                         st->opid = gf_filter_pid_new(filter);
     159           7 :                         st->stream_type = GF_STREAM_AUDIO;
     160           7 :                         gf_list_add(ctx->streams, st);
     161             :                 }
     162           7 :                 st->in_use = GF_TRUE;
     163           7 :                 st->stream_num = i;
     164           7 :                 id = 0x100 | mpeg2ps_get_audio_stream_id(ctx->ps, st->stream_num);
     165           7 :                 if (!sync_id) sync_id = id;
     166             : 
     167           7 :                 gf_filter_pid_copy_properties(st->opid, ctx->ipid);
     168           7 :                 sprintf(szName, "Audio%d", i+1);
     169           7 :                 gf_filter_pid_set_name(st->opid, szName);
     170           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(st->stream_type) );
     171           7 :                 switch (mpeg2ps_get_audio_stream_type(ctx->ps, st->stream_num)) {
     172           5 :                 case MPEG_AUDIO_MPEG:
     173           5 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_CODECID, &PROP_UINT( GF_CODECID_MPEG_AUDIO) );
     174           5 :                         break;
     175           2 :                 case MPEG_AUDIO_AC3:
     176           2 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_CODECID, &PROP_UINT( GF_CODECID_AC3) );
     177           2 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL( GF_TRUE) );
     178           2 :                         break;
     179           0 :                 case MPEG_AUDIO_LPCM:
     180           0 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_4CC('L','P','C','M') ) );
     181           0 :                         break;
     182             :                 default:
     183             :                         break;
     184             :                 }
     185           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT( mpeg2ps_get_audio_stream_sample_freq(ctx->ps, i) ) );
     186           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT( mpeg2ps_get_audio_stream_channels(ctx->ps, i) ) );
     187           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_BITRATE, &PROP_UINT( mpeg2ps_get_audio_stream_bitrate(ctx->ps, i) ) );
     188             : 
     189           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(90000) );
     190           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_ID, &PROP_UINT( id) );
     191           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_CLOCK_ID, &PROP_UINT( sync_id ) );
     192           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_DURATION, &PROP_FRAC64( dur ) );
     193           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL( GF_TRUE ) );
     194           7 :                 gf_filter_pid_set_property_str(st->opid, "nocts", &PROP_BOOL(GF_TRUE ));
     195             : 
     196           7 :                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD ) );
     197             :         }
     198           7 : }
     199             : 
     200             : 
     201           7 : GF_Err m2psdmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     202             : {
     203             :         u32 i;
     204             :         const GF_PropertyValue *p;
     205           7 :         GF_M2PSDmxCtx *ctx = gf_filter_get_udta(filter);
     206             : 
     207           7 :         if (is_remove) {
     208           0 :                 ctx->ipid = NULL;
     209           0 :                 while (gf_list_count(ctx->streams) ) {
     210           0 :                         M2PSStream *st = gf_list_pop_back(ctx->streams);
     211           0 :                         if (st->opid)
     212           0 :                                 gf_filter_pid_remove(st->opid);
     213           0 :                         gf_free(st);
     214             :                 }
     215             :                 return GF_OK;
     216             :         }
     217           7 :         if (! gf_filter_pid_check_caps(pid))
     218             :                 return GF_NOT_SUPPORTED;
     219             : 
     220           7 :         if (!ctx->ipid) {
     221             :                 GF_FilterEvent fevt;
     222           7 :                 ctx->ipid = pid;
     223             : 
     224             :                 //we work with full file only, send a play event on source to indicate that
     225           7 :                 GF_FEVT_INIT(fevt, GF_FEVT_PLAY, pid);
     226             :                 fevt.play.start_range = 0;
     227           7 :                 fevt.base.on_pid = ctx->ipid;
     228           7 :                 fevt.play.full_file_only = GF_TRUE;
     229           7 :                 gf_filter_pid_send_event(ctx->ipid, &fevt);
     230             :         }
     231             : 
     232           7 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILEPATH);
     233           7 :         if (!p) return GF_NOT_SUPPORTED;
     234             : 
     235           7 :         if (ctx->src_url && !strcmp(ctx->src_url, p->value.string)) return GF_OK;
     236             : 
     237           7 :         if (ctx->ps) {
     238           0 :                 mpeg2ps_close(ctx->ps);
     239           0 :                 for (i=0; i<gf_list_count(ctx->streams); i++) {
     240           0 :                         M2PSStream *st = gf_list_get(ctx->streams, i);
     241           0 :                         st->in_use = GF_FALSE;
     242             :                 }
     243             :         }
     244           7 :         ctx->ps = NULL;
     245             : 
     246           7 :         ctx->src_url = p->value.string;
     247             : 
     248           7 :         return GF_OK;
     249             : }
     250             : 
     251        3388 : static Bool m2psdmx_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
     252             : {
     253             :         u32 i;
     254        3388 :         GF_M2PSDmxCtx *ctx = gf_filter_get_udta(filter);
     255             : 
     256        3388 :         switch (evt->base.type) {
     257          12 :         case GF_FEVT_PLAY:
     258          12 :                 if (ctx->nb_playing && (ctx->start_range ==  evt->play.start_range)) {
     259           5 :                         ctx->nb_playing++;
     260           5 :                         return GF_TRUE;
     261             :                 }
     262           7 :                 ctx->nb_playing++;
     263           7 :                 ctx->start_range = evt->play.start_range;
     264           7 :                 gf_filter_post_process_task(filter);
     265             : 
     266           7 :                 if (!ctx->initial_play_done) {
     267           7 :                         ctx->initial_play_done = GF_TRUE;
     268             :                         //seek will not change the current source state, don't send a seek
     269           7 :                         if (ctx->start_range<0.5)
     270             :                                 return GF_TRUE;
     271             :                 }
     272             : 
     273           2 :                 for (i=0; i<gf_list_count(ctx->streams); i++) {
     274           2 :                         M2PSStream *pss = gf_list_get(ctx->streams, i);
     275           2 :                         if (pss->opid == evt->base.on_pid)
     276           1 :                                 pss->in_use = GF_TRUE;
     277           2 :                         if (!pss->in_use) continue;
     278             : 
     279           2 :                         if (pss->stream_type==GF_STREAM_VISUAL) {
     280           1 :                                 mpeg2ps_seek_video_frame(ctx->ps, pss->stream_num, (u64) (ctx->start_range*1000));
     281             :                         } else {
     282           1 :                                 mpeg2ps_seek_audio_frame(ctx->ps, pss->stream_num, (u64) (ctx->start_range*1000) );
     283             :                         }
     284             :                 }
     285             :                 //cancel event
     286             :                 return GF_TRUE;
     287             : 
     288           3 :         case GF_FEVT_STOP:
     289           3 :                 ctx->nb_playing--;
     290           8 :                 for (i=0; i<gf_list_count(ctx->streams); i++) {
     291           5 :                         M2PSStream *pss = gf_list_get(ctx->streams, i);
     292           5 :                         if (pss->opid == evt->base.on_pid)
     293           3 :                                 pss->in_use = GF_FALSE;
     294             :                 }
     295             :                 //cancel event if not last stream playing
     296           3 :                 if (ctx->nb_playing) return GF_TRUE;
     297             : 
     298           2 :                 return GF_FALSE;
     299             : 
     300             :         case GF_FEVT_SET_SPEED:
     301             :                 //cancel event
     302             :                 return GF_TRUE;
     303             :         default:
     304             :                 break;
     305             :         }
     306             :         //by default don't cancel event - to rework once we have downloading in place
     307        3373 :         return GF_FALSE;
     308             : }
     309             : 
     310        9714 : GF_Err m2psdmx_process(GF_Filter *filter)
     311             : {
     312        9714 :         GF_M2PSDmxCtx *ctx = gf_filter_get_udta(filter);
     313             :         Bool start, end;
     314             :         u32 i, count, nb_done;
     315        9714 :         if (!ctx->ps) {
     316        3373 :                 GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
     317        3373 :                 if (!pck) {
     318             :                         return GF_OK;
     319             :                 }
     320        3373 :                 gf_filter_pck_get_framing(pck, &start, &end);
     321        3373 :                 if (!end) {
     322        3366 :                         gf_filter_pid_drop_packet(ctx->ipid);
     323        3366 :                         return GF_OK;
     324             :                 }
     325           7 :                 gf_filter_pid_drop_packet(ctx->ipid);
     326             : 
     327           7 :                 ctx->ps = mpeg2ps_init(ctx->src_url);
     328           7 :                 if (!ctx->ps) {
     329             :                         GF_Err e = GF_NON_COMPLIANT_BITSTREAM;
     330           0 :                         if (! gf_file_exists(ctx->src_url)) e = GF_URL_ERROR;
     331           0 :                         gf_filter_setup_failure(filter, e);
     332           0 :                         return GF_NOT_SUPPORTED;
     333             :                 }
     334           7 :                 m2psdmx_setup(filter, ctx);
     335             :         }
     336        6348 :         if (!ctx->nb_playing) return GF_OK;
     337             : 
     338             : 
     339             :         nb_done = 0;
     340        6309 :         count = gf_list_count(ctx->streams);
     341             : 
     342        6309 :         if (ctx->in_seek) {
     343           0 :                 u64 seek_to = (u64) (1000*ctx->start_range);
     344           0 :                 for (i=0; i<count;i++) {
     345           0 :                         M2PSStream *st = gf_list_get(ctx->streams, i);
     346           0 :                         if (!st->in_use) continue;
     347           0 :                         if (st->stream_type==GF_STREAM_VISUAL) {
     348           0 :                                 mpeg2ps_seek_video_frame(ctx->ps, st->stream_num, seek_to);
     349             :                         } else {
     350           0 :                                 mpeg2ps_seek_audio_frame(ctx->ps, st->stream_num, seek_to);
     351             :                         }
     352             :                 }
     353           0 :                 ctx->in_seek = GF_FALSE;
     354             :         }
     355             : 
     356             : 
     357       12585 :         for (i=0; i<count;i++) {
     358             :                 u8 *buf;
     359             :                 u32 buf_len;
     360             :                 u8 *pck_data;
     361             :                 GF_FilterPacket *dst_pck;
     362       12585 :                 M2PSStream *st = gf_list_get(ctx->streams, i);
     363       12585 :                 if (!st->in_use) {
     364           0 :                         nb_done++;
     365        2871 :                         continue;
     366             :                 }
     367             : 
     368       12585 :                 if (gf_filter_pid_would_block(st->opid)) continue;
     369             : 
     370       11626 :                 if (st->stream_type==GF_STREAM_VISUAL) {
     371             :                         u8 ftype;
     372             :                         u64 dts, cts;
     373        5320 :                         u32 res = mpeg2ps_get_video_frame(ctx->ps, st->stream_num, (u8 **) &buf, &buf_len, &ftype, TS_90000, &dts, &cts);
     374        5320 :                         if (!res) {
     375        1495 :                                 nb_done++;
     376        2990 :                                 continue;
     377             :                         }
     378             : 
     379             :                         //bug in some streams, make sure we don't dispatch twice the same ts
     380        3825 :                         if (st->last_dts == dts) dts++;;
     381        3825 :                         st->last_dts = dts;
     382             : 
     383        3825 :                         if ((buf[buf_len - 4] == 0) && (buf[buf_len - 3] == 0) && (buf[buf_len - 2] == 1)) buf_len -= 4;
     384        3825 :                         dst_pck = gf_filter_pck_new_alloc(st->opid, buf_len, &pck_data);
     385        3825 :                         if (!dst_pck) continue;
     386             : 
     387        3825 :                         memcpy(pck_data, buf, buf_len);
     388        3825 :                         if (ftype==1) gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
     389             : 
     390        3825 :                         if (cts != GF_FILTER_NO_TS) {
     391        3825 :                                 if (dts == GF_FILTER_NO_TS) dts = cts;
     392        3825 :                                 dts -= ctx->first_dts;
     393        3825 :                                 cts -= ctx->first_dts;
     394        3825 :                                 gf_filter_pck_set_dts(dst_pck, dts);
     395        3825 :                                 gf_filter_pck_set_cts(dst_pck, cts);
     396        3825 :                                 gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_FALSE);
     397             :                         } else {
     398           0 :                                 gf_filter_pck_set_framing(dst_pck, GF_FALSE, GF_FALSE);
     399             :                         }
     400        3825 :                         gf_filter_pck_send(dst_pck);
     401             :                 } else {
     402             :                         u64 cts;
     403        6306 :                         u32 res = mpeg2ps_get_audio_frame(ctx->ps, st->stream_num, (u8**)&buf, &buf_len, TS_90000, NULL, &cts);
     404        6306 :                         if (!res) {
     405         417 :                                 nb_done++;
     406         834 :                                 continue;
     407             :                         }
     408        5889 :                         dst_pck = gf_filter_pck_new_alloc(st->opid, buf_len, &pck_data);
     409        5889 :                         if (!dst_pck) continue;
     410             :                         
     411        5889 :                         memcpy(pck_data, buf, buf_len);
     412        5889 :                         if (cts != GF_FILTER_NO_TS) {
     413        5889 :                                 cts -= ctx->first_dts;
     414        5889 :                                 gf_filter_pck_set_cts(dst_pck, cts);
     415        5889 :                                 gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_FALSE);
     416             :                         } else {
     417           0 :                                 gf_filter_pck_set_framing(dst_pck, GF_FALSE, GF_FALSE);
     418             :                         }
     419        5889 :                         gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
     420             : 
     421        5889 :                         gf_filter_pck_send(dst_pck);
     422             :                 }
     423             :         }
     424             : 
     425        6309 :         if (nb_done==count) {
     426           9 :                 for (i=0; i<count;i++) {
     427           9 :                         M2PSStream *st = gf_list_get(ctx->streams, i);
     428           9 :                         gf_filter_pid_set_eos(st->opid);
     429             :                 }
     430             :                 return GF_EOS;
     431             :         }
     432             :         return GF_OK;
     433             : }
     434             : 
     435           7 : GF_Err m2psdmx_initialize(GF_Filter *filter)
     436             : {
     437           7 :         GF_M2PSDmxCtx *ctx = gf_filter_get_udta(filter);
     438           7 :         ctx->streams = gf_list_new();
     439           7 :         return GF_OK;
     440             : }
     441             : 
     442           7 : void m2psdmx_finalize(GF_Filter *filter)
     443             : {
     444           7 :         GF_M2PSDmxCtx *ctx = gf_filter_get_udta(filter);
     445             : 
     446          26 :         while (gf_list_count(ctx->streams)) {
     447          12 :                 M2PSStream *st = gf_list_pop_back(ctx->streams);
     448          12 :                 gf_free(st);
     449             :         }
     450           7 :         gf_list_del(ctx->streams);
     451           7 :         if (ctx->ps) mpeg2ps_close(ctx->ps);
     452           7 : }
     453             : 
     454        3072 : static const char *m2psdmx_probe_data(const u8 *data, u32 size, GF_FilterProbeScore *score)
     455             : {
     456        3072 :         *score = GF_FPROBE_EXT_MATCH;
     457        3072 :         return "mpg|mpeg|vob";
     458             : }
     459             : 
     460             : static const GF_FilterCapability M2PSDmxCaps[] =
     461             : {
     462             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
     463             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "mpg|mpeg|vob"),
     464             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "video/mpeg|audio/mpeg"),
     465             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     466             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
     467             :         CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
     468             : };
     469             : 
     470             : 
     471             : 
     472             : GF_FilterRegister M2PSDmxRegister = {
     473             :         .name = "m2psdmx",
     474             :         GF_FS_SET_DESCRIPTION("MPEG PS demuxer")
     475             :         GF_FS_SET_HELP("This filter demultiplexes MPEG-2 program stream files/data to produce media PIDs and frames.")
     476             :         .private_size = sizeof(GF_M2PSDmxCtx),
     477             :         .initialize = m2psdmx_initialize,
     478             :         .finalize = m2psdmx_finalize,
     479             :         SETCAPS(M2PSDmxCaps),
     480             :         .configure_pid = m2psdmx_configure_pid,
     481             :         .process = m2psdmx_process,
     482             :         .process_event = m2psdmx_process_event,
     483             :         .probe_data = m2psdmx_probe_data,
     484             :         //this filter is not very reliable, prefer ffmpeg when available
     485             :         .priority = 255
     486             : };
     487             : 
     488             : #endif // GPAC_DISABLE_MPEG2PS
     489             : 
     490        2877 : const GF_FilterRegister *m2psdmx_register(GF_FilterSession *session)
     491             : {
     492             : #ifndef GPAC_DISABLE_MPEG2PS
     493        2877 :         return &M2PSDmxRegister;
     494             : #else
     495             :         return NULL;
     496             : #endif
     497             : }
     498             : 

Generated by: LCOV version 1.13