LCOV - code coverage report
Current view: top level - filters - reframe_adts.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 385 456 84.4 %
Date: 2021-04-29 23:48:07 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / AAC ADTS reframer 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/avparse.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/filters.h>
      29             : 
      30             : #ifndef GPAC_DISABLE_AV_PARSERS
      31             : 
      32             : enum
      33             : {
      34             :         AAC_SIGNAL_NONE=0,
      35             :         AAC_SIGNAL_IMPLICIT,
      36             :         AAC_SIGNAL_EXPLICIT
      37             : };
      38             : 
      39             : typedef struct
      40             : {
      41             :         Bool is_mp2, no_crc;
      42             :         u32 profile, sr_idx, nb_ch, frame_size, hdr_size;
      43             : } ADTSHeader;
      44             : 
      45             : typedef struct
      46             : {
      47             :         u64 pos;
      48             :         Double duration;
      49             : } ADTSIdx;
      50             : 
      51             : typedef struct
      52             : {
      53             :         //filter args
      54             :         u32 frame_size;
      55             :         Double index;
      56             :         u32 sbr;
      57             :         u32 ps;
      58             : //      Bool mpeg4;
      59             :         Bool ovsbr;
      60             :         Bool expart;
      61             :         s32 aacchcfg;
      62             : 
      63             :         //only one input pid declared
      64             :         GF_FilterPid *ipid;
      65             :         //output pid for audio
      66             :         GF_FilterPid *opid;
      67             : 
      68             :         //video pid for cover art
      69             :         GF_FilterPid *vpid;
      70             : 
      71             :         GF_BitStream *bs;
      72             :         u64 file_pos, cts;
      73             :         u32 sr_idx, nb_ch, is_mp2, profile;
      74             :         GF_Fraction64 duration;
      75             :         Double start_range;
      76             :         Bool in_seek;
      77             :         u32 timescale;
      78             : 
      79             :         ADTSHeader hdr;
      80             :         u32 dts_inc;
      81             : 
      82             :         Bool is_playing;
      83             :         Bool is_file, file_loaded;
      84             :         Bool initial_play_done;
      85             : 
      86             :         GF_FilterPacket *src_pck;
      87             : 
      88             :         ADTSIdx *indexes;
      89             :         u32 index_alloc_size, index_size;
      90             : 
      91             :         u8 *adts_buffer;
      92             :         u32 adts_buffer_size, adts_buffer_alloc, resume_from;
      93             :         u64 byte_offset;
      94             : 
      95             :         u32 tag_size;
      96             :         u8 *id3_buffer;
      97             :         u32 id3_buffer_size, id3_buffer_alloc;
      98             :         u32 nb_frames;
      99             : 
     100             :         GF_M4ADecSpecInfo acfg;
     101             :         u32 bitrate;
     102             : } GF_ADTSDmxCtx;
     103             : 
     104             : 
     105       29200 : static Bool adts_dmx_sync_frame_bs(GF_BitStream *bs, ADTSHeader *hdr)
     106             : {
     107             :         u32 val;
     108             :         u64 pos;
     109             : 
     110     8246856 :         while (gf_bs_available(bs)>7) {
     111             :                 u32 nb_blocks_per_frame;
     112     8215565 :                 val = gf_bs_read_u8(bs);
     113     8215565 :                 if (val!=0xFF) continue;
     114      206670 :                 val = gf_bs_read_int(bs, 4);
     115      206670 :                 if (val != 0x0F) {
     116      106506 :                         gf_bs_read_int(bs, 4);
     117      106506 :                         continue;
     118             :                 }
     119      100164 :                 hdr->is_mp2 = (Bool)gf_bs_read_int(bs, 1);
     120      100164 :                 gf_bs_read_int(bs, 2);
     121      100164 :                 hdr->no_crc = (Bool)gf_bs_read_int(bs, 1);
     122      100164 :                 pos = gf_bs_get_position(bs) - 2;
     123             : 
     124      100164 :                 hdr->profile = 1 + gf_bs_read_int(bs, 2);
     125      100164 :                 hdr->sr_idx = gf_bs_read_int(bs, 4);
     126      100164 :                 gf_bs_read_int(bs, 1);
     127      100164 :                 hdr->nb_ch = gf_bs_read_int(bs, 3);
     128             :                 //value 1->6 match channel number, value 7 is 7.1
     129      100164 :                 if (hdr->nb_ch==7)
     130       60801 :                         hdr->nb_ch = 8;
     131             : 
     132      100164 :                 gf_bs_read_int(bs, 4);
     133      100164 :                 hdr->frame_size = gf_bs_read_int(bs, 13);
     134      100164 :                 gf_bs_read_int(bs, 11);
     135             : 
     136      100164 :                 nb_blocks_per_frame = gf_bs_read_int(bs, 2);
     137      100164 :                 hdr->hdr_size = 7;
     138             : 
     139      100164 :                 if ((!hdr->nb_ch && (nb_blocks_per_frame<2)) || (nb_blocks_per_frame>2)) {
     140       63574 :                         hdr->frame_size = 0;
     141       63574 :                         gf_bs_seek(bs, pos+1);
     142       63574 :                         continue;
     143             :                 }
     144             : 
     145       36590 :                 if (!hdr->no_crc) {
     146             :                         u32 skip;
     147        2178 :                         if (!nb_blocks_per_frame) {
     148             :                                 skip = 2;
     149             :                         } else {
     150        1735 :                                 skip = 2 + 2*nb_blocks_per_frame; //and we have 2 bytes per raw_data_block
     151             :                         }
     152        2178 :                         hdr->hdr_size += skip;
     153        2178 :                         gf_bs_skip_bytes(bs, skip);
     154             :                 }
     155             : 
     156       36590 :                 if (!GF_M4ASampleRates[hdr->sr_idx] || (hdr->frame_size < hdr->hdr_size)) {
     157        8771 :                         hdr->frame_size = 0;
     158        8771 :                         gf_bs_seek(bs, pos+1);
     159        8771 :                         continue;
     160             :                 }
     161       27819 :                 hdr->frame_size -= hdr->hdr_size;
     162             : 
     163       27819 :                 if (gf_bs_available(bs) == hdr->frame_size) {
     164             :                         return GF_TRUE;
     165             :                 }
     166       27773 :                 if (gf_bs_available(bs) < hdr->frame_size) {
     167             :                         break;
     168             :                 }
     169             : 
     170       26904 :                 gf_bs_skip_bytes(bs, hdr->frame_size);
     171       26904 :                 val = gf_bs_read_u8(bs);
     172       26904 :                 if (val!=0xFF) {
     173         709 :                         hdr->frame_size = 0;
     174         709 :                         gf_bs_seek(bs, pos+1);
     175         709 :                         continue;
     176             :                 }
     177       26195 :                 val = gf_bs_read_int(bs, 4);
     178       26195 :                 if (val!=0x0F) {
     179           1 :                         hdr->frame_size = 0;
     180           1 :                         gf_bs_read_int(bs, 4);
     181           1 :                         gf_bs_seek(bs, pos+1);
     182           1 :                         continue;
     183             :                 }
     184       26194 :                 gf_bs_seek(bs, pos+hdr->hdr_size);
     185       26194 :                 return GF_TRUE;
     186             :         }
     187             :         return GF_FALSE;
     188             : }
     189             : 
     190             : void id3dmx_flush(GF_Filter *filter, u8 *id3_buf, u32 id3_buf_size, GF_FilterPid *audio_pid, GF_FilterPid **video_pid_p);
     191             : 
     192             : 
     193         187 : GF_Err adts_dmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     194             : {
     195             :         const GF_PropertyValue *p;
     196         187 :         GF_ADTSDmxCtx *ctx = gf_filter_get_udta(filter);
     197             : 
     198         187 :         if (is_remove) {
     199           0 :                 ctx->ipid = NULL;
     200           0 :                 if (ctx->opid) {
     201           0 :                         gf_filter_pid_remove(ctx->opid);
     202           0 :                         ctx->opid = NULL;
     203             :                 }
     204             :                 return GF_OK;
     205             :         }
     206         187 :         if (! gf_filter_pid_check_caps(pid))
     207             :                 return GF_NOT_SUPPORTED;
     208             : 
     209         187 :         ctx->ipid = pid;
     210         187 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_TIMESCALE);
     211         187 :         if (p) ctx->timescale = p->value.uint;
     212             : 
     213         187 :         if (ctx->timescale && !ctx->opid) {
     214          12 :                 ctx->opid = gf_filter_pid_new(filter);
     215          12 :                 gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
     216          12 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, NULL);
     217             :                 //we don't update copy props on output for now - if we decide we need it, we will need to also force resengin the decoder config
     218             :         }
     219             : 
     220             :         return GF_OK;
     221             : }
     222             : 
     223       11434 : static void adts_dmx_check_dur(GF_Filter *filter, GF_ADTSDmxCtx *ctx)
     224             : {
     225             :         FILE *stream;
     226             :         GF_BitStream *bs;
     227             :         ADTSHeader hdr;
     228             :         u64 duration, cur_dur, rate;
     229             :         s32 sr_idx = -1;
     230             :         const GF_PropertyValue *p;
     231       22819 :         if (!ctx->opid || ctx->timescale || ctx->file_loaded) return;
     232             : 
     233         137 :         if (ctx->index<=0) {
     234          82 :                 ctx->file_loaded = GF_TRUE;
     235             :                 return;
     236             :         }
     237             : 
     238          55 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILEPATH);
     239          55 :         if (!p || !p->value.string || !strncmp(p->value.string, "gmem://", 7)) {
     240           6 :                 ctx->is_file = GF_FALSE;
     241           6 :                 ctx->file_loaded = GF_TRUE;
     242             :                 return;
     243             :         }
     244          49 :         ctx->is_file = GF_TRUE;
     245             : 
     246          49 :         stream = gf_fopen(p->value.string, "rb");
     247          49 :         if (!stream) return;
     248             : 
     249          49 :         ctx->index_size = 0;
     250             : 
     251          49 :         bs = gf_bs_from_file(stream, GF_BITSTREAM_READ);
     252             :         duration = 0;
     253             :         cur_dur = 0;
     254       25265 :         while (adts_dmx_sync_frame_bs(bs, &hdr)) {
     255       25216 :                 if ((sr_idx>=0) && (sr_idx != hdr.sr_idx)) {
     256           0 :                         duration *= GF_M4ASampleRates[hdr.sr_idx];
     257           0 :                         duration /= GF_M4ASampleRates[sr_idx];
     258             : 
     259           0 :                         cur_dur *= GF_M4ASampleRates[hdr.sr_idx];
     260           0 :                         cur_dur /= GF_M4ASampleRates[sr_idx];
     261             :                 }
     262       25216 :                 sr_idx = hdr.sr_idx;
     263       25216 :                 duration += ctx->frame_size;
     264       25216 :                 cur_dur += ctx->frame_size;
     265       25216 :                 if (cur_dur > ctx->index * GF_M4ASampleRates[sr_idx]) {
     266         556 :                         if (!ctx->index_alloc_size) ctx->index_alloc_size = 10;
     267         509 :                         else if (ctx->index_alloc_size == ctx->index_size) ctx->index_alloc_size *= 2;
     268         556 :                         ctx->indexes = gf_realloc(ctx->indexes, sizeof(ADTSIdx)*ctx->index_alloc_size);
     269         556 :                         ctx->indexes[ctx->index_size].pos = gf_bs_get_position(bs) - hdr.hdr_size;
     270         556 :                         ctx->indexes[ctx->index_size].duration = (Double) duration;
     271         556 :                         ctx->indexes[ctx->index_size].duration /= GF_M4ASampleRates[sr_idx];
     272         556 :                         ctx->index_size ++;
     273             :                         cur_dur = 0;
     274             :                 }
     275             : 
     276       25216 :                 gf_bs_skip_bytes(bs, hdr.frame_size);
     277             :         }
     278          49 :         rate = gf_bs_get_position(bs);
     279          49 :         gf_bs_del(bs);
     280          49 :         gf_fclose(stream);
     281             : 
     282          49 :         if (sr_idx>=0) {
     283          49 :                 if (!ctx->duration.num || (ctx->duration.num  * GF_M4ASampleRates[sr_idx] != duration * ctx->duration.den)) {
     284          49 :                         ctx->duration.num = (s32) duration;
     285          49 :                         ctx->duration.den = GF_M4ASampleRates[sr_idx];
     286             : 
     287          49 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DURATION, & PROP_FRAC64(ctx->duration));
     288             : 
     289          49 :                         if (duration && !gf_sys_is_test_mode() ) {
     290           0 :                                 rate *= 8 * ctx->duration.den;
     291           0 :                                 rate /= ctx->duration.num;
     292           0 :                                 ctx->bitrate = (u32) rate;
     293             :                         }
     294             :                 }
     295             :         }
     296             :         
     297          49 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILE_CACHED);
     298          49 :         if (p && p->value.boolean) ctx->file_loaded = GF_TRUE;
     299          49 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CAN_DATAREF, & PROP_BOOL(GF_TRUE ) );
     300             : }
     301             : 
     302       83493 : static void adts_dmx_check_pid(GF_Filter *filter, GF_ADTSDmxCtx *ctx)
     303             : {
     304             :         GF_BitStream *dsi;
     305             :         Bool use_implicit=GF_FALSE;
     306             :         u8 *dsi_b;
     307             :         u32 i, sbr_sr_idx, dsi_s, sr, sbr_sr, codecid, timescale=0;
     308             : 
     309       83493 :         if (!ctx->opid) {
     310         137 :                 ctx->opid = gf_filter_pid_new(filter);
     311         137 :                 gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
     312         137 :                 adts_dmx_check_dur(filter, ctx);
     313             :         }
     314             : 
     315       83493 :         if ((ctx->sr_idx == ctx->hdr.sr_idx) && (ctx->nb_ch == ctx->hdr.nb_ch)
     316      166688 :                 && (ctx->is_mp2 == ctx->hdr.is_mp2) && (ctx->profile == ctx->hdr.profile) ) return;
     317             : 
     318             :         //copy properties at init or reconfig
     319         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, & PROP_UINT( GF_STREAM_AUDIO));
     320         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, & PROP_UINT( GF_CODECID_AAC_MPEG4));
     321         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLES_PER_FRAME, & PROP_UINT(ctx->frame_size) );
     322         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, & PROP_BOOL(GF_FALSE) );
     323         149 :         if (ctx->is_file && ctx->index) {
     324          49 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PLAYBACK_MODE, & PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD) );
     325             :         }
     326             : 
     327         149 :         if (ctx->duration.num)
     328          49 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DURATION, & PROP_FRAC64(ctx->duration));
     329             : 
     330             : 
     331         149 :         ctx->is_mp2 = ctx->hdr.is_mp2;
     332         149 :         ctx->nb_ch = ctx->hdr.nb_ch;
     333         149 :         ctx->profile = ctx->hdr.profile;
     334             : 
     335         149 :         sr = GF_M4ASampleRates[ctx->hdr.sr_idx];
     336         149 :         if (!ctx->timescale) {
     337             :                 //we change sample rate, change cts
     338         137 :                 if (ctx->cts && (ctx->sr_idx != ctx->hdr.sr_idx)) {
     339           0 :                         ctx->cts *= sr;
     340           0 :                         ctx->cts /= GF_M4ASampleRates[ctx->sr_idx];
     341             :                 }
     342             :         }
     343         149 :         ctx->sr_idx = ctx->hdr.sr_idx;
     344             : 
     345             :         /*keep MPEG-2 AAC codecid even for HE-SBR (that's correct according to latest MPEG-4 audio spec)*/
     346         149 :         codecid = ctx->hdr.is_mp2 ? ctx->hdr.profile+GF_CODECID_AAC_MPEG2_MP-1 : GF_CODECID_AAC_MPEG4;
     347         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, & PROP_UINT(codecid) );
     348             : 
     349             :         //force explicit SBR if explicit PS
     350         149 :         if (ctx->ps==AAC_SIGNAL_EXPLICIT) {
     351           3 :                 ctx->sbr = AAC_SIGNAL_EXPLICIT;
     352             :         }
     353             :         /*no provision for explicit indication of MPEG-2 AAC through MPEG-4 PLs, so force implicit*/
     354         149 :         if (ctx->hdr.is_mp2) {
     355           0 :                 if (ctx->sbr == AAC_SIGNAL_EXPLICIT) ctx->sbr = AAC_SIGNAL_IMPLICIT;
     356           0 :                 if (ctx->ps == AAC_SIGNAL_EXPLICIT) ctx->ps = AAC_SIGNAL_IMPLICIT;
     357             :         }
     358             : 
     359         149 :         dsi = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     360         149 :         ctx->dts_inc = ctx->frame_size;
     361             : 
     362         149 :         if (!ctx->ovsbr) {
     363             :                 sbr_sr = 0;
     364             :                 sbr_sr_idx = 0;
     365         132 :                 for (i=0; i<16; i++) {
     366         281 :                         if (GF_M4ASampleRates[i] == (u32) 2*sr) {
     367             :                                 sbr_sr_idx = i;
     368             :                                 sbr_sr = 2*sr;
     369             :                                 break;
     370             :                         }
     371             :                 }
     372             :         } else {
     373             :                 sbr_sr = sr;
     374           0 :                 sbr_sr_idx = ctx->hdr.sr_idx;
     375             :         }
     376             : 
     377         149 :         ctx->acfg.base_object_type = ctx->hdr.profile;
     378         149 :         ctx->acfg.base_sr = sr;
     379         149 :         ctx->acfg.base_sr_index = ctx->hdr.sr_idx;
     380         149 :         ctx->acfg.nb_chan = ctx->hdr.nb_ch;
     381         149 :         ctx->acfg.sbr_object_type = 0;
     382             : 
     383             :         /*explicit PS signal (non backward-compatible), only for stereo ADTS*/
     384         149 :         if  (ctx->acfg.nb_chan<=2) {
     385         141 :                 if (ctx->ps==AAC_SIGNAL_EXPLICIT) {
     386           3 :                         ctx->acfg.base_object_type = 29;
     387           3 :                         ctx->acfg.sbr_object_type = ctx->hdr.profile;
     388           3 :                         ctx->acfg.sbr_sr = sr;
     389           3 :                         ctx->acfg.sbr_sr_index = ctx->acfg.base_sr_index;
     390         138 :                 } else if (ctx->ps==AAC_SIGNAL_IMPLICIT) {
     391             :                         use_implicit = GF_TRUE;
     392             :                 }
     393             :         }
     394             : 
     395         149 :         if (ctx->sbr==AAC_SIGNAL_EXPLICIT) {
     396             :                 //don't overwrite obj type if explicit PS is used
     397           5 :                 if (ctx->acfg.base_object_type != 29)
     398           2 :                         ctx->acfg.base_object_type = 5;
     399           5 :                 ctx->acfg.sbr_object_type = ctx->hdr.profile;
     400           5 :                 ctx->acfg.sbr_sr = sbr_sr;
     401           5 :                 ctx->acfg.sbr_sr_index = sbr_sr_idx;
     402         144 :         } else if (ctx->sbr==AAC_SIGNAL_IMPLICIT) {
     403             :                 sbr_sr = 0;
     404             :                 use_implicit = GF_TRUE;
     405             :         } else {
     406             :                 sbr_sr = 0;
     407             :         }
     408         149 :         ctx->acfg.audioPL = gf_m4a_get_profile(&ctx->acfg);
     409             : 
     410             :         /*for better interop, always store using full SR when using explict signaling*/
     411         149 :         if (sbr_sr) {
     412           5 :                 ctx->dts_inc *= 2;
     413             :                 sr = sbr_sr;
     414             :         }
     415             : 
     416         149 :         gf_m4a_write_config_bs(dsi, &ctx->acfg);
     417         149 :         gf_bs_align(dsi);
     418             : 
     419             :         //implicit signaling, not written by gf_m4a_write_config_bs
     420         149 :         if (use_implicit) {
     421           4 :                 gf_bs_write_int(dsi, 0x2b7, 11); /*sync extension type*/
     422           4 :                 gf_bs_write_int(dsi, 5, 5);     /*audio objectType*/
     423             :                 /*implicit AAC SBR signal*/
     424           4 :                 if (ctx->sbr==AAC_SIGNAL_IMPLICIT) {
     425           2 :                         gf_bs_write_int(dsi, 1, 1);     /*SBR present flag*/
     426           2 :                         gf_bs_write_int(dsi, sbr_sr_idx, 4);
     427             :                 } else {
     428           2 :                         gf_bs_write_int(dsi, 0, 1);     /*SBR present flag*/
     429             :                 }
     430           4 :                 if (ctx->ps==AAC_SIGNAL_IMPLICIT) {
     431           3 :                         gf_bs_write_int(dsi, 0x548, 11); /*sync extension type*/
     432           3 :                         gf_bs_write_int(dsi, 1, 1);     /* PS present flag */
     433             :                 }
     434           4 :                 gf_bs_align(dsi);
     435             :         }
     436             : 
     437         149 :         gf_bs_get_content(dsi, &dsi_b, &dsi_s);
     438         149 :         gf_bs_del(dsi);
     439         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, & PROP_DATA_NO_COPY(dsi_b, dsi_s) );
     440         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PROFILE_LEVEL, & PROP_UINT (ctx->acfg.audioPL) );
     441         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, & PROP_UINT(sr));
     442             : 
     443             :         timescale = sr;
     444         149 :         if (ctx->ovsbr) timescale = 2*sr;
     445             : 
     446         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_TIMESCALE, & PROP_UINT(ctx->timescale ? ctx->timescale : timescale));
     447         149 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, & PROP_UINT(ctx->nb_ch) );
     448             : 
     449         149 :         if (ctx->bitrate) {
     450           0 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_BITRATE, & PROP_UINT(ctx->bitrate));
     451             :         }
     452             : 
     453         149 :         if (ctx->id3_buffer_size) {
     454           0 :                 id3dmx_flush(filter, ctx->id3_buffer, ctx->id3_buffer_size, ctx->opid, ctx->expart ? &ctx->vpid : NULL);
     455           0 :                 ctx->id3_buffer_size = 0;
     456             :         }
     457             : 
     458             : }
     459             : 
     460        6681 : static Bool adts_dmx_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
     461             : {
     462             :         u32 i;
     463             :         GF_FilterEvent fevt;
     464        6681 :         GF_ADTSDmxCtx *ctx = gf_filter_get_udta(filter);
     465             : 
     466        6681 :         switch (evt->base.type) {
     467         154 :         case GF_FEVT_PLAY:
     468         154 :                 if (!ctx->is_playing) {
     469         154 :                         ctx->is_playing = GF_TRUE;
     470         154 :                         ctx->cts = 0;
     471             :                 }
     472         154 :                 ctx->nb_frames = 0;
     473         154 :                 ctx->id3_buffer_size = 0;
     474             : 
     475         154 :                 if (! ctx->is_file) {
     476         100 :                         if (evt->play.start_range || ctx->initial_play_done) {
     477           0 :                                 ctx->adts_buffer_size = 0;
     478           0 :                                 ctx->resume_from = 0;
     479             :                         }
     480             : 
     481         100 :                         ctx->initial_play_done = GF_TRUE;
     482         100 :                         return GF_FALSE;
     483             :                 }
     484          54 :                 ctx->start_range = evt->play.start_range;
     485          54 :                 ctx->in_seek = GF_TRUE;
     486          54 :                 ctx->file_pos = 0;
     487          54 :                 if (ctx->start_range) {
     488           2 :                         for (i=1; i<ctx->index_size; i++) {
     489           3 :                                 if (ctx->indexes[i].duration>ctx->start_range) {
     490           1 :                                         ctx->cts = (u64) (ctx->indexes[i-1].duration * GF_M4ASampleRates[ctx->sr_idx]);
     491           1 :                                         ctx->file_pos = ctx->indexes[i-1].pos;
     492           1 :                                         break;
     493             :                                 }
     494             :                         }
     495             :                 }
     496          54 :                 if (!ctx->initial_play_done) {
     497          49 :                         ctx->initial_play_done = GF_TRUE;
     498             :                         //seek will not change the current source state, don't send a seek
     499          49 :                         if (!ctx->file_pos)
     500             :                                 return GF_TRUE;
     501             :                 }
     502           5 :                 ctx->resume_from = 0;
     503           5 :                 ctx->adts_buffer_size = 0;
     504             :                 //post a seek
     505           5 :                 GF_FEVT_INIT(fevt, GF_FEVT_SOURCE_SEEK, ctx->ipid);
     506           5 :                 fevt.seek.start_offset = ctx->file_pos;
     507           5 :                 gf_filter_pid_send_event(ctx->ipid, &fevt);
     508             : 
     509             :                 //cancel event
     510           5 :                 return GF_TRUE;
     511             : 
     512          53 :         case GF_FEVT_STOP:
     513             :                 //don't cancel event
     514          53 :                 ctx->is_playing = GF_FALSE;
     515          53 :                 return GF_FALSE;
     516             : 
     517             :         case GF_FEVT_SET_SPEED:
     518             :                 //cancel event
     519             :                 return GF_TRUE;
     520             :         default:
     521             :                 break;
     522             :         }
     523             :         //by default don't cancel event - to rework once we have downloading in place
     524        6473 :         return GF_FALSE;
     525             : }
     526             : 
     527             : static GFINLINE void adts_dmx_update_cts(GF_ADTSDmxCtx *ctx)
     528             : {
     529             :         assert(ctx->dts_inc);
     530             : 
     531       83356 :         if (ctx->timescale) {
     532        6205 :                 u64 inc = ctx->dts_inc;
     533        6205 :                 inc *= ctx->timescale;
     534        6205 :                 inc /= GF_M4ASampleRates[ctx->sr_idx];
     535        6205 :                 ctx->cts += inc;
     536             :         } else {
     537       77151 :                 ctx->cts += ctx->dts_inc;
     538             :         }
     539             : }
     540             : 
     541     3279306 : GF_Err adts_dmx_process(GF_Filter *filter)
     542             : {
     543     3279306 :         GF_ADTSDmxCtx *ctx = gf_filter_get_udta(filter);
     544             :         GF_FilterPacket *pck, *dst_pck;
     545             :         u8 *data, *output;
     546             :         u8 *start;
     547             :         u32 pck_size, remain, prev_pck_size;
     548             :         u64 cts = GF_FILTER_NO_TS;
     549             : 
     550             :         //always reparse duration
     551     3279306 :         if (!ctx->duration.num)
     552       11297 :                 adts_dmx_check_dur(filter, ctx);
     553             : 
     554     3279306 :         if (ctx->opid && !ctx->is_playing)
     555             :                 return GF_OK;
     556             : 
     557       12331 :         pck = gf_filter_pid_get_packet(ctx->ipid);
     558       12331 :         if (!pck) {
     559         536 :                 if (gf_filter_pid_is_eos(ctx->ipid)) {
     560         252 :                         if (!ctx->adts_buffer_size) {
     561         138 :                                 if (ctx->opid)
     562         138 :                                         gf_filter_pid_set_eos(ctx->opid);
     563         138 :                                 if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
     564         138 :                                 ctx->src_pck = NULL;
     565         138 :                                 return GF_EOS;
     566             :                         }
     567             :                 } else {
     568             :                         return GF_OK;
     569             :                 }
     570             :         }
     571             : 
     572       11909 :         prev_pck_size = ctx->adts_buffer_size;
     573       11909 :         if (pck && !ctx->resume_from) {
     574       11658 :                 data = (char *) gf_filter_pck_get_data(pck, &pck_size);
     575       11658 :                 if (!pck_size) {
     576           0 :                         gf_filter_pid_drop_packet(ctx->ipid);
     577           0 :                         return GF_OK;
     578             :                 }
     579             : 
     580       11658 :                 if (ctx->byte_offset != GF_FILTER_NO_BO) {
     581        5390 :                         u64 byte_offset = gf_filter_pck_get_byte_offset(pck);
     582        5390 :                         if (!ctx->adts_buffer_size) {
     583         155 :                                 ctx->byte_offset = byte_offset;
     584        5235 :                         } else if (ctx->byte_offset + ctx->adts_buffer_size != byte_offset) {
     585           0 :                                 ctx->byte_offset = GF_FILTER_NO_BO;
     586           0 :                                 if ((byte_offset != GF_FILTER_NO_BO) && (byte_offset>ctx->adts_buffer_size) ) {
     587           0 :                                         ctx->byte_offset = byte_offset - ctx->adts_buffer_size;
     588             :                                 }
     589             :                         }
     590             :                 }
     591             : 
     592       11658 :                 if (ctx->adts_buffer_size + pck_size > ctx->adts_buffer_alloc) {
     593         851 :                         ctx->adts_buffer_alloc = ctx->adts_buffer_size + pck_size;
     594         851 :                         ctx->adts_buffer = gf_realloc(ctx->adts_buffer, ctx->adts_buffer_alloc);
     595             :                 }
     596       11658 :                 memcpy(ctx->adts_buffer + ctx->adts_buffer_size, data, pck_size);
     597       11658 :                 ctx->adts_buffer_size += pck_size;
     598             :         }
     599             : 
     600             :         //input pid sets some timescale - we flushed pending data , update cts
     601       11909 :         if (ctx->timescale && pck) {
     602        6207 :                 cts = gf_filter_pck_get_cts(pck);
     603             :         }
     604             : 
     605        6207 :         if (cts == GF_FILTER_NO_TS) {
     606             :                 //avoids updating cts
     607             :                 prev_pck_size = 0;
     608             :         }
     609             : 
     610       11909 :         remain = ctx->adts_buffer_size;
     611       11909 :         start = ctx->adts_buffer;
     612             : 
     613       11909 :         if (ctx->resume_from) {
     614         137 :                 start += ctx->resume_from - 1;
     615         137 :                 remain -= ctx->resume_from - 1;
     616         137 :                 ctx->resume_from = 0;
     617             :         }
     618             : 
     619       95265 :         while (remain) {
     620             :                 u8 *sync;
     621             :                 u32 sync_pos, size, offset, bytes_to_drop=0, nb_blocks_per_frame;
     622             : 
     623       95151 :                 if (!ctx->tag_size && (remain>3)) {
     624             : 
     625             :                         /* Did we read an ID3v2 ? */
     626       95103 :                         if (start[0] == 'I' && start[1] == 'D' && start[2] == '3') {
     627           0 :                                 if (remain<10)
     628             :                                         return GF_OK;
     629             : 
     630           0 :                                 ctx->tag_size = ((start[9] & 0x7f) + ((start[8] & 0x7f) << 7) + ((start[7] & 0x7f) << 14) + ((start[6] & 0x7f) << 21));
     631             : 
     632             :                                 bytes_to_drop = 10;
     633           0 :                                 if (ctx->id3_buffer_alloc < ctx->tag_size+10) {
     634           0 :                                         ctx->id3_buffer = gf_realloc(ctx->id3_buffer, ctx->tag_size+10);
     635           0 :                                         ctx->id3_buffer_alloc = ctx->tag_size+10;
     636             :                                 }
     637           0 :                                 memcpy(ctx->id3_buffer, start, 10);
     638           0 :                                 ctx->id3_buffer_size = 10;
     639             :                                 goto drop_byte;
     640             :                         }
     641             :                 }
     642       95151 :                 if (ctx->tag_size) {
     643           0 :                         if (ctx->tag_size>remain) {
     644             :                                 bytes_to_drop = remain;
     645           0 :                                 ctx->tag_size-=remain;
     646             :                         } else {
     647             :                                 bytes_to_drop = ctx->tag_size;
     648           0 :                                 ctx->tag_size = 0;
     649             :                         }
     650           0 :                         memcpy(ctx->id3_buffer + ctx->id3_buffer_size, start, bytes_to_drop);
     651           0 :                         ctx->id3_buffer_size += bytes_to_drop;
     652             : 
     653           0 :                         if (!ctx->tag_size && ctx->opid) {
     654           0 :                                 id3dmx_flush(filter, ctx->id3_buffer, ctx->id3_buffer_size, ctx->opid, ctx->expart ? &ctx->vpid : NULL);
     655           0 :                                 ctx->id3_buffer_size = 0;
     656             :                         }
     657             :                         goto drop_byte;
     658             : 
     659             :                 }
     660             : 
     661       95151 :                 sync = memchr(start, 0xFF, remain);
     662       95151 :                 sync_pos = (u32) (sync ? sync - start : remain);
     663             : 
     664             :                 //couldn't find sync byte in this packet
     665       95151 :                 if (remain - sync_pos < 7) {
     666             :                         break;
     667             :                 }
     668             : 
     669             :                 //not sync !
     670       95025 :                 if ((sync[1] & 0xF0) != 0xF0) {
     671           0 :                         GF_LOG(ctx->nb_frames ? GF_LOG_WARNING : GF_LOG_DEBUG, GF_LOG_PARSER, ("[ADTSDmx] invalid ADTS sync bytes, resyncing\n"));
     672           0 :                         ctx->nb_frames = 0;
     673             :                         goto drop_byte;
     674             :                 }
     675       95025 :                 if (!ctx->bs) {
     676         149 :                         ctx->bs = gf_bs_new(sync + 1, remain - sync_pos - 1, GF_BITSTREAM_READ);
     677             :                 } else {
     678       94876 :                         gf_bs_reassign_buffer(ctx->bs, sync + 1, remain - sync_pos - 1);
     679             :                 }
     680             : 
     681             :                 //ok parse header
     682       95025 :                 gf_bs_read_int(ctx->bs, 4);
     683             : 
     684       95025 :                 ctx->hdr.is_mp2 = (Bool)gf_bs_read_int(ctx->bs, 1);
     685             :                 //if (ctx->mpeg4)
     686             :                 //we deprecate old MPEG-2 signaling for AAC in ISOBMFF, as it is not well supported anyway and we don't write adif_header as
     687             :                 //supposed to be for these types
     688       95025 :                 ctx->hdr.is_mp2 = 0;
     689             : 
     690       95025 :                 gf_bs_read_int(ctx->bs, 2);
     691       95025 :                 ctx->hdr.no_crc = (Bool)gf_bs_read_int(ctx->bs, 1);
     692             : 
     693       95025 :                 ctx->hdr.profile = 1 + gf_bs_read_int(ctx->bs, 2);
     694       95025 :                 ctx->hdr.sr_idx = gf_bs_read_int(ctx->bs, 4);
     695       95025 :                 gf_bs_read_int(ctx->bs, 1);
     696       95025 :                 ctx->hdr.nb_ch = gf_bs_read_int(ctx->bs, 3);
     697             : 
     698       95025 :                 gf_bs_read_int(ctx->bs, 4);
     699       95025 :                 ctx->hdr.frame_size = gf_bs_read_int(ctx->bs, 13);
     700       95025 :                 gf_bs_read_int(ctx->bs, 11);
     701       95025 :                 nb_blocks_per_frame = gf_bs_read_int(ctx->bs, 2);
     702       95025 :                 ctx->hdr.hdr_size = 7;
     703             : 
     704       95025 :                 if (!ctx->hdr.no_crc) {
     705             :                         u32 skip;
     706           0 :                         if (!nb_blocks_per_frame) {
     707             :                                 skip = 2;
     708             :                         } else {
     709           0 :                                 skip = 2 + 2*nb_blocks_per_frame; //and we have 2 bytes per raw_data_block
     710             :                         }
     711           0 :                         ctx->hdr.hdr_size += skip;
     712           0 :                         gf_bs_skip_bytes(ctx->bs, skip);
     713             :                 }
     714             : 
     715       95025 :                 if (!ctx->hdr.frame_size || !GF_M4ASampleRates[ctx->hdr.sr_idx]) {
     716           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[ADTSDmx] Invalid ADTS frame header, resyncing\n"));
     717           0 :                         ctx->nb_frames = 0;
     718             :                         goto drop_byte;
     719             :                 }
     720       95025 :                 if ((nb_blocks_per_frame>2) || (nb_blocks_per_frame && ctx->hdr.nb_ch)) {
     721           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[ADTSDmx] Unsupported multi-block ADTS frame header - patch welcome\n"));
     722           0 :                         ctx->nb_frames = 0;
     723             :                         goto drop_byte;
     724       95025 :                 } else if (!nb_blocks_per_frame) {
     725       95025 :                         if (ctx->aacchcfg<0)
     726           0 :                                 ctx->hdr.nb_ch = -ctx->aacchcfg;
     727       95025 :                         else if (!ctx->hdr.nb_ch)
     728           0 :                                 ctx->hdr.nb_ch = ctx->aacchcfg;
     729             : 
     730       95025 :                         if (!ctx->hdr.nb_ch) {
     731           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[ADTSDmx] Missing channel configuration in ADTS frame header, defaulting to stereo - use `--aacchcfg` to force config\n"));
     732           0 :                                 ctx->hdr.nb_ch = ctx->aacchcfg = 2;
     733             :                         }
     734             :                 }
     735             : 
     736       95025 :                 if (nb_blocks_per_frame==2) {
     737           0 :                         u32 pos = (u32) gf_bs_get_position(ctx->bs);
     738           0 :                         gf_m4a_parse_program_config_element(ctx->bs, &ctx->acfg);
     739           0 :                         if (!ctx->hdr.no_crc)
     740           0 :                                 gf_bs_skip_bytes(ctx->bs, 2);  //per block CRC
     741             : 
     742           0 :                         ctx->hdr.hdr_size += (u32) gf_bs_get_position(ctx->bs) - pos;
     743             :                 }
     744             :                 //value 1->6 match channel number, value 7 is 7.1
     745       95025 :                 if (ctx->hdr.nb_ch==7)
     746           0 :                         ctx->hdr.nb_ch = 8;
     747             : 
     748             : 
     749             :                 //ready to send packet
     750       95025 :                 if (ctx->hdr.frame_size + 1 < remain) {
     751             :                         u32 next_frame = ctx->hdr.frame_size;
     752             :                         //make sure we are sync!
     753       83379 :                         if ((sync[next_frame] !=0xFF) || ((sync[next_frame+1] & 0xF0) !=0xF0) ) {
     754           0 :                                 GF_LOG(ctx->nb_frames ? GF_LOG_WARNING : GF_LOG_DEBUG, GF_LOG_PARSER, ("[ADTSDmx] invalid next ADTS frame sync, resyncing\n"));
     755           0 :                                 ctx->nb_frames = 0;
     756             :                                 goto drop_byte;
     757             :                         }
     758             :                 }
     759             :                 //otherwise wait for next frame, unless if end of stream
     760       11646 :                 else if (pck) {
     761       11532 :                         if (ctx->timescale && !prev_pck_size &&  (cts != GF_FILTER_NO_TS) ) {
     762        6207 :                                 ctx->cts = cts;
     763             :                         }
     764             :                         break;
     765             :                 }
     766             : 
     767       83493 :                 if (ctx->hdr.frame_size < ctx->hdr.hdr_size) {
     768           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[ADTSDmx] Corrupted ADTS frame header, resyncing\n"));
     769           0 :                         ctx->nb_frames = 0;
     770             :                         goto drop_byte;
     771             :                 }
     772             : 
     773       83493 :                 adts_dmx_check_pid(filter, ctx);
     774             : 
     775       83493 :                 if (!ctx->is_playing) {
     776         137 :                         ctx->resume_from = 1 + ctx->adts_buffer_size - remain;
     777         137 :                         return GF_OK;
     778             :                 }
     779             : 
     780       83356 :                 ctx->nb_frames++;
     781       83356 :                 size = ctx->hdr.frame_size - ctx->hdr.hdr_size;
     782             :                 offset = ctx->hdr.hdr_size;
     783             :                 //per raw-block CRC
     784       83356 :                 if ((nb_blocks_per_frame==2) && !ctx->hdr.no_crc)
     785           0 :                         size -= 2;
     786             : 
     787       83356 :                 if (ctx->in_seek) {
     788         148 :                         u64 nb_samples_at_seek = (u64) (ctx->start_range * GF_M4ASampleRates[ctx->sr_idx]);
     789         148 :                         if (ctx->cts + ctx->dts_inc >= nb_samples_at_seek) {
     790             :                                 //u32 samples_to_discard = (ctx->cts + ctx->dts_inc) - nb_samples_at_seek;
     791          53 :                                 ctx->in_seek = GF_FALSE;
     792             :                         }
     793             :                 }
     794             : 
     795             :                 bytes_to_drop = ctx->hdr.frame_size;
     796       83356 :                 if (ctx->timescale && !prev_pck_size &&  (cts != GF_FILTER_NO_TS) ) {
     797           0 :                         ctx->cts = cts;
     798             :                         cts = GF_FILTER_NO_TS;
     799             :                 }
     800             : 
     801       83356 :                 if (!ctx->in_seek) {
     802       83261 :                         dst_pck = gf_filter_pck_new_alloc(ctx->opid, size, &output);
     803       83261 :                         if (!dst_pck) return GF_OUT_OF_MEM;
     804       83261 :                         if (ctx->src_pck) gf_filter_pck_merge_properties(ctx->src_pck, dst_pck);
     805             : 
     806       83261 :                         memcpy(output, sync + offset, size);
     807             : 
     808       83261 :                         gf_filter_pck_set_dts(dst_pck, ctx->cts);
     809       83261 :                         gf_filter_pck_set_cts(dst_pck, ctx->cts);
     810       83261 :                         gf_filter_pck_set_duration(dst_pck, ctx->dts_inc);
     811       83261 :                         gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
     812       83261 :                         gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
     813             : 
     814       83261 :                         if (ctx->byte_offset != GF_FILTER_NO_BO) {
     815       75406 :                                 gf_filter_pck_set_byte_offset(dst_pck, ctx->byte_offset + ctx->hdr.hdr_size);
     816             :                         }
     817             : 
     818       83261 :                         gf_filter_pck_send(dst_pck);
     819             :                 }
     820             :                 adts_dmx_update_cts(ctx);
     821             : 
     822             : 
     823             :                 //truncated last frame
     824       83356 :                 if (bytes_to_drop>remain) {
     825           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[ADTSDmx] truncated ADTS frame!\n"));
     826             :                         bytes_to_drop=remain;
     827             :                 }
     828             : 
     829      166712 : drop_byte:
     830       83356 :                 if (!bytes_to_drop) {
     831             :                         bytes_to_drop = 1;
     832             :                 }
     833       83356 :                 start += bytes_to_drop;
     834       83356 :                 remain -= bytes_to_drop;
     835             : 
     836       83356 :                 if (prev_pck_size) {
     837        6190 :                         if (prev_pck_size > bytes_to_drop) prev_pck_size -= bytes_to_drop;
     838             :                         else {
     839             :                                 prev_pck_size=0;
     840        6190 :                                 if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
     841        6190 :                                 ctx->src_pck = pck;
     842        6190 :                                 if (pck)
     843        6190 :                                         gf_filter_pck_ref_props(&ctx->src_pck);
     844             :                         }
     845             :                 }
     846       83356 :                 if (ctx->byte_offset != GF_FILTER_NO_BO)
     847       75501 :                         ctx->byte_offset += bytes_to_drop;
     848             :         }
     849             : 
     850       11772 :         if (!pck) {
     851         114 :                 ctx->adts_buffer_size = 0;
     852         114 :                 return adts_dmx_process(filter);
     853             :         } else {
     854       11658 :                 if (remain) {
     855       11658 :                         memmove(ctx->adts_buffer, start, remain);
     856             :                 }
     857       11658 :                 ctx->adts_buffer_size = remain;
     858       11658 :                 gf_filter_pid_drop_packet(ctx->ipid);
     859             :         }
     860       11658 :         return GF_OK;
     861             : }
     862             : 
     863         149 : static void adts_dmx_finalize(GF_Filter *filter)
     864             : {
     865         149 :         GF_ADTSDmxCtx *ctx = gf_filter_get_udta(filter);
     866         149 :         if (ctx->bs) gf_bs_del(ctx->bs);
     867         149 :         if (ctx->indexes) gf_free(ctx->indexes);
     868         149 :         if (ctx->adts_buffer) gf_free(ctx->adts_buffer);
     869         149 :         if (ctx->id3_buffer) gf_free(ctx->id3_buffer);
     870         149 :         if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
     871         149 : }
     872             : 
     873        3074 : static const char *adts_dmx_probe_data(const u8 *data, u32 size, GF_FilterProbeScore *score)
     874             : {
     875             :         u32 nb_frames=0, next_pos=0, max_consecutive_frames=0;
     876             :         ADTSHeader prev_hdr;
     877             :         GF_BitStream *bs;
     878             :         Bool has_id3=GF_FALSE;
     879             :         Bool has_broken_data=GF_FALSE;
     880             : 
     881             :         /*check for id3*/
     882        3074 :         if (size>= 10) {
     883        3070 :                 if (data[0] == 'I' && data[1] == 'D' && data[2] == '3') {
     884           1 :                         u32 tag_size = ((data[9] & 0x7f) + ((data[8] & 0x7f) << 7) + ((data[7] & 0x7f) << 14) + ((data[6] & 0x7f) << 21));
     885             : 
     886           1 :                         if (tag_size+10 > size) {
     887           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("ID3 tag detected size %d but probe data only %d bytes, will rely on file extension (try increasing probe size using --block_size)\n", tag_size+10, size));
     888           0 :                                 *score = GF_FPROBE_EXT_MATCH;
     889           0 :                                 return "aac|adts";
     890             :                         }
     891           1 :                         data += tag_size+10;
     892           1 :                         size -= tag_size+10;
     893             :                         has_id3 = GF_TRUE;
     894             :                 }
     895             :         }
     896             : 
     897        3074 :         bs = gf_bs_new(data, size, GF_BITSTREAM_READ);
     898             :         memset(&prev_hdr, 0, sizeof(ADTSHeader));
     899        3935 :         while (gf_bs_available(bs)) {
     900             :                 ADTSHeader hdr;
     901             :                 u32 pos;
     902        3935 :                 hdr.frame_size = 0;
     903        3935 :                 if (!adts_dmx_sync_frame_bs(bs, &hdr)) {
     904        2911 :                         if (hdr.frame_size) {
     905             :                                 //nb_frames++;
     906         866 :                                 max_consecutive_frames++;
     907             :                         }
     908        3074 :                         break;
     909             :                 }
     910        1024 :                 if ((hdr.hdr_size!=7) && (hdr.hdr_size!=9)) continue;
     911             : //              if (!hdr.nb_ch) continue;
     912        1024 :                 pos = (u32) gf_bs_get_position(bs);
     913             : 
     914        1024 :                 if (!nb_frames) {
     915             :                         nb_frames = 1;
     916         840 :                 } else if ((next_pos + hdr.hdr_size == pos) && (hdr.sr_idx==prev_hdr.sr_idx) && (hdr.nb_ch==prev_hdr.nb_ch) ) {
     917         817 :                         nb_frames++;
     918         817 :                         if (max_consecutive_frames<nb_frames) max_consecutive_frames = nb_frames;
     919         817 :                         if (max_consecutive_frames>5)
     920             :                                 break;
     921             :                 } else {
     922             :                         nb_frames=1;
     923             :                         has_broken_data=GF_TRUE;
     924             :                 }
     925         861 :                 prev_hdr = hdr;
     926         861 :                 gf_bs_skip_bytes(bs, hdr.frame_size);
     927         861 :                 next_pos = (u32) gf_bs_get_position(bs);
     928             :         }
     929        3074 :         gf_bs_del(bs);
     930        3074 :         if (max_consecutive_frames>=4) {
     931         163 :                 *score = has_broken_data ? GF_FPROBE_MAYBE_SUPPORTED : GF_FPROBE_SUPPORTED;
     932         163 :                 return "audio/aac";
     933             :         }
     934        2911 :         if (has_id3 && max_consecutive_frames) {
     935           1 :                 *score = GF_FPROBE_MAYBE_SUPPORTED;
     936           1 :                 return "audio/aac";
     937             :         }
     938             :         return NULL;
     939             : }
     940             : 
     941             : static const GF_FilterCapability ADTSDmxCaps[] =
     942             : {
     943             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
     944             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "aac|adts"),
     945             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "audio/x-m4a|audio/aac|audio/aacp|audio/x-aac"),
     946             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     947             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
     948             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
     949             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
     950             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
     951             :         //we explitely set this one to prevent adts->latm reframer connection
     952             :         CAP_BOOL(GF_CAPS_OUTPUT_STATIC_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
     953             :         {0},
     954             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     955             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
     956             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
     957             : };
     958             : 
     959             : 
     960             : #define OFFS(_n)        #_n, offsetof(GF_ADTSDmxCtx, _n)
     961             : static const GF_FilterArgs ADTSDmxArgs[] =
     962             : {
     963             :         { OFFS(frame_size), "size of AAC frame in audio samples", GF_PROP_UINT, "1024", NULL, GF_FS_ARG_HINT_EXPERT},
     964             :         { OFFS(index), "indexing window length", GF_PROP_DOUBLE, "1.0", NULL, 0},
     965             : //      { OFFS(mpeg4), "force signaling as MPEG-4 AAC", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
     966             :         { OFFS(ovsbr), "force oversampling SBR (does not multiply timescales by 2)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
     967             :         { OFFS(sbr), "set SBR signaling\n"\
     968             :                                 "- no: no SBR signaling at all\n"\
     969             :                                 "- imp: backward-compatible SBR signaling (audio signaled as AAC-LC)\n"\
     970             :                                 "- exp: explicit SBR signaling (audio signaled as AAC-SBR)"\
     971             :                                 , GF_PROP_UINT, "no", "no|imp|exp", GF_FS_ARG_HINT_ADVANCED},
     972             :         { OFFS(ps), "set PS signaling\n"\
     973             :                                 "- no: no PS signaling at all\n"\
     974             :                                 "- imp: backward-compatible PS signaling (audio signaled as AAC-LC)\n"\
     975             :                                 "- exp: explicit PS signaling (audio signaled as AAC-PS)"\
     976             :                                 , GF_PROP_UINT, "no", "no|imp|exp", GF_FS_ARG_HINT_ADVANCED},
     977             :         { OFFS(expart), "expose pictures as a dedicated video pid", GF_PROP_BOOL, "false", NULL, 0},
     978             :         { OFFS(aacchcfg), "set AAC channel configuration to this value if missing from ADTS header, use negative value to always override", GF_PROP_SINT, "0", NULL, GF_FS_ARG_HINT_EXPERT},
     979             :         {0}
     980             : };
     981             : 
     982             : 
     983             : GF_FilterRegister ADTSDmxRegister = {
     984             :         .name = "rfadts",
     985             :         GF_FS_SET_DESCRIPTION("ADTS reframer")
     986             :         GF_FS_SET_HELP("This filter parses AAC files/data and outputs corresponding audio PID and frames.")
     987             :         .private_size = sizeof(GF_ADTSDmxCtx),
     988             :         .args = ADTSDmxArgs,
     989             :         .finalize = adts_dmx_finalize,
     990             :         SETCAPS(ADTSDmxCaps),
     991             :         .configure_pid = adts_dmx_configure_pid,
     992             :         .process = adts_dmx_process,
     993             :         .probe_data = adts_dmx_probe_data,
     994             :         .process_event = adts_dmx_process_event
     995             : };
     996             : 
     997             : 
     998        2877 : const GF_FilterRegister *adts_dmx_register(GF_FilterSession *session)
     999             : {
    1000        2877 :         return &ADTSDmxRegister;
    1001             : }
    1002             : 
    1003             : #else
    1004             : const GF_FilterRegister *adts_dmx_register(GF_FilterSession *session)
    1005             : {
    1006             :         return NULL;
    1007             : }
    1008             : #endif // GPAC_DISABLE_AV_PARSERS

Generated by: LCOV version 1.13