LCOV - code coverage report
Current view: top level - filters - dmx_avi.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 223 321 69.5 %
Date: 2021-04-29 23:48:07 Functions: 7 7 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 / AVI 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_AVILIB
      33             : #include <gpac/internal/avilib.h>
      34             : #include <gpac/media_tools.h>
      35             : 
      36             : typedef struct
      37             : {
      38             :         GF_FilterPid *opid;
      39             :         u32 stream_num;
      40             :         Bool in_use;
      41             :         u32 aud_frame, audio_bps, nb_channels, freq;
      42             :         u64 audio_ts, seek_to_ts;
      43             :         Bool audio_done, is_aac, playing, init_play_done;
      44             : } AVIAstream;
      45             : 
      46             : 
      47             : typedef struct
      48             : {
      49             :         //opts
      50             :         GF_Fraction fps;
      51             :         Bool importer;
      52             : 
      53             :         GF_FilterPid *ipid;
      54             : 
      55             :         GF_FilterPid *v_opid;
      56             :         Bool v_in_use;
      57             :         u32 nb_frames, cur_frame, nb_frame_sent;
      58             :         u32 dummy, nvops;
      59             :         const char *src_url;
      60             :         avi_t *avi;
      61             : 
      62             :         Bool use_file_fps;
      63             :         GF_Fraction64 duration;
      64             :         Bool v_playing;
      65             :         Bool v_init_play_done;
      66             : 
      67             :         GF_List *audios;
      68             : } GF_AVIDmxCtx;
      69             : 
      70             : 
      71          11 : static void avidmx_setup(GF_Filter *filter, GF_AVIDmxCtx *ctx)
      72             : {
      73             :         u32 sync_id = 0;
      74             :         u32 codecid = 0;
      75             :         Bool unframed;
      76             :         u32 i, count, pfmt=0;
      77             :         GF_Fraction64 dur;
      78             :         char *comp;
      79             : 
      80          11 :         if (ctx->use_file_fps) {
      81          11 :                 Double fps = AVI_frame_rate(ctx->avi);
      82          11 :                 gf_media_get_video_timing(fps, &ctx->fps.num, &ctx->fps.den);
      83             :         }
      84             : 
      85          11 :         dur.den = ctx->fps.num;
      86          11 :         dur.num = (u64) (ctx->fps.den * AVI_video_frames(ctx->avi));
      87             : 
      88             :         unframed = GF_TRUE;
      89          11 :         comp = AVI_video_compressor(ctx->avi);
      90          11 :         if (!comp) {
      91           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Cannot retrieve video compressor name, ignoring video stream\n"));
      92             :         }
      93             :         /*these are/should be OK*/
      94          11 :         else if (!stricmp(comp, "DIVX") || !stricmp(comp, "DX50")   /*DivX*/
      95          11 :                 || !stricmp(comp, "XVID") /*XviD*/
      96           1 :                 || !stricmp(comp, "3iv2") /*3ivX*/
      97           1 :                 || !stricmp(comp, "fvfw") /*ffmpeg*/
      98           1 :                 || !stricmp(comp, "NDIG") /*nero*/
      99           1 :                 || !stricmp(comp, "MP4V") /*!! not tested*/
     100           1 :                 || !stricmp(comp, "M4CC") /*Divio - not tested*/
     101           1 :                 || !stricmp(comp, "PVMM") /*PacketVideo - not tested*/
     102           1 :                 || !stricmp(comp, "SEDG") /*Samsung - not tested*/
     103           1 :                 || !stricmp(comp, "RMP4") /*Sigma - not tested*/
     104           1 :                 || !stricmp(comp, "MP43") /*not tested*/
     105           1 :                 || !stricmp(comp, "FMP4") /*not tested*/
     106           1 :                 || !stricmp(comp, "VP6F") /*not tested*/
     107             :         ) {
     108             :                 codecid = GF_CODECID_MPEG4_PART2;
     109           1 :         } else if ( !stricmp(comp, "H264") /*not tested*/
     110           1 :                 || !stricmp(comp, "X264") /*not tested*/
     111             :         ) {
     112             :                 codecid = GF_CODECID_AVC;
     113           1 :         } else if ( !stricmp(comp, "avc1") ) {
     114             :                 codecid = GF_CODECID_AVC;
     115             :                 unframed = GF_FALSE;
     116           1 :         } else if (!stricmp(comp, "DIV3") || !stricmp(comp, "DIV4")) {
     117           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Video format %s not compliant with MPEG-4 Visual - please recompress the file first\n", comp));
     118           1 :         } else if (!comp[0]) {
     119             :                 codecid = GF_CODECID_RAW;
     120             :                 pfmt = GF_PIXEL_BGR;
     121             :         } else {
     122           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Video format %s not supported, patch welcome\n", comp));
     123             :         }
     124             : 
     125          11 :         ctx->v_in_use = GF_FALSE;
     126          11 :         if (codecid) {
     127             :                 u32 w, h;
     128          11 :                 if (!ctx->v_opid) {
     129          11 :                         ctx->v_opid = gf_filter_pid_new(filter);
     130             :                 }
     131          11 :                 ctx->nb_frames = (u32) AVI_video_frames(ctx->avi);
     132          11 :                 ctx->cur_frame = 0;
     133             :                 sync_id = 1;
     134          11 :                 ctx->v_in_use = GF_TRUE;
     135             : 
     136          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_VISUAL) );
     137          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_CODECID, &PROP_UINT(codecid) );
     138          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(ctx->fps.num) );
     139             : 
     140          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_ID, &PROP_UINT( sync_id) );
     141          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_CLOCK_ID, &PROP_UINT( sync_id ) );
     142          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_FPS, &PROP_FRAC( ctx->fps ) );
     143          11 :                 w = AVI_video_width(ctx->avi);
     144          11 :                 h = AVI_video_height(ctx->avi);
     145          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_WIDTH, &PROP_UINT( w ) );
     146          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_HEIGHT, &PROP_UINT( h ) );
     147          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_DURATION, &PROP_FRAC64( dur ) );
     148             : 
     149          11 :                 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD ) );
     150             : 
     151          11 :                 if (pfmt) {
     152           1 :                         u32 stride=0;
     153           1 :                         gf_pixel_get_size_info(pfmt, w, h, NULL, &stride, NULL, NULL, NULL);
     154           1 :                         gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_STRIDE, &PROP_UINT( stride ) );
     155           1 :                         gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_PIXFMT, &PROP_UINT( pfmt ) );
     156          10 :                 } else if (unframed) {
     157          10 :                         gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL(GF_TRUE) );
     158          10 :                         gf_filter_pid_set_property_str(ctx->v_opid, "nocts", &PROP_BOOL( GF_TRUE ) );
     159           0 :                 } else if (ctx->avi->extradata_size && ctx->avi->extradata) {
     160           0 :                         gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA(ctx->avi->extradata, ctx->avi->extradata_size) );
     161             : 
     162             :                 }
     163             :         }
     164             : 
     165             :         unframed = GF_FALSE;
     166          11 :         count = AVI_audio_tracks(ctx->avi);
     167          14 :         for (i=0; i<count; i++) {
     168             :                 u32 a_fmt, afmt=0, nb_bits;
     169           3 :                 AVI_set_audio_track(ctx->avi, i);
     170             : 
     171             :                 codecid = 0;
     172           3 :                 a_fmt = AVI_audio_format(ctx->avi);
     173           3 :                 nb_bits = AVI_audio_bits(ctx->avi);
     174           3 :                 switch (a_fmt) {
     175           1 :                 case WAVE_FORMAT_PCM:
     176             :                 case GF_4CC('P','C','M',' '):
     177             :                         codecid = GF_CODECID_RAW;
     178           1 :                         switch (nb_bits) {
     179             :                         case 8:
     180             :                                 afmt = GF_AUDIO_FMT_U8;
     181             :                                 break;
     182           1 :                         case 16:
     183             :                                 afmt = GF_AUDIO_FMT_S16;
     184           1 :                                 break;
     185           0 :                         case 24:
     186             :                                 afmt = GF_AUDIO_FMT_S24;
     187           0 :                                 break;
     188           0 :                         case 32:
     189             :                                 afmt = GF_AUDIO_FMT_S32;
     190           0 :                                 break;
     191           0 :                         default:
     192           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Audio bit depth %d not mapped, patch welcome\n", nb_bits));
     193             :                                 afmt = GF_AUDIO_FMT_S16;
     194             :                                 break;
     195             :                         }
     196             :                         break;
     197             :                 case WAVE_FORMAT_ADPCM:
     198             :                         codecid = GF_CODECID_ADPCM;
     199             :                         break;
     200           0 :                 case WAVE_FORMAT_IBM_CVSD:
     201             :                         codecid = GF_CODECID_IBM_CVSD;
     202           0 :                         break;
     203           0 :                 case WAVE_FORMAT_ALAW:
     204             :                         codecid = GF_CODECID_ALAW;
     205           0 :                         break;
     206           0 :                 case WAVE_FORMAT_MULAW:
     207             :                         codecid = GF_CODECID_MULAW;
     208           0 :                         break;
     209           0 :                 case WAVE_FORMAT_OKI_ADPCM:
     210             :                         codecid = GF_CODECID_OKI_ADPCM;
     211           0 :                         break;
     212           0 :                 case WAVE_FORMAT_DVI_ADPCM:
     213             :                         codecid = GF_CODECID_DVI_ADPCM;
     214           0 :                         break;
     215           0 :                 case WAVE_FORMAT_DIGISTD:
     216             :                         codecid = GF_CODECID_DIGISTD;
     217           0 :                         break;
     218           0 :                 case WAVE_FORMAT_YAMAHA_ADPCM:
     219             :                         codecid = GF_CODECID_YAMAHA_ADPCM;
     220           0 :                         break;
     221           0 :                 case WAVE_FORMAT_DSP_TRUESPEECH:
     222             :                         codecid = GF_CODECID_DSP_TRUESPEECH;
     223           0 :                         break;
     224           0 :                 case WAVE_FORMAT_GSM610:
     225             :                         codecid = GF_CODECID_GSM610;
     226           0 :                         break;
     227           0 :                 case IBM_FORMAT_MULAW:
     228             :                         codecid = GF_CODECID_IBM_MULAW;
     229           0 :                         break;
     230           0 :                 case IBM_FORMAT_ALAW:
     231             :                         codecid = GF_CODECID_IBM_ALAW;
     232           0 :                         break;
     233           0 :                 case IBM_FORMAT_ADPCM:
     234             :                         codecid = GF_CODECID_IBM_ADPCM;
     235           0 :                         break;
     236           2 :                 case WAVE_FORMAT_MP3:
     237             :                         codecid = GF_CODECID_MPEG_AUDIO;
     238             :                         unframed = GF_TRUE;
     239           2 :                         break;
     240           0 :                 case WAVE_FORMAT_AAC_ADTS:
     241             :                         codecid = GF_CODECID_AAC_MPEG4;
     242             :                         unframed = GF_TRUE;
     243           0 :                         break;
     244           0 :                 case WAVE_FORMAT_AAC:
     245             :                         codecid = GF_CODECID_AAC_MPEG4;
     246           0 :                         break;
     247           0 :                 case WAVE_FORMAT_AC3:
     248             :                         codecid = GF_CODECID_AC3;
     249           0 :                         break;
     250           0 :                 default:
     251           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Audio format %d not supported, patch welcome\n", a_fmt));
     252             :                         break;
     253             :                 }
     254             : 
     255           3 :                 if (codecid) {
     256             :                         AVIAstream *st = NULL;
     257           3 :                         u32 brate, j, c  = gf_list_count(ctx->audios);
     258           3 :                         for (j=0; j<c; j++) {
     259           0 :                                 st = gf_list_get(ctx->audios, j);
     260           0 :                                 if (!st->in_use) break;
     261             :                                 st = NULL;
     262             :                         }
     263           3 :                         if (!st) {
     264           3 :                                 GF_SAFEALLOC(st, AVIAstream);
     265           3 :                                 if (!st) continue;
     266           3 :                                 st->opid = gf_filter_pid_new(filter);
     267           3 :                                 gf_list_add(ctx->audios, st);
     268             :                         }
     269           3 :                         st->in_use = GF_TRUE;
     270           3 :                         st->stream_num = i;
     271           3 :                         if (!sync_id) sync_id = 2 + st->stream_num;
     272           3 :                         st->audio_done = GF_FALSE;
     273             : 
     274           3 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_AUDIO) );
     275           3 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_CODECID, &PROP_UINT( codecid) );
     276           3 :                         st->freq = AVI_audio_rate(ctx->avi);
     277           3 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT( st->freq ) );
     278           3 :                         st->nb_channels = AVI_audio_channels(ctx->avi);
     279           3 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT( st->nb_channels ) );
     280           3 :                         brate = AVI_audio_mp3rate(ctx->avi);
     281             :                         //for mp3 and aac
     282           3 :                         if (brate && (unframed || (codecid == GF_CODECID_AAC_MPEG4)))
     283           2 :                                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_BITRATE, &PROP_UINT( brate ) );
     284           3 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_ID, &PROP_UINT( 2 + st->stream_num) );
     285           3 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_CLOCK_ID, &PROP_UINT( sync_id ) );
     286           3 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_DURATION, &PROP_FRAC64( dur ) );
     287             : 
     288           3 :                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD ) );
     289           3 :                         st->audio_bps = 0;
     290           3 :                         if (unframed) {
     291           2 :                                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL( GF_TRUE ) );
     292             :                                 //we don't set timescale, let the reframer handle it
     293             :                         } else {
     294           1 :                                 if (afmt) {
     295           1 :                                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(afmt) );
     296             :                                 }
     297           1 :                                 st->audio_bps = AVI_audio_bits(ctx->avi);
     298           1 :                                 gf_filter_pid_set_property(st->opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(st->freq) );
     299             : 
     300           1 :                                 if (codecid == GF_CODECID_AAC_MPEG4) {
     301             : #ifndef GPAC_DISABLE_AV_PARSERS
     302             :                                         GF_M4ADecSpecInfo acfg;
     303           0 :                                         u8 *dsi=NULL;
     304           0 :                                         u32 dsi_len=0;
     305             :                                         memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo));
     306           0 :                                         acfg.base_object_type = GF_M4A_AAC_LC;
     307           0 :                                         acfg.base_sr = st->freq;
     308           0 :                                         acfg.nb_chan = st->nb_channels;
     309             :                                         acfg.sbr_object_type = 0;
     310           0 :                                         acfg.audioPL = gf_m4a_get_profile(&acfg);
     311           0 :                                         gf_m4a_write_config(&acfg, &dsi, &dsi_len);
     312           0 :                                         gf_filter_pid_set_property(st->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_len) );
     313             : #endif
     314           0 :                                         st->audio_bps = 0;
     315           0 :                                         st->is_aac = GF_TRUE;
     316             :                                 }
     317             :                         }
     318             : 
     319             :                 }
     320             :         }
     321          11 : }
     322             : 
     323          11 : GF_Err avidmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     324             : {
     325             :         const GF_PropertyValue *p;
     326          11 :         GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
     327             : 
     328          11 :         if (is_remove) {
     329           0 :                 ctx->ipid = NULL;
     330           0 :                 if (ctx->v_opid) {
     331           0 :                         gf_filter_pid_remove(ctx->v_opid);
     332           0 :                         ctx->v_opid = NULL;
     333             :                 }
     334           0 :                 while (gf_list_count(ctx->audios) ) {
     335           0 :                         AVIAstream *st = gf_list_pop_back(ctx->audios);
     336           0 :                         if (st->opid)
     337           0 :                                 gf_filter_pid_remove(st->opid);
     338           0 :                         gf_free(st);
     339             :                 }
     340             :                 return GF_OK;
     341             :         }
     342          11 :         if (! gf_filter_pid_check_caps(pid))
     343             :                 return GF_NOT_SUPPORTED;
     344             : 
     345          11 :         if (!ctx->ipid) {
     346             :                 GF_FilterEvent fevt;
     347          11 :                 ctx->ipid = pid;
     348             : 
     349             :                 //we work with full file only, send a play event on source to indicate that
     350          11 :                 GF_FEVT_INIT(fevt, GF_FEVT_PLAY, pid);
     351             :                 fevt.play.start_range = 0;
     352          11 :                 fevt.base.on_pid = ctx->ipid;
     353          11 :                 fevt.play.full_file_only = GF_TRUE;
     354          11 :                 gf_filter_pid_send_event(ctx->ipid, &fevt);
     355             :         }
     356             : 
     357          11 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILEPATH);
     358          11 :         if (!p) return GF_NOT_SUPPORTED;
     359             : 
     360          11 :         if (ctx->src_url && !strcmp(ctx->src_url, p->value.string)) return GF_OK;
     361             : 
     362          11 :         if (ctx->avi) {
     363             :                 u32 i;
     364           0 :                 AVI_close(ctx->avi);
     365           0 :                 ctx->v_in_use = GF_FALSE;
     366           0 :                 for (i=0; i<gf_list_count(ctx->audios); i++) {
     367           0 :                         AVIAstream *st = gf_list_get(ctx->audios, i);
     368           0 :                         st->in_use = GF_FALSE;
     369             :                 }
     370             :         }
     371          11 :         ctx->avi = NULL;
     372             : 
     373          11 :         ctx->src_url = p->value.string;
     374             : 
     375          11 :         return GF_OK;
     376             : }
     377             : 
     378        3117 : static Bool avidmx_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
     379             : {
     380        3117 :         GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
     381             : 
     382        3117 :         switch (evt->base.type) {
     383          14 :         case GF_FEVT_PLAY:
     384          14 :                 gf_filter_post_process_task(filter);
     385          14 :                 if (evt->base.on_pid==ctx->v_opid) {
     386             :                         u32 frame_idx = 0;
     387          11 :                         ctx->v_playing = GF_TRUE;
     388          11 :                         if ((evt->play.start_range==0) && !ctx->v_init_play_done) {
     389          11 :                                 ctx->v_init_play_done = GF_TRUE;
     390          11 :                                 return GF_TRUE;
     391             :                         }
     392           0 :                         ctx->v_init_play_done = GF_TRUE;
     393           0 :                         frame_idx = (u32) (ctx->avi->fps * evt->play.start_range);
     394           0 :                         if (frame_idx) {
     395           0 :                                 AVI_set_video_position(ctx->avi, frame_idx);
     396             :                         } else {
     397           0 :                                 AVI_seek_start(ctx->avi);
     398           0 :                                 gf_filter_post_process_task(filter);
     399             :                         }
     400           0 :                         ctx->cur_frame = frame_idx;
     401             :                 } else {
     402             :                         u32 i;
     403           0 :                         for (i=0; i<gf_list_count(ctx->audios); i++) {
     404           3 :                                 AVIAstream *st = gf_list_get(ctx->audios, i);
     405           3 :                                 if (st->opid != evt->base.on_pid) continue;
     406           3 :                                 st->playing = GF_TRUE;
     407           3 :                                 if ((evt->play.start_range==0) && !st->init_play_done) {
     408           3 :                                         st->init_play_done = GF_TRUE;
     409           3 :                                         return GF_TRUE;
     410             :                                 }
     411           0 :                                 st->init_play_done = GF_TRUE;
     412           0 :                                 AVI_set_audio_position(ctx->avi, 0);
     413           0 :                                 st->seek_to_ts = (u32) (evt->play.start_range * st->freq);
     414             :                         }
     415             :                 }
     416             : 
     417             :                 //cancel play event, we work with full file
     418             :                 return GF_TRUE;
     419             : 
     420           4 :         case GF_FEVT_STOP:
     421           4 :                 if (evt->base.on_pid==ctx->v_opid) {
     422           4 :                         ctx->v_playing = GF_FALSE;
     423             :                 } else {
     424             :                         u32 i;
     425           0 :                         for (i=0; i<gf_list_count(ctx->audios); i++) {
     426           0 :                                 AVIAstream *st = gf_list_get(ctx->audios, i);
     427           0 :                                 if (st->opid != evt->base.on_pid) continue;
     428           0 :                                 st->playing = GF_TRUE;
     429             :                         }
     430             :                 }
     431             :                 //don't cancel event
     432             :                 return GF_FALSE;
     433             : 
     434             :         case GF_FEVT_SET_SPEED:
     435             :                 //cancel event
     436             :                 return GF_TRUE;
     437             :         default:
     438             :                 break;
     439             :         }
     440             :         //by default don't cancel event - to rework once we have downloading in place
     441        3099 :         return GF_FALSE;
     442             : }
     443             : 
     444        5763 : GF_Err avidmx_process(GF_Filter *filter)
     445             : {
     446        5763 :         GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
     447             :         u32 i, count, nb_done, nb_active=0;
     448             :         Bool start, end, video_done;
     449             : 
     450        5763 :         if (!ctx->avi) {
     451        3099 :                 GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
     452        3099 :                 if (!pck) {
     453             :                         return GF_OK;
     454             :                 }
     455        3099 :                 gf_filter_pck_get_framing(pck, &start, &end);
     456        3099 :                 gf_filter_pid_drop_packet(ctx->ipid);
     457             : 
     458        3099 :                 if (!end) {
     459             :                         return GF_OK;
     460             :                 }
     461             : 
     462          11 :                 ctx->avi = AVI_open_input_file((char *)ctx->src_url, 1);
     463          11 :                 if (!ctx->avi) {
     464             :                         GF_Err e = GF_NON_COMPLIANT_BITSTREAM;
     465           0 :                         if (! gf_file_exists(ctx->src_url)) e = GF_URL_ERROR;
     466           0 :                         gf_filter_setup_failure(filter, e);
     467           0 :                         return GF_NOT_SUPPORTED;
     468             :                 }
     469          11 :                 avidmx_setup(filter, ctx);
     470          11 :                 return GF_OK;
     471             :         }
     472             :         video_done = GF_FALSE;
     473        4849 :         if (ctx->v_in_use && ctx->v_playing && (ctx->cur_frame < ctx->nb_frames) && !gf_filter_pid_would_block(ctx->v_opid) ) {
     474             :                 u32 key;
     475             :                 u64 file_offset, cts;
     476             :                 u8 *pck_data;
     477        2185 :                 s32 size = AVI_frame_size(ctx->avi, ctx->cur_frame);
     478        2185 :                 if (!size) {
     479           0 :                         AVI_read_frame(ctx->avi, NULL, &key);
     480           0 :                         ctx->dummy++;
     481             :                 }
     482             :                 //remove dummy frames
     483             :                 else {
     484        2185 :                         file_offset = (u64) AVI_get_video_position(ctx->avi, ctx->cur_frame);
     485        2185 :                         cts = ctx->nb_frame_sent * ctx->fps.den;
     486             : 
     487        2185 :                         if (size > 4) {
     488        2180 :                                 GF_FilterPacket *dst_pck = gf_filter_pck_new_alloc(ctx->v_opid, size, &pck_data);
     489        2180 :                                 if (!dst_pck) return GF_OUT_OF_MEM;
     490        2180 :                                 AVI_read_frame(ctx->avi, pck_data, &key);
     491        2180 :                                 gf_filter_pck_set_byte_offset(dst_pck, file_offset);
     492        2180 :                                 gf_filter_pck_set_cts(dst_pck, cts);
     493        2180 :                                 gf_filter_pck_set_duration(dst_pck, ctx->fps.den);
     494        2180 :                                 gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
     495        2180 :                                 if (key) gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
     496        2180 :                                 gf_filter_pck_send(dst_pck);
     497        2180 :                                 ctx->nb_frame_sent++;
     498             :                         } else {
     499           5 :                                 AVI_read_frame(ctx->avi, NULL, &key);
     500           5 :                                 ctx->nvops++;
     501             :                         }
     502             :                 }
     503             :                 nb_active++;
     504             : 
     505        2185 :                 ctx->cur_frame++;
     506        2185 :                 if (ctx->cur_frame < ctx->nb_frames)
     507        2178 :                         gf_filter_post_process_task(filter);
     508             :                 else
     509             :                         video_done = GF_TRUE;
     510         479 :         } else if (!ctx->v_in_use) {
     511             :                 video_done = GF_TRUE;
     512         479 :         } else if (ctx->cur_frame >= ctx->nb_frames) {
     513             :                 video_done = GF_TRUE;
     514             :         }
     515             :         
     516             :         nb_done = 0;
     517        2664 :         count = gf_list_count(ctx->audios);
     518        3825 :         for (i=0; i<count; i++) {
     519             :                 s32 size;
     520        1161 :                 AVIAstream *st = gf_list_get(ctx->audios, i);
     521        1161 :                 if (st->audio_done || !st->in_use) {
     522           0 :                         nb_done++;
     523           0 :                         continue;
     524             :                 }
     525        1161 :                 if (!st->playing || gf_filter_pid_would_block(st->opid) )
     526           3 :                         continue;
     527        1158 :                 AVI_set_audio_track(ctx->avi, st->stream_num);
     528        1158 :                 nb_active++;
     529             : 
     530        1158 :                 size = AVI_audio_size(ctx->avi, st->aud_frame);
     531             : 
     532        1158 :                 if (st->seek_to_ts && size) {
     533           0 :                         if (st->seek_to_ts > st->audio_ts) {
     534           0 :                                 st->aud_frame ++;
     535           0 :                                 continue;
     536             :                         }
     537             :                         else
     538           0 :                                 st->seek_to_ts = 0;
     539             :                 }
     540             : 
     541        1158 :                 if (size>0) {
     542             :                         int continuous;
     543             :                         u8 *pck_data;
     544             :                         u64 file_offset;
     545        1155 :                         GF_FilterPacket *dst_pck = gf_filter_pck_new_alloc(st->opid, size, &pck_data);
     546        1155 :                         if (!dst_pck) return GF_OUT_OF_MEM;
     547             :                         
     548        1155 :                         file_offset = gf_ftell(ctx->avi->fdes);
     549        1155 :                         AVI_read_audio(ctx->avi, pck_data, size, (int*)&continuous);
     550             : 
     551        1155 :                         if (st->audio_bps) {
     552         385 :                                 u32 nb_samples = (8*size) / (st->audio_bps * st->nb_channels);
     553         385 :                                 gf_filter_pck_set_cts(dst_pck, st->audio_ts);
     554         385 :                                 gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
     555         385 :                                 st->audio_ts += nb_samples;
     556         770 :                         } else if (st->is_aac) {
     557           0 :                                 gf_filter_pck_set_cts(dst_pck, st->audio_ts);
     558           0 :                                 gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
     559           0 :                                 st->audio_ts += 1024;
     560             :                         }
     561             : 
     562        1155 :                         if (continuous)
     563           3 :                                 gf_filter_pck_set_byte_offset(dst_pck, file_offset);
     564             : 
     565        1155 :                         gf_filter_pck_send(dst_pck);
     566             : 
     567        1155 :                         st->aud_frame ++;
     568             :                 } else {
     569           3 :                         st->audio_done = GF_TRUE;
     570           3 :                         nb_done++;
     571             :                 }
     572             :         }
     573        2664 :         if (!nb_active)
     574             :                 return GF_OK;
     575        2593 :         if (video_done && (nb_done==count) ) {
     576           7 :                 if (ctx->v_opid && ctx->v_in_use) gf_filter_pid_set_eos(ctx->v_opid);
     577             : 
     578           3 :                 for (i=0; i<count;i++) {
     579           3 :                         AVIAstream *st = gf_list_get(ctx->audios, i);
     580           3 :                         gf_filter_pid_set_eos(st->opid);
     581             :                 }
     582             :                 return GF_EOS;
     583             :         }
     584        2586 :         gf_filter_post_process_task(filter);
     585        2586 :         return GF_OK;
     586             : }
     587             : 
     588          11 : GF_Err avidmx_initialize(GF_Filter *filter)
     589             : {
     590          11 :         GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
     591          11 :         ctx->use_file_fps = ctx->fps.den ? GF_FALSE : GF_TRUE;
     592          11 :         ctx->audios = gf_list_new();
     593          11 :         return GF_OK;
     594             : }
     595             : 
     596          11 : void avidmx_finalize(GF_Filter *filter)
     597             : {
     598          11 :         GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
     599          11 :         if (ctx->avi) AVI_close(ctx->avi);
     600          14 :         while (gf_list_count(ctx->audios)) {
     601           3 :                 AVIAstream *st = gf_list_pop_back(ctx->audios);
     602           3 :                 gf_free(st);
     603             :         }
     604          11 :         gf_list_del(ctx->audios);
     605             : 
     606          11 :         if (ctx->importer) {
     607           4 :                 GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("AVI Removed Frames: 1 VFW delay frames - 296 N-VOPs\n", ctx->dummy, ctx->nvops));
     608             :         }
     609             : 
     610          11 : }
     611             : 
     612             : 
     613             : static const GF_FilterCapability AVIDmxCaps[] =
     614             : {
     615             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
     616             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "avi"),
     617             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "video/avi|video/x-avi"),
     618             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     619             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
     620             : };
     621             : 
     622             : 
     623             : #define OFFS(_n)        #_n, offsetof(GF_AVIDmxCtx, _n)
     624             : static const GF_FilterArgs AVIDmxArgs[] =
     625             : {
     626             :         { OFFS(fps), "import frame rate, default is AVI one", GF_PROP_FRACTION, "1/0", NULL, 0},
     627             :         { OFFS(importer), "compatibility with old importer, displays import results", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
     628             :         {0}
     629             : };
     630             : 
     631             : 
     632             : GF_FilterRegister AVIDmxRegister = {
     633             :         .name = "avidmx",
     634             :         GF_FS_SET_DESCRIPTION("AVI demuxer")
     635             :         GF_FS_SET_HELP("This filter demultiplexes AVI files/data to produce media PIDs and frames.")
     636             :         .private_size = sizeof(GF_AVIDmxCtx),
     637             :         .initialize = avidmx_initialize,
     638             :         .finalize = avidmx_finalize,
     639             :         .args = AVIDmxArgs,
     640             :         SETCAPS(AVIDmxCaps),
     641             :         .configure_pid = avidmx_configure_pid,
     642             :         .process = avidmx_process,
     643             :         .process_event = avidmx_process_event,
     644             : };
     645             : 
     646             : #endif // GPAC_DISABLE_AVILIB
     647             : 
     648        2877 : const GF_FilterRegister *avidmx_register(GF_FilterSession *session)
     649             : {
     650             : #ifndef GPAC_DISABLE_AVILIB
     651        2877 :         return &AVIDmxRegister;
     652             : #else
     653             :         return NULL;
     654             : #endif
     655             : }
     656             : 

Generated by: LCOV version 1.13