LCOV - code coverage report
Current view: top level - filters - rewrite_adts.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 144 176 81.8 %
Date: 2021-04-29 23:48:07 Functions: 6 6 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 write filter
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/filters.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/bitstream.h>
      29             : 
      30             : #include <gpac/avparse.h>
      31             : 
      32             : 
      33             : typedef struct
      34             : {
      35             :         //opts
      36             :         Bool exporter, mpeg2;
      37             : 
      38             :         //only one input pid declared
      39             :         GF_FilterPid *ipid;
      40             :         //only one output pid declared
      41             :         GF_FilterPid *opid;
      42             : 
      43             :         u32 codecid, channels, sr_idx, aac_type, ch_cfg;
      44             : 
      45             :         Bool is_latm;
      46             : 
      47             :         GF_BitStream *bs_w;
      48             : 
      49             : #ifndef GPAC_DISABLE_AV_PARSERS
      50             :         GF_M4ADecSpecInfo acfg;
      51             :         u8 *pce;
      52             :         u32 pce_size;
      53             : #else
      54             :         u8 *dsi;
      55             :         u32 dsi_size;
      56             : #endif
      57             :         u32 dsi_crc;
      58             :         Bool update_dsi;
      59             :         GF_Fraction fdsi;
      60             :         u64 last_cts;
      61             :         u32 timescale;
      62             : } GF_ADTSMxCtx;
      63             : 
      64             : 
      65             : 
      66             : 
      67          13 : GF_Err adtsmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
      68             : {
      69             :         u32 i, sr, chan_cfg=0;
      70             :         Bool patch_channels = GF_FALSE;
      71             :         const GF_PropertyValue *p;
      72          13 :         GF_ADTSMxCtx *ctx = gf_filter_get_udta(filter);
      73             : 
      74          13 :         if (is_remove) {
      75           0 :                 ctx->ipid = NULL;
      76           0 :                 if (ctx->opid) {
      77           0 :                         gf_filter_pid_remove(ctx->opid);
      78           0 :                         ctx->opid = NULL;
      79             :                 }
      80             :                 return GF_OK;
      81             :         }
      82          13 :         if (! gf_filter_pid_check_caps(pid))
      83             :                 return GF_NOT_SUPPORTED;
      84             : 
      85          13 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
      86          13 :         if (!p) return GF_NOT_SUPPORTED;
      87          13 :         ctx->codecid = p->value.uint;
      88             : 
      89          13 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAMPLE_RATE);
      90          13 :         if (!p) return GF_NOT_SUPPORTED;
      91          13 :         sr = p->value.uint;
      92             : 
      93          13 :         ctx->channels = 0;
      94          13 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_NUM_CHANNELS);
      95          13 :         if (p)
      96          13 :                 ctx->channels = p->value.uint;
      97             : 
      98             : #ifndef GPAC_DISABLE_AV_PARSERS
      99          13 :         memset(&ctx->acfg, 0, sizeof(GF_M4ADecSpecInfo));
     100             : #endif
     101             : 
     102          13 :         ctx->aac_type = 0;
     103          13 :         if (ctx->is_latm) {
     104             :                 u32 crc;
     105           2 :                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     106           2 :                 if (!p) return GF_NOT_SUPPORTED;
     107             : 
     108           2 :                 crc = gf_crc_32(p->value.data.ptr, p->value.data.size);
     109           2 :                 if (crc != ctx->dsi_crc) {
     110           2 :                         ctx->dsi_crc = crc;
     111             : #ifndef GPAC_DISABLE_AV_PARSERS
     112           2 :                         gf_m4a_get_config(p->value.data.ptr, p->value.data.size, &ctx->acfg);
     113             : #endif
     114           2 :                         ctx->update_dsi = GF_TRUE;
     115             :                 }
     116             : 
     117           2 :                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_TIMESCALE);
     118           2 :                 if (!p) return GF_NOT_SUPPORTED;
     119           2 :                 ctx->timescale = p->value.uint;
     120             : 
     121          11 :         } else if (ctx->codecid==GF_CODECID_AAC_MPEG4) {
     122             :                 //setup default config
     123          11 :                 chan_cfg = ctx->channels;
     124          11 :                 if (chan_cfg==8)
     125             :                         chan_cfg = 7;
     126             : 
     127          11 :                 if (!ctx->mpeg2) {
     128             : #ifndef GPAC_DISABLE_AV_PARSERS
     129          11 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     130          11 :                         if (p) {
     131           9 :                                 gf_m4a_get_config(p->value.data.ptr, p->value.data.size, &ctx->acfg);
     132           9 :                                 ctx->aac_type = ctx->acfg.base_object_type - 1;
     133           9 :                                 chan_cfg = ctx->acfg.chan_cfg;
     134           9 :                                 sr = ctx->acfg.base_sr;
     135             :                         } else
     136             : #endif
     137             :                         {
     138           2 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[RFADTS] no AAC decoder config, assuming AAC-LC\n"));
     139           2 :                                 ctx->aac_type = GF_M4A_AAC_LC;
     140             : 
     141           2 :                                 if (!ctx->channels) {
     142           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[RFADTS] no channel config found for ADTS, forcing stereo\n"));
     143           0 :                                         chan_cfg = ctx->channels = 2;
     144             :                                         patch_channels = GF_TRUE;
     145             :                                 }
     146             : 
     147           2 :                                 if (!chan_cfg) {
     148           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[RFADTS] Unkown channel config, will not be able to signal it in ADTS\n"));
     149             :                                 }
     150             :                         }
     151             :                 }
     152             : 
     153          11 :                 if (chan_cfg>7) {
     154           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[RFADTS] Unkown channel config, will not be able to signal it in ADTS\n"));
     155             :                         chan_cfg = 0;
     156             :                 }
     157             :         } else {
     158           0 :                 ctx->aac_type = ctx->codecid - GF_CODECID_AAC_MPEG2_MP;
     159             :         }
     160             : 
     161             : #ifndef GPAC_DISABLE_AV_PARSERS
     162          13 :         if (ctx->channels && ctx->acfg.nb_chan && (ctx->channels != ctx->acfg.nb_chan)) {
     163             :                 //do not warn here, as most MP4 files will use nbChan=2 for multichan
     164           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[RFADTS] Mismatch between container number of channels (%d) and AAC config (%d), using AAC config\n", ctx->channels, ctx->acfg.nb_chan));
     165           0 :                 ctx->channels = ctx->acfg.nb_chan;
     166             :                 patch_channels = GF_TRUE;
     167             :         }
     168          13 :         if ((ctx->acfg.base_object_type==2) && (ctx->acfg.base_sr!=sr)) {
     169           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[RFADTS] Mismatch between container samplerate (%d) and AAC config SBR base samplerate (%d), using AAC config\n", sr, ctx->acfg.base_sr));
     170           0 :                 sr = ctx->acfg.base_sr;
     171             :         }
     172          13 :         if (!ctx->acfg.chan_cfg && ctx->acfg.program_config_element_present) {
     173           0 :                 GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     174           0 :                 gf_m4a_write_program_config_element_bs(bs, &ctx->acfg);
     175           0 :                 if (ctx->pce) gf_free(ctx->pce);
     176           0 :                 ctx->pce = NULL;
     177           0 :                 gf_bs_get_content(bs, &ctx->pce, &ctx->pce_size);
     178           0 :                 gf_bs_del(bs);
     179             : 
     180           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[RFADTS] ADTS will use multiple raw blocks to signal channel configuration\n"));
     181             :         }
     182             : #else
     183             : 
     184             :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     185             :         if (!p) return GF_NOT_SUPPORTED;
     186             :         ctx->dsi = p->value.data.ptr;
     187             :         ctx->dsi_size = p->value.data.size;
     188             : #endif
     189             : 
     190             : 
     191          13 :         ctx->ch_cfg = chan_cfg;
     192             : 
     193          68 :         for (i=0; i<16; i++) {
     194          68 :                 if (GF_M4ASampleRates[i] == (u32) sr) {
     195          13 :                         ctx->sr_idx = i;
     196          13 :                         break;
     197             :                 }
     198             :         }
     199             : 
     200             : 
     201          13 :         if (!ctx->opid) {
     202          11 :                 ctx->opid = gf_filter_pid_new(filter);
     203             :         }
     204          13 :         ctx->ipid = pid;
     205          13 :         gf_filter_pid_copy_properties(ctx->opid, pid);
     206          13 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, NULL);
     207          13 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL(GF_TRUE) );
     208          13 :         if (ctx->is_latm)
     209           2 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED_LATM, &PROP_BOOL(GF_TRUE) );
     210             : 
     211          13 :         if (patch_channels)
     212           0 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(ctx->channels));
     213          13 :         gf_filter_pid_set_framing_mode(ctx->ipid, GF_TRUE);
     214          13 :         return GF_OK;
     215             : }
     216             : 
     217             : 
     218             : 
     219        2772 : GF_Err adtsmx_process(GF_Filter *filter)
     220             : {
     221        2772 :         GF_ADTSMxCtx *ctx = gf_filter_get_udta(filter);
     222             :         GF_FilterPacket *pck, *dst_pck;
     223             :         u8 *data, *output;
     224             :         u32 pck_size, size;
     225             : 
     226        2772 :         pck = gf_filter_pid_get_packet(ctx->ipid);
     227        2772 :         if (!pck) {
     228         374 :                 if (gf_filter_pid_is_eos(ctx->ipid)) {
     229          24 :                         gf_filter_pid_set_eos(ctx->opid);
     230          24 :                         return GF_EOS;
     231             :                 }
     232             :                 return GF_OK;
     233             :         }
     234             : 
     235        2398 :         data = (char *) gf_filter_pck_get_data(pck, &pck_size);
     236             : 
     237        2398 :         if (ctx->is_latm) {
     238             :                 u32 asize;
     239             : 
     240         377 :                 size = pck_size+20;
     241         377 :                 dst_pck = gf_filter_pck_new_alloc(ctx->opid, size, &output);
     242         377 :                 if (!dst_pck) return GF_OUT_OF_MEM;
     243             : 
     244         377 :                 if (!ctx->bs_w) ctx->bs_w = gf_bs_new(output, size, GF_BITSTREAM_WRITE);
     245         375 :                 else gf_bs_reassign_buffer(ctx->bs_w, output, size);
     246             : 
     247         377 :                 gf_bs_write_int(ctx->bs_w, 0x2B7, 11);
     248         377 :                 gf_bs_write_int(ctx->bs_w, 0, 13);
     249         377 :                 if (ctx->codecid==GF_CODECID_USAC) {
     250           0 :                         GF_FilterSAPType sap = gf_filter_pck_get_sap(pck);
     251           0 :                         if ((sap == GF_FILTER_SAP_1) || (sap == GF_FILTER_SAP_4_PROL)) {
     252           0 :                                 ctx->update_dsi = GF_TRUE;
     253             :                         }
     254             :                 } else {
     255             : 
     256         377 :                         if (ctx->fdsi.num && ctx->fdsi.den) {
     257           0 :                                 u64 ts = gf_filter_pck_get_cts(pck);
     258           0 :                                 if (ts != GF_FILTER_NO_TS) {
     259           0 :                                         if ((ts - ctx->last_cts) * ctx->fdsi.den >= ctx->timescale * ctx->fdsi.num) {
     260           0 :                                                 ctx->last_cts = ts;
     261           0 :                                                 ctx->update_dsi = GF_TRUE;
     262             :                                         }
     263             :                                 }
     264             :                         }
     265             :                 }
     266             :                 /*same mux config = 0 (refresh aac config)*/
     267         377 :                 if (ctx->update_dsi) {
     268           2 :                         gf_bs_write_int(ctx->bs_w, 0, 1);
     269             :                         /*mux config */
     270           2 :                         gf_bs_write_int(ctx->bs_w, 0, 1);/*audio mux version = 0*/
     271           2 :                         gf_bs_write_int(ctx->bs_w, 1, 1);/*allStreamsSameTimeFraming*/
     272           2 :                         gf_bs_write_int(ctx->bs_w, 0, 6);/*numSubFrames*/
     273           2 :                         gf_bs_write_int(ctx->bs_w, 0, 4);/*numProgram*/
     274           2 :                         gf_bs_write_int(ctx->bs_w, 0, 3);/*numLayer prog 1*/
     275             : 
     276             : #ifndef GPAC_DISABLE_AV_PARSERS
     277           2 :                         gf_m4a_write_config_bs(ctx->bs_w, &ctx->acfg);
     278             : #else
     279             :                         gf_bs_write_data(ctx->bs_w, ctx->dsi, ctx->dsi_size);
     280             : #endif
     281           2 :                         gf_bs_write_int(ctx->bs_w, 0, 3);/*frameLengthType*/
     282           2 :                         gf_bs_write_int(ctx->bs_w, 0, 8);/*latmBufferFullness*/
     283           2 :                         gf_bs_write_int(ctx->bs_w, 0, 1);/*other data present*/
     284           2 :                         gf_bs_write_int(ctx->bs_w, 0, 1);/*crcCheckPresent*/
     285             : 
     286           2 :                         ctx->update_dsi = 0;
     287             :                 } else {
     288         375 :                         gf_bs_write_int(ctx->bs_w, 1, 1);
     289             :                 }
     290             :                 /*write payloadLengthInfo*/
     291         377 :                 asize = pck_size;
     292             :                 while (1) {
     293         745 :                         if (asize>=255) {
     294         184 :                                 gf_bs_write_int(ctx->bs_w, 255, 8);
     295         184 :                                 asize -= 255;
     296             :                         } else {
     297         377 :                                 gf_bs_write_int(ctx->bs_w, asize, 8);
     298             :                                 break;
     299             :                         }
     300             :                 }
     301         377 :                 gf_bs_write_data(ctx->bs_w, data, pck_size);
     302         377 :                 gf_bs_align(ctx->bs_w);
     303             : 
     304         377 :                 size = (u32) gf_bs_get_position(ctx->bs_w);
     305         377 :                 gf_filter_pck_truncate(dst_pck, size);
     306             : 
     307             :                 /*rewrite LATM frame header*/
     308         377 :                 output[1] |= ((size-3) >> 8 ) & 0x1F;
     309         377 :                 output[2] = (size-3) & 0xFF;
     310             : 
     311             :         } else {
     312             :                 u32 nb_blocks = 0;
     313        2021 :                 size = pck_size+7;
     314             : #ifndef GPAC_DISABLE_AV_PARSERS
     315        2021 :                 if (! ctx->acfg.chan_cfg && ctx->pce_size) {
     316             :                         nb_blocks = 2;
     317           0 :                         size += ctx->pce_size;
     318             :                 }
     319             : #endif
     320        2021 :                 dst_pck = gf_filter_pck_new_alloc(ctx->opid, size, &output);
     321        2021 :                 if (!dst_pck) return GF_OUT_OF_MEM;
     322             : 
     323        2021 :                 if (!ctx->bs_w) ctx->bs_w = gf_bs_new(output, size, GF_BITSTREAM_WRITE);
     324        2012 :                 else gf_bs_reassign_buffer(ctx->bs_w, output, size);
     325             : 
     326        2021 :                 gf_bs_write_int(ctx->bs_w, 0xFFF, 12);/*sync*/
     327        2021 :                 gf_bs_write_int(ctx->bs_w, (ctx->mpeg2==1) ? 1 : 0, 1);/*mpeg2 aac*/
     328        2021 :                 gf_bs_write_int(ctx->bs_w, 0, 2); /*layer*/
     329        2021 :                 gf_bs_write_int(ctx->bs_w, 1, 1); /* protection_absent*/
     330        2021 :                 gf_bs_write_int(ctx->bs_w, ctx->aac_type, 2);
     331        2021 :                 gf_bs_write_int(ctx->bs_w, ctx->sr_idx, 4);
     332        2021 :                 gf_bs_write_int(ctx->bs_w, 0, 1);
     333        2021 :                 gf_bs_write_int(ctx->bs_w, ctx->ch_cfg, 3);
     334        2021 :                 gf_bs_write_int(ctx->bs_w, 0, 4);
     335        2021 :                 gf_bs_write_int(ctx->bs_w, size, 13);
     336        2021 :                 gf_bs_write_int(ctx->bs_w, 0x7FF, 11);
     337             : 
     338        2021 :                 gf_bs_write_int(ctx->bs_w, nb_blocks, 2);
     339             : 
     340        2021 :                 output += 7;
     341             : #ifndef GPAC_DISABLE_AV_PARSERS
     342        2021 :                 if (nb_blocks) {
     343           0 :                         memcpy(output, ctx->pce, ctx->pce_size);
     344           0 :                         output += ctx->pce_size;
     345             :                 }
     346             : #endif
     347        2021 :                 memcpy(output, data, pck_size);
     348             :         }
     349             : 
     350        2398 :         gf_filter_pck_merge_properties(pck, dst_pck);
     351        2398 :         gf_filter_pck_set_byte_offset(dst_pck, GF_FILTER_NO_BO);
     352             : 
     353             : 
     354        2398 :         gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
     355             : 
     356        2398 :         gf_filter_pck_send(dst_pck);
     357        2398 :         gf_filter_pid_drop_packet(ctx->ipid);
     358        2398 :         return GF_OK;
     359             : }
     360             : 
     361          11 : static void adtsmx_finalize(GF_Filter *filter)
     362             : {
     363          11 :         GF_ADTSMxCtx *ctx = gf_filter_get_udta(filter);
     364          11 :         if (ctx->bs_w) gf_bs_del(ctx->bs_w);
     365          11 :         if (ctx->pce) gf_free(ctx->pce);
     366          11 : }
     367             : 
     368             : static const GF_FilterCapability ADTSMxCaps[] =
     369             : {
     370             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     371             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
     372             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT_OPT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
     373             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT_OPT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
     374             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT_OPT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
     375             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
     376             :         CAP_BOOL(GF_CAPS_OUTPUT, GF_PROP_PID_UNFRAMED, GF_TRUE),
     377             : };
     378             : 
     379             : 
     380             : #define OFFS(_n)        #_n, offsetof(GF_ADTSMxCtx, _n)
     381             : static const GF_FilterArgs ADTSMxArgs[] =
     382             : {
     383             :         { OFFS(mpeg2), "signal as MPEG2 AAC\n"
     384             :         "- auto: selects based on AAC profile\n"
     385             :         "- no: always signals as MPEG-4 AAC\n"
     386             :         "- yes: always signals as MPEG-2 AAC"
     387             :         "", GF_PROP_UINT, "auto", "auto|no|yes", GF_FS_ARG_HINT_ADVANCED},
     388             :         {0}
     389             : };
     390             : 
     391             : 
     392             : GF_FilterRegister ADTSMxRegister = {
     393             :         .name = "ufadts",
     394             :         GF_FS_SET_DESCRIPTION("ADTS writer")
     395             :         GF_FS_SET_HELP("This filter converts AAC streams into ADTS encapsulated data.")
     396             :         .private_size = sizeof(GF_ADTSMxCtx),
     397             :         .args = ADTSMxArgs,
     398             :         .finalize = adtsmx_finalize,
     399             :         SETCAPS(ADTSMxCaps),
     400             :         .configure_pid = adtsmx_configure_pid,
     401             :         .process = adtsmx_process
     402             : };
     403             : 
     404             : 
     405        2877 : const GF_FilterRegister *adtsmx_register(GF_FilterSession *session)
     406             : {
     407        2877 :         return &ADTSMxRegister;
     408             : }
     409             : 
     410           2 : static GF_Err latmmx_initialize(GF_Filter*filter)
     411             : {
     412           2 :         GF_ADTSMxCtx *ctx = gf_filter_get_udta(filter);
     413           2 :         ctx->is_latm = GF_TRUE;
     414           2 :         return GF_OK;
     415             : }
     416             : 
     417             : #define OFFS(_n)        #_n, offsetof(GF_ADTSMxCtx, _n)
     418             : static const GF_FilterArgs LATMMxArgs[] =
     419             : {
     420             :         { OFFS(fdsi), "set delay between two LATM Audio Config", GF_PROP_FRACTION, "0", NULL, GF_FS_ARG_HINT_ADVANCED},
     421             :         {0}
     422             : };
     423             : 
     424             : 
     425             : static const GF_FilterCapability LATMMxCaps[] =
     426             : {
     427             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     428             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
     429             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
     430             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
     431             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
     432             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_USAC),
     433             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
     434             :         CAP_BOOL(GF_CAPS_OUTPUT, GF_PROP_PID_UNFRAMED_LATM, GF_TRUE),
     435             : };
     436             : 
     437             : GF_FilterRegister LATMMxRegister = {
     438             :         .name = "uflatm",
     439             :         GF_FS_SET_DESCRIPTION("Raw AAC to LATM writer")
     440             :         GF_FS_SET_HELP("This filter converts AAC streams into LATM encapsulated data.")
     441             :         .private_size = sizeof(GF_ADTSMxCtx),
     442             :         .args = LATMMxArgs,
     443             :         .initialize = latmmx_initialize,
     444             :         .finalize = adtsmx_finalize,
     445             :         SETCAPS(LATMMxCaps),
     446             :         .configure_pid = adtsmx_configure_pid,
     447             :         .process = adtsmx_process
     448             : };
     449             : 
     450             : 
     451        2877 : const GF_FilterRegister *latm_mx_register(GF_FilterSession *session)
     452             : {
     453        2877 :         return &LATMMxRegister;
     454             : }

Generated by: LCOV version 1.13