LCOV - code coverage report
Current view: top level - filters - reframe_latm.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 238 290 82.1 %
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             : #include <gpac/internal/media_dev.h>
      30             : 
      31             : #ifndef GPAC_DISABLE_AV_PARSERS
      32             : 
      33             : typedef struct
      34             : {
      35             :         u64 pos;
      36             :         Double duration;
      37             : } LATMIdx;
      38             : 
      39             : typedef struct
      40             : {
      41             :         //filter args
      42             :         u32 frame_size;
      43             :         Double index;
      44             : 
      45             :         //only one input pid declared
      46             :         GF_FilterPid *ipid;
      47             :         //only one output pid declared
      48             :         GF_FilterPid *opid;
      49             : 
      50             :         GF_BitStream *bs;
      51             :         u64 file_pos, cts;
      52             :         u32 sr_idx, nb_ch, base_object_type;
      53             :         GF_Fraction64 duration;
      54             :         Double start_range;
      55             :         Bool in_seek;
      56             :         u32 timescale;
      57             : 
      58             :         GF_M4ADecSpecInfo acfg;
      59             :         
      60             :         char *latm_buffer;
      61             :         u32 latm_buffer_size, latm_buffer_alloc;
      62             :         u32 dts_inc;
      63             : 
      64             :         Bool is_playing;
      65             :         Bool is_file, file_loaded;
      66             :         Bool initial_play_done;
      67             : 
      68             :         GF_FilterPacket *src_pck;
      69             : 
      70             :         LATMIdx *indexes;
      71             :         u32 index_alloc_size, index_size;
      72             :         u32 resume_from;
      73             : 
      74             :         Bool prev_sap;
      75             :         u32 bitrate;
      76             :         GF_Err in_error;
      77             : } GF_LATMDmxCtx;
      78             : 
      79             : 
      80        7905 : static Bool latm_dmx_sync_frame_bs(GF_BitStream *bs, GF_M4ADecSpecInfo *acfg, u32 *nb_bytes, u8 *buffer, u32 *nb_skipped)
      81             : {
      82             :         u32 val, size;
      83             :         u64 pos, mux_size;
      84        7905 :         if (nb_skipped) *nb_skipped = 0;
      85        7905 :         if (!acfg) return 0;
      86             : 
      87     9242282 :         while (gf_bs_available(bs)>3) {
      88     9240365 :                 val = gf_bs_read_u8(bs);
      89     9240365 :                 if (val!=0x56) {
      90     9217002 :                         if (nb_skipped) (*nb_skipped) ++;
      91     9217002 :                         continue;
      92             :                 }
      93       23363 :                 val = gf_bs_read_int(bs, 3);
      94       23363 :                 if (val != 0x07) {
      95       16424 :                         gf_bs_read_int(bs, 5);
      96       16424 :                         if (nb_skipped) (*nb_skipped) ++;
      97       16424 :                         continue;
      98             :                 }
      99        6939 :                 mux_size = gf_bs_read_int(bs, 13);
     100        6939 :                 pos = gf_bs_get_position(bs);
     101        6939 :                 if (mux_size>gf_bs_available(bs) ) {
     102        1223 :                         gf_bs_seek(bs, pos-3);
     103        1223 :                         return GF_FALSE;
     104             :                 }
     105             : 
     106             :                 /*use same stream mux*/
     107        5716 :                 if (!gf_bs_read_int(bs, 1)) {
     108             :                         Bool amux_version, amux_versionA;
     109             : 
     110         817 :                         amux_version = (Bool)gf_bs_read_int(bs, 1);
     111             :                         amux_versionA = GF_FALSE;
     112         817 :                         if (amux_version) amux_versionA = (Bool)gf_bs_read_int(bs, 1);
     113         272 :                         if (!amux_versionA) {
     114             :                                 u32 i, allStreamsSameTimeFraming, numProgram;
     115         618 :                                 if (amux_version) gf_latm_get_value(bs);
     116             : 
     117         618 :                                 allStreamsSameTimeFraming = gf_bs_read_int(bs, 1);
     118         618 :                                 /*numSubFrames = */gf_bs_read_int(bs, 6);
     119         618 :                                 numProgram = gf_bs_read_int(bs, 4);
     120        4383 :                                 for (i=0; i<=numProgram; i++) {
     121             :                                         u32 j, num_lay;
     122        3765 :                                         num_lay = gf_bs_read_int(bs, 3);
     123       19677 :                                         for (j=0; j<=num_lay; j++) {
     124             :                                                 u32 frameLengthType;
     125             :                                                 Bool same_cfg = GF_FALSE;
     126       15912 :                                                 if (i || j) same_cfg = (Bool)gf_bs_read_int(bs, 1);
     127             : 
     128       15294 :                                                 if (!same_cfg) {
     129        7636 :                                                         if (amux_version==1) gf_latm_get_value(bs);
     130        7636 :                                                         gf_m4a_parse_config(bs, acfg, GF_FALSE);
     131             :                                                 }
     132       15912 :                                                 frameLengthType = gf_bs_read_int(bs, 3);
     133       15912 :                                                 if (!frameLengthType) {
     134        2437 :                                                         /*latmBufferFullness = */gf_bs_read_int(bs, 8);
     135             :                                                         if (!allStreamsSameTimeFraming) {
     136             :                                                         }
     137             :                                                 } else {
     138             :                                                         /*not supported*/
     139             :                                                 }
     140             :                                         }
     141             : 
     142             :                                 }
     143             :                                 /*other data present*/
     144         618 :                                 if (gf_bs_read_int(bs, 1)) {
     145             : //                                      u32 k = 0;
     146             :                                 }
     147             :                                 /*CRCcheck present*/
     148         618 :                                 if (gf_bs_read_int(bs, 1)) {
     149             :                                 }
     150             :                         }
     151             :                 }
     152             : 
     153             :                 size = 0;
     154             :                 while (1) {
     155        6352 :                         u32 tmp = gf_bs_read_int(bs, 8);
     156        6352 :                         size += tmp;
     157        6352 :                         if (tmp!=255) break;
     158             :                 }
     159        5716 :                 if (gf_bs_available(bs) < size) {
     160           0 :                         gf_bs_seek(bs, pos-3);
     161           0 :                         return GF_FALSE;
     162             :                 }
     163             : 
     164        5716 :                 if (nb_bytes) {
     165        2970 :                         *nb_bytes = (u32) size;
     166             :                 }
     167             : 
     168        5716 :                 if (buffer) {
     169        2970 :                         gf_bs_read_data(bs, (char *) buffer, size);
     170             :                 } else {
     171      294416 :                         while (size) {
     172      291670 :                                 gf_bs_read_int(bs, 8);
     173      291670 :                                 size--;
     174             :                         }
     175             :                 }
     176             : 
     177             :                 /*parse amux*/
     178        5716 :                 gf_bs_seek(bs, pos + mux_size);
     179             : 
     180        5716 :                 if ((gf_bs_available(bs)>2) && gf_bs_peek_bits(bs, 11, 0) != 0x2B7) {
     181         951 :                         gf_bs_seek(bs, pos + 1);
     182         951 :                         if (nb_skipped) (*nb_skipped) ++;
     183         951 :                         continue;
     184             :                 }
     185             : 
     186             :                 return GF_TRUE;
     187             :         }
     188             :         return GF_FALSE;
     189             : }
     190             : 
     191             : 
     192             : 
     193           4 : GF_Err latm_dmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     194             : {
     195             :         const GF_PropertyValue *p;
     196           4 :         GF_LATMDmxCtx *ctx = gf_filter_get_udta(filter);
     197             : 
     198           4 :         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           4 :         if (! gf_filter_pid_check_caps(pid))
     207             :                 return GF_NOT_SUPPORTED;
     208             : 
     209           4 :         ctx->ipid = pid;
     210           4 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_TIMESCALE);
     211           4 :         if (p) ctx->timescale = p->value.uint;
     212             : 
     213           4 :         if (ctx->timescale && !ctx->opid) {
     214           0 :                 ctx->opid = gf_filter_pid_new(filter);
     215           0 :                 gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
     216           0 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, NULL);
     217             :         }
     218             : 
     219             :         return GF_OK;
     220             : }
     221             : 
     222          36 : static void latm_dmx_check_dur(GF_Filter *filter, GF_LATMDmxCtx *ctx)
     223             : {
     224             :         FILE *stream;
     225             :         GF_BitStream *bs;
     226             :         GF_M4ADecSpecInfo acfg;
     227             :         u64 duration, cur_dur, cur_pos, rate;
     228             :         s32 sr_idx = -1;
     229             :         const GF_PropertyValue *p;
     230          70 :         if (!ctx->opid || ctx->timescale || ctx->file_loaded) return;
     231             : 
     232           4 :         if (ctx->index<=0) {
     233           2 :                 ctx->file_loaded = GF_TRUE;
     234             :                 return;
     235             :         }
     236             : 
     237           2 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILEPATH);
     238           2 :         if (!p || !p->value.string || !strncmp(p->value.string, "gmem://", 7)) {
     239           0 :                 ctx->is_file = GF_FALSE;
     240           0 :                 ctx->file_loaded = GF_TRUE;
     241             :                 return;
     242             :         }
     243           2 :         ctx->is_file = GF_TRUE;
     244             : 
     245           2 :         stream = gf_fopen(p->value.string, "rb");
     246           2 :         if (!stream) return;
     247             : 
     248           2 :         ctx->index_size = 0;
     249             : 
     250             :         memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo));
     251             : 
     252             : 
     253           2 :         bs = gf_bs_from_file(stream, GF_BITSTREAM_READ);
     254             :         duration = 0;
     255             :         cur_dur = 0;
     256           2 :         cur_pos = gf_bs_get_position(bs);
     257        1625 :         while (latm_dmx_sync_frame_bs(bs, &acfg, 0, NULL, NULL)) {
     258        1623 :                 if ((sr_idx>=0) && (sr_idx != acfg.base_sr_index)) {
     259           0 :                         duration *= GF_M4ASampleRates[acfg.base_sr_index];
     260           0 :                         duration /= GF_M4ASampleRates[sr_idx];
     261             : 
     262           0 :                         cur_dur *= GF_M4ASampleRates[acfg.base_sr_index];
     263           0 :                         cur_dur /= GF_M4ASampleRates[sr_idx];
     264             :                 }
     265        1623 :                 sr_idx = acfg.base_sr_index;
     266        1623 :                 duration += ctx->frame_size;
     267        1623 :                 cur_dur += ctx->frame_size;
     268        1623 :                 if (cur_dur > ctx->index * GF_M4ASampleRates[sr_idx]) {
     269          36 :                         if (!ctx->index_alloc_size) ctx->index_alloc_size = 10;
     270          34 :                         else if (ctx->index_alloc_size == ctx->index_size) ctx->index_alloc_size *= 2;
     271          36 :                         ctx->indexes = gf_realloc(ctx->indexes, sizeof(LATMIdx)*ctx->index_alloc_size);
     272          36 :                         ctx->indexes[ctx->index_size].pos = cur_pos;
     273          36 :                         ctx->indexes[ctx->index_size].duration = (Double) duration;
     274          36 :                         ctx->indexes[ctx->index_size].duration /= GF_M4ASampleRates[sr_idx];
     275          36 :                         ctx->index_size ++;
     276             :                         cur_dur = 0;
     277             :                 }
     278             : 
     279        1623 :                 cur_pos = gf_bs_get_position(bs);
     280             :         }
     281           2 :         rate = gf_bs_get_position(bs);
     282           2 :         gf_bs_del(bs);
     283           2 :         gf_fclose(stream);
     284             : 
     285           2 :         if (sr_idx>=0) {
     286           2 :                 if (!ctx->duration.num || (ctx->duration.num  * GF_M4ASampleRates[sr_idx] != duration * ctx->duration.den)) {
     287           2 :                         ctx->duration.num = (s32) duration;
     288           2 :                         ctx->duration.den = GF_M4ASampleRates[sr_idx];
     289             : 
     290           2 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DURATION, & PROP_FRAC64(ctx->duration));
     291             : 
     292           2 :                         if (duration && !gf_sys_is_test_mode() ) {
     293           0 :                                 rate *= 8 * ctx->duration.den;
     294           0 :                                 rate /= ctx->duration.num;
     295           0 :                                 ctx->bitrate = (u32) rate;
     296             :                         }
     297             :                 }
     298             :         }
     299           2 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILE_CACHED);
     300           2 :         if (p && p->value.boolean) ctx->file_loaded = GF_TRUE;
     301           2 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CAN_DATAREF, & PROP_BOOL(GF_TRUE ) );
     302             : }
     303             : 
     304        2970 : static void latm_dmx_check_pid(GF_Filter *filter, GF_LATMDmxCtx *ctx)
     305             : {
     306             :         u8 *dsi_b;
     307             :         u32 dsi_s, sr, timescale=0;
     308             :         u32 codecid;
     309        2970 :         if (!ctx->opid) {
     310           4 :                 ctx->opid = gf_filter_pid_new(filter);
     311           4 :                 gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
     312           4 :                 latm_dmx_check_dur(filter, ctx);
     313             :         }
     314        2970 :         if (!GF_M4ASampleRates[ctx->acfg.base_sr_index]) {
     315           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[LATMDmx] Wrong sample rate in audio config, broken stream\n"));
     316           0 :                 ctx->in_error = GF_NON_COMPLIANT_BITSTREAM;
     317        2966 :                 return;
     318             :         }
     319             : 
     320        2970 :         if ((ctx->sr_idx == ctx->acfg.base_sr_index) && (ctx->nb_ch == ctx->acfg.nb_chan )
     321        2966 :                 && (ctx->base_object_type == ctx->acfg.base_object_type) ) return;
     322             : 
     323           4 :         if (ctx->acfg.base_object_type==GF_M4A_USAC)
     324             :                 codecid = GF_CODECID_USAC;
     325             :         else
     326             :                 codecid = GF_CODECID_AAC_MPEG4;
     327             :         //copy properties at init or reconfig
     328           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, & PROP_UINT( GF_STREAM_AUDIO));
     329           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, & PROP_UINT( codecid));
     330           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLES_PER_FRAME, & PROP_UINT(ctx->frame_size) );
     331           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, & PROP_BOOL(GF_FALSE) );
     332           4 :         if (ctx->is_file && ctx->index) {
     333           2 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PLAYBACK_MODE, & PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD) );
     334             :         }
     335           4 :         if (ctx->duration.num)
     336           2 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DURATION, & PROP_FRAC64(ctx->duration));
     337             : 
     338             : 
     339           4 :         ctx->nb_ch = ctx->acfg.nb_chan;
     340           4 :         ctx->base_object_type = ctx->acfg.base_object_type;
     341             : 
     342           4 :         sr = GF_M4ASampleRates[ctx->acfg.base_sr_index];
     343           4 :         if (!ctx->timescale) {
     344             :                 //we change sample rate, change cts
     345           4 :                 if (ctx->cts && (ctx->sr_idx != ctx->acfg.base_sr_index)) {
     346           0 :                         ctx->cts *= sr;
     347           0 :                         ctx->cts /= GF_M4ASampleRates[ctx->sr_idx];
     348             :                 }
     349             :         }
     350           4 :         ctx->sr_idx = ctx->acfg.base_sr_index;
     351             : 
     352           4 :         ctx->dts_inc = ctx->frame_size;
     353           4 :         gf_m4a_write_config(&ctx->acfg, &dsi_b, &dsi_s);
     354           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, & PROP_DATA_NO_COPY(dsi_b, dsi_s) );
     355           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PROFILE_LEVEL, & PROP_UINT (ctx->acfg.audioPL) );
     356           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, & PROP_UINT(sr));
     357             : 
     358             :         timescale = sr;
     359             : 
     360           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_TIMESCALE, & PROP_UINT(ctx->timescale ? ctx->timescale : timescale));
     361           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, & PROP_UINT(ctx->nb_ch) );
     362             : 
     363           4 :         if (ctx->bitrate) {
     364           0 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_BITRATE, & PROP_UINT(ctx->bitrate));
     365             :         }
     366             : }
     367             : 
     368          74 : static Bool latm_dmx_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
     369             : {
     370             :         u32 i;
     371             :         GF_FilterEvent fevt;
     372          74 :         GF_LATMDmxCtx *ctx = gf_filter_get_udta(filter);
     373             : 
     374          74 :         switch (evt->base.type) {
     375           4 :         case GF_FEVT_PLAY:
     376           4 :                 if (!ctx->is_playing) {
     377           4 :                         ctx->is_playing = GF_TRUE;
     378           4 :                         ctx->cts = 0;
     379             :                 }
     380           4 :                 if (! ctx->is_file) {
     381           2 :                         if (evt->play.start_range || ctx->initial_play_done) {
     382           0 :                                 ctx->latm_buffer_size = 0;
     383           0 :                                 ctx->resume_from = 0;
     384             :                         }
     385             : 
     386           2 :                         ctx->initial_play_done = GF_TRUE;
     387           2 :                         return GF_FALSE;
     388             :                 }
     389           2 :                 ctx->start_range = evt->play.start_range;
     390           2 :                 ctx->in_seek = GF_TRUE;
     391           2 :                 ctx->file_pos = 0;
     392           2 :                 if (ctx->start_range) {
     393           0 :                         for (i=1; i<ctx->index_size; i++) {
     394           0 :                                 if (ctx->indexes[i].duration>ctx->start_range) {
     395           0 :                                         ctx->cts = (u64) (ctx->indexes[i-1].duration * GF_M4ASampleRates[ctx->sr_idx]);
     396           0 :                                         ctx->file_pos = ctx->indexes[i-1].pos;
     397           0 :                                         break;
     398             :                                 }
     399             :                         }
     400             :                 }
     401           2 :                 if (!ctx->initial_play_done) {
     402           2 :                         ctx->initial_play_done = GF_TRUE;
     403             :                         //seek will not change the current source state, don't send a seek
     404           2 :                         if (!ctx->file_pos)
     405             :                                 return GF_TRUE;
     406             :                 }
     407           0 :                 ctx->latm_buffer_size = 0;
     408           0 :                 ctx->resume_from = 0;
     409             :                 //post a seek
     410           0 :                 GF_FEVT_INIT(fevt, GF_FEVT_SOURCE_SEEK, ctx->ipid);
     411           0 :                 fevt.seek.start_offset = ctx->file_pos;
     412           0 :                 gf_filter_pid_send_event(ctx->ipid, &fevt);
     413             : 
     414             :                 //cancel event
     415           0 :                 return GF_TRUE;
     416             : 
     417           1 :         case GF_FEVT_STOP:
     418             :                 //don't cancel event
     419           1 :                 ctx->is_playing = GF_FALSE;
     420           1 :                 return GF_FALSE;
     421             : 
     422             :         case GF_FEVT_SET_SPEED:
     423             :                 //cancel event
     424             :                 return GF_TRUE;
     425             :         default:
     426             :                 break;
     427             :         }
     428             :         //by default don't cancel event - to rework once we have downloading in place
     429          69 :         return GF_FALSE;
     430             : }
     431             : 
     432             : static GFINLINE void latm_dmx_update_cts(GF_LATMDmxCtx *ctx)
     433             : {
     434             :         assert(ctx->dts_inc);
     435             : 
     436        2966 :         if (ctx->timescale) {
     437           0 :                 u64 inc = ctx->dts_inc;
     438           0 :                 inc *= ctx->timescale;
     439           0 :                 inc /= GF_M4ASampleRates[ctx->sr_idx];
     440           0 :                 ctx->cts += inc;
     441             :         } else {
     442        2966 :                 ctx->cts += ctx->dts_inc;
     443             :         }
     444             : }
     445             : 
     446          86 : GF_Err latm_dmx_process(GF_Filter *filter)
     447             : {
     448          86 :         GF_LATMDmxCtx *ctx = gf_filter_get_udta(filter);
     449             :         GF_FilterPacket *pck, *dst_pck;
     450             :         u32 pos;
     451             :         u8 *data=NULL, *output;
     452          86 :         u32 pck_size=0, prev_pck_size;
     453             :         u64 cts = GF_FILTER_NO_TS;
     454             : 
     455          86 :         if (ctx->in_error)
     456             :                 return ctx->in_error;
     457             : 
     458             :         //always reparse duration
     459          86 :         if (!ctx->duration.num)
     460          32 :                 latm_dmx_check_dur(filter, ctx);
     461             : 
     462          86 :         if (ctx->opid && !ctx->is_playing)
     463             :                 return GF_OK;
     464             : 
     465          71 :         pck = gf_filter_pid_get_packet(ctx->ipid);
     466          71 :         if (!pck) {
     467           3 :                 if (gf_filter_pid_is_eos(ctx->ipid)) {
     468           3 :                         if (!ctx->latm_buffer_size) {
     469           3 :                                 if (ctx->opid)
     470           3 :                                         gf_filter_pid_set_eos(ctx->opid);
     471           3 :                                 if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
     472           3 :                                 ctx->src_pck = NULL;
     473           3 :                                 return GF_EOS;
     474             :                         }
     475             :                 } else {
     476             :                         return GF_OK;
     477             :                 }
     478             :         } else {
     479          68 :                 data = (char *) gf_filter_pck_get_data(pck, &pck_size);
     480             :         }
     481             : 
     482             :         //input pid sets some timescale - we flushed pending data , update cts
     483          68 :         if (ctx->timescale && pck) {
     484           0 :                 cts = gf_filter_pck_get_cts(pck);
     485             :         }
     486             : 
     487          68 :         prev_pck_size = ctx->latm_buffer_size;
     488             : 
     489          68 :         if (pck && !ctx->resume_from) {
     490          64 :                 if (ctx->latm_buffer_size + pck_size > ctx->latm_buffer_alloc) {
     491          20 :                         ctx->latm_buffer_alloc = ctx->latm_buffer_size + pck_size;
     492          20 :                         ctx->latm_buffer = gf_realloc(ctx->latm_buffer, ctx->latm_buffer_alloc);
     493             :                 }
     494          64 :                 memcpy(ctx->latm_buffer + ctx->latm_buffer_size, data, pck_size);
     495          64 :                 ctx->latm_buffer_size += pck_size;
     496             :         }
     497             : 
     498          68 :         if (!ctx->bs) ctx->bs = gf_bs_new(ctx->latm_buffer, ctx->latm_buffer_size, GF_BITSTREAM_READ);
     499          64 :         else gf_bs_reassign_buffer(ctx->bs, ctx->latm_buffer, ctx->latm_buffer_size);
     500             : 
     501          68 :         if (ctx->resume_from) {
     502           4 :                 gf_bs_seek(ctx->bs, ctx->resume_from-1);
     503           4 :                 ctx->resume_from = 0;
     504             :         }
     505             : 
     506          68 :         if (cts == GF_FILTER_NO_TS)
     507             :                 prev_pck_size = 0;
     508             : 
     509             : 
     510        2966 :         while (1) {
     511        3034 :                 pos = (u32) gf_bs_get_position(ctx->bs);
     512             :                 u8 latm_buffer[4096];
     513        3034 :                 u32 latm_frame_size = 4096;
     514        3034 :                 if (!latm_dmx_sync_frame_bs(ctx->bs,&ctx->acfg, &latm_frame_size, latm_buffer, NULL)) break;
     515             : 
     516        2970 :                 if (ctx->in_seek) {
     517           2 :                         u64 nb_samples_at_seek = (u64) (ctx->start_range * GF_M4ASampleRates[ctx->sr_idx]);
     518           2 :                         if (ctx->cts + ctx->dts_inc >= nb_samples_at_seek) {
     519             :                                 //u32 samples_to_discard = (ctx->cts + ctx->dts_inc) - nb_samples_at_seek;
     520           2 :                                 ctx->in_seek = GF_FALSE;
     521             :                         }
     522             :                 }
     523             : 
     524        2970 :                 latm_dmx_check_pid(filter, ctx);
     525             : 
     526        2970 :                 if (!ctx->is_playing) {
     527           4 :                         ctx->resume_from = pos+1;
     528           8 :                         return GF_OK;
     529             :                 }
     530             : 
     531        2966 :                 if (!ctx->in_seek) {
     532             :                         GF_FilterSAPType sap = GF_FILTER_SAP_1;
     533             : 
     534        2966 :                         dst_pck = gf_filter_pck_new_alloc(ctx->opid, latm_frame_size, &output);
     535        2966 :                         if (!dst_pck) return GF_OUT_OF_MEM;
     536             : 
     537        2966 :                         if (ctx->src_pck) gf_filter_pck_merge_properties(ctx->src_pck, dst_pck);
     538             : 
     539        2966 :                         memcpy(output, latm_buffer, latm_frame_size);
     540             : 
     541        2966 :                         gf_filter_pck_set_cts(dst_pck, ctx->cts);
     542        2966 :                         gf_filter_pck_set_duration(dst_pck, ctx->dts_inc);
     543        2966 :                         gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
     544             : 
     545             :                         /*xHE-AAC, check RAP*/
     546        2966 :                         if (ctx->acfg.base_object_type==GF_CODECID_USAC) {
     547           0 :                                 if (latm_frame_size && (output[0] & 0x80) && !ctx->prev_sap) {
     548             :                                         sap = GF_FILTER_SAP_1;
     549           0 :                                         ctx->prev_sap = GF_TRUE;
     550             :                                 } else {
     551             :                                         sap = GF_FILTER_SAP_NONE;
     552           0 :                                         ctx->prev_sap = GF_FALSE;
     553             :                                 }
     554             :                         }
     555        2966 :                         gf_filter_pck_set_sap(dst_pck, sap);
     556             : 
     557        2966 :                         gf_filter_pck_send(dst_pck);
     558             :                 }
     559             :                 latm_dmx_update_cts(ctx);
     560             : 
     561        2966 :                 if (prev_pck_size) {
     562           0 :                         pos = (u32) gf_bs_get_position(ctx->bs);
     563           0 :                         if (prev_pck_size<=pos) {
     564             :                                 prev_pck_size=0;
     565           0 :                                 if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
     566           0 :                                 ctx->src_pck = pck;
     567           0 :                                 if (pck)
     568           0 :                                         gf_filter_pck_ref_props(&ctx->src_pck);
     569             :                         }
     570             :                 }
     571             :         }
     572             : 
     573          64 :         if (pck) {
     574          64 :                 pos = (u32) gf_bs_get_position(ctx->bs);
     575             :                 assert(ctx->latm_buffer_size >= pos);
     576          64 :                 memmove(ctx->latm_buffer, ctx->latm_buffer+pos, ctx->latm_buffer_size - pos);
     577          64 :                 ctx->latm_buffer_size -= pos;
     578          64 :                 gf_filter_pid_drop_packet(ctx->ipid);
     579             :                 assert(!ctx->resume_from);
     580             :         } else {
     581           0 :                 ctx->latm_buffer_size = 0;
     582           0 :                 return latm_dmx_process(filter);
     583             :         }
     584          64 :         return GF_OK;
     585             : }
     586             : 
     587           4 : static void latm_dmx_finalize(GF_Filter *filter)
     588             : {
     589           4 :         GF_LATMDmxCtx *ctx = gf_filter_get_udta(filter);
     590           4 :         if (ctx->bs) gf_bs_del(ctx->bs);
     591           4 :         if (ctx->indexes) gf_free(ctx->indexes);
     592           4 :         if (ctx->latm_buffer) gf_free(ctx->latm_buffer);
     593           4 : }
     594             : 
     595        3074 : static const char *latm_dmx_probe_data(const u8 *data, u32 size, GF_FilterProbeScore *score)
     596             : {
     597             :         u32 nb_frames=0;
     598             :         u32 nb_skip=0;
     599             :         GF_M4ADecSpecInfo acfg;
     600        3074 :         GF_BitStream *bs = gf_bs_new(data, size, GF_BITSTREAM_READ);
     601         172 :         while (1) {
     602        3246 :                 u32 nb_skipped = 0;
     603        3246 :                 if (!latm_dmx_sync_frame_bs(bs, &acfg, 0, NULL, &nb_skipped)) break;
     604         172 :                 if (! GF_M4ASampleRates[acfg.base_sr_index]) {
     605             :                         nb_frames = 0;
     606             :                         break;
     607             :                 }
     608             : 
     609         172 :                 if (nb_skipped) {
     610           1 :                         if (nb_skip) {
     611             :                                 nb_frames = 0;
     612             :                                 break;
     613             :                         }
     614             :                         nb_skip++;
     615             :                 }
     616         172 :                 nb_frames++;
     617             :         }
     618        3074 :         gf_bs_del(bs);
     619        3074 :         if (nb_frames>=2) {
     620           4 :                 *score = nb_skip ? GF_FPROBE_MAYBE_SUPPORTED : GF_FPROBE_SUPPORTED;
     621           4 :                 return "audio/aac+latm";
     622             :         }
     623             :         return NULL;
     624             : }
     625             : 
     626             : static const GF_FilterCapability LATMDmxCaps[] =
     627             : {
     628             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
     629             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "latm"),
     630             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "audio/aac+latm"),
     631             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     632             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
     633             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
     634             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
     635             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
     636             :         CAP_BOOL(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
     637             :         {0},
     638             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     639             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
     640             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
     641             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED_LATM, GF_TRUE),
     642             : };
     643             : 
     644             : 
     645             : #define OFFS(_n)        #_n, offsetof(GF_LATMDmxCtx, _n)
     646             : static const GF_FilterArgs LATMDmxArgs[] =
     647             : {
     648             :         { OFFS(frame_size), "size of AAC frame in audio samples", GF_PROP_UINT, "1024", NULL, GF_FS_ARG_HINT_EXPERT},
     649             :         { OFFS(index), "indexing window length", GF_PROP_DOUBLE, "1.0", NULL, 0},
     650             :         {0}
     651             : };
     652             : 
     653             : 
     654             : GF_FilterRegister LATMDmxRegister = {
     655             :         .name = "rflatm",
     656             :         GF_FS_SET_DESCRIPTION("LATM reframer")
     657             :         GF_FS_SET_HELP("This filter parses AAC in LATM files/data and outputs corresponding audio PID and frames.")
     658             :         .private_size = sizeof(GF_LATMDmxCtx),
     659             :         .args = LATMDmxArgs,
     660             :         .finalize = latm_dmx_finalize,
     661             :         SETCAPS(LATMDmxCaps),
     662             :         .configure_pid = latm_dmx_configure_pid,
     663             :         .process = latm_dmx_process,
     664             :         .probe_data = latm_dmx_probe_data,
     665             :         .process_event = latm_dmx_process_event
     666             : };
     667             : 
     668             : 
     669        2877 : const GF_FilterRegister *latm_dmx_register(GF_FilterSession *session)
     670             : {
     671        2877 :         return &LATMDmxRegister;
     672             : }
     673             : 
     674             : #else
     675             : const GF_FilterRegister *latm_dmx_register(GF_FilterSession *session)
     676             : {
     677             :         return NULL;
     678             : }
     679             : #endif // GPAC_DISABLE_AV_PARSERS

Generated by: LCOV version 1.13