LCOV - code coverage report
Current view: top level - filters - dec_faad.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 170 224 75.9 %
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 FAAD2 decoder 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             : 
      29             : #ifdef GPAC_HAS_FAAD
      30             : 
      31             : #ifdef __GNUC__
      32             : #pragma GCC diagnostic ignored "-Wunknown-pragmas"
      33             : #endif
      34             : 
      35             : #if !defined(__GNUC__)
      36             : # if defined(_WIN32_WCE) || defined (WIN32)
      37             : #  pragma comment(lib, "libfaad")
      38             : # endif
      39             : #endif
      40             : 
      41             : #include <neaacdec.h>
      42             : #include <gpac/constants.h>
      43             : #include <gpac/avparse.h>
      44             : 
      45             : 
      46             : typedef struct
      47             : {
      48             :         NeAACDecHandle codec;
      49             :         NeAACDecFrameInfo info; u32 sample_rate, timescale, num_samples;
      50             :         u8 num_channels;
      51             : 
      52             :         GF_FilterPid *ipid, *opid;
      53             :         u32 cfg_crc;
      54             : 
      55             :         Bool signal_mc;
      56             :         Bool is_sbr;
      57             : 
      58             :         u32 channel_mask;
      59             :         char ch_reorder[16];
      60             :         u64 last_cts, first_priming_cts_plus_one;
      61             :         u32 ts_offset;
      62             : } GF_FAADCtx;
      63             : 
      64           2 : static void faaddec_check_mc_config(GF_FAADCtx *ctx)
      65             : {
      66             :         u32 i, channel_mask = 0;
      67          14 :         for (i=0; i<ctx->num_channels; i++) {
      68          12 :                 switch (ctx->info.channel_position[i]) {
      69           2 :                 case FRONT_CHANNEL_CENTER:
      70           2 :                         channel_mask |= GF_AUDIO_CH_FRONT_CENTER;
      71           2 :                         break;
      72           2 :                 case FRONT_CHANNEL_LEFT:
      73           2 :                         channel_mask |= GF_AUDIO_CH_FRONT_LEFT;
      74           2 :                         break;
      75           2 :                 case FRONT_CHANNEL_RIGHT:
      76           2 :                         channel_mask |= GF_AUDIO_CH_FRONT_RIGHT;
      77           2 :                         break;
      78           0 :                 case SIDE_CHANNEL_LEFT:
      79           0 :                         channel_mask |= GF_AUDIO_CH_REAR_SURROUND_LEFT;
      80           0 :                         break;
      81           0 :                 case SIDE_CHANNEL_RIGHT:
      82           0 :                         channel_mask |= GF_AUDIO_CH_REAR_SURROUND_RIGHT;
      83           0 :                         break;
      84           2 :                 case BACK_CHANNEL_LEFT:
      85           2 :                         channel_mask |= GF_AUDIO_CH_SURROUND_LEFT;
      86           2 :                         break;
      87           2 :                 case BACK_CHANNEL_RIGHT:
      88           2 :                         channel_mask |= GF_AUDIO_CH_SURROUND_RIGHT;
      89           2 :                         break;
      90           0 :                 case BACK_CHANNEL_CENTER:
      91           0 :                         channel_mask |= GF_AUDIO_CH_REAR_CENTER;
      92           0 :                         break;
      93           2 :                 case LFE_CHANNEL:
      94           2 :                         channel_mask |= GF_AUDIO_CH_LFE;
      95           2 :                         break;
      96             :                 default:
      97             :                         break;
      98             :                 }
      99             :         }
     100           2 :         if (ctx->channel_mask != channel_mask) {
     101           2 :                 ctx->channel_mask = channel_mask;
     102           2 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT(channel_mask) );
     103             :         }
     104           2 : }
     105             : 
     106           4 : static GF_Err faaddec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     107             : {
     108             :         const GF_PropertyValue *p;
     109           4 :         GF_FAADCtx *ctx = gf_filter_get_udta(filter);
     110             : #ifndef GPAC_DISABLE_AV_PARSERS
     111             :         GF_Err e;
     112             :         GF_M4ADecSpecInfo a_cfg;
     113             : #endif
     114             : 
     115           4 :         if (is_remove) {
     116           0 :                 if (ctx->opid) {
     117           0 :                         gf_filter_pid_remove(ctx->opid);
     118           0 :                         ctx->opid = NULL;
     119             :                 }
     120           0 :                 ctx->ipid = NULL;
     121           0 :                 return GF_OK;
     122             :         }
     123           4 :         if (! gf_filter_pid_check_caps(pid))
     124             :                 return GF_NOT_SUPPORTED;
     125             : 
     126           4 :         if (!ctx->opid) {
     127           4 :                 ctx->opid = gf_filter_pid_new(filter);
     128             :         }
     129             :         //copy properties at init or reconfig
     130           4 :         gf_filter_pid_copy_properties(ctx->opid, pid);
     131           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
     132           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(GF_AUDIO_FMT_S16) );
     133           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, NULL );
     134           4 :         ctx->ipid = pid;
     135             : 
     136             : 
     137           4 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_NO_PRIMING);
     138             :         //force re-priming
     139           4 :         if (p && !p->value.boolean) {
     140           0 :                 ctx->cfg_crc = 0;
     141             :         }
     142             : 
     143           4 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     144           4 :         if (p && p->value.data.ptr && p->value.data.size) {
     145           4 :                 u32 ex_crc = gf_crc_32(p->value.data.ptr, p->value.data.size);
     146           4 :                 if (ctx->cfg_crc == ex_crc)
     147             :                         return GF_OK;
     148             :                 //no need to flush
     149           4 :                 if (ctx->codec) NeAACDecClose(ctx->codec);
     150           4 :                 ctx->codec = NULL;
     151           4 :                 ctx->cfg_crc = ex_crc;
     152             :         } else {
     153           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Reconfiguring but no DSI set, skipping\n"));
     154             :                 return GF_OK;
     155             :         }
     156             : 
     157           4 :         ctx->codec = NeAACDecOpen();
     158           4 :         if (!ctx->codec) {
     159           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error initializing decoder\n"));
     160             :                 return GF_IO_ERR;
     161             :         }
     162             : 
     163           4 :         ctx->ts_offset = 0;
     164           4 :         ctx->first_priming_cts_plus_one = 0;
     165             : 
     166             : #ifndef GPAC_DISABLE_AV_PARSERS
     167           4 :         e = gf_m4a_get_config(p->value.data.ptr, p->value.data.size, &a_cfg);
     168           4 :         if (e) return e;
     169             : #endif
     170           4 :         if (NeAACDecInit2(ctx->codec, (unsigned char *)p->value.data.ptr, p->value.data.size, (unsigned long*)&ctx->sample_rate, (u8*)&ctx->num_channels) < 0)
     171             :         {
     172             : #ifndef GPAC_DISABLE_AV_PARSERS
     173             :                 s8 res;
     174             :                 u8 *dsi, *s_base_object_type;
     175             :                 u32 dsi_len;
     176           0 :                 switch (a_cfg.base_object_type) {
     177             :                 case GF_M4A_AAC_MAIN:
     178             :                         s_base_object_type = gf_stringizer(GF_M4A_AAC_MAIN);
     179             :                         goto base_object_type_error;
     180           0 :                 case GF_M4A_AAC_LC:
     181             :                         s_base_object_type = gf_stringizer(GF_M4A_AAC_LC);
     182           0 :                         goto base_object_type_error;
     183           0 :                 case GF_M4A_AAC_SSR:
     184             :                         s_base_object_type = gf_stringizer(GF_M4A_AAC_SSR);
     185           0 :                         goto base_object_type_error;
     186           0 :                 case GF_M4A_AAC_LTP:
     187             :                         s_base_object_type = gf_stringizer(GF_M4A_AAC_LTP);
     188           0 :                         goto base_object_type_error;
     189           0 :                 case GF_M4A_AAC_SBR:
     190             :                         s_base_object_type = gf_stringizer(GF_M4A_AAC_SBR);
     191           0 :                         goto base_object_type_error;
     192           0 :                 case GF_M4A_AAC_PS:
     193             :                         s_base_object_type = gf_stringizer(GF_M4A_AAC_PS);
     194           0 : base_object_type_error: /*error case*/
     195           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FAAD] Error: unsupported %s format for stream - defaulting to AAC LC\n", s_base_object_type));
     196             :                 default:
     197             :                         break;
     198             :                 }
     199           0 :                 a_cfg.base_object_type = GF_M4A_AAC_LC;
     200           0 :                 a_cfg.has_sbr = GF_FALSE;
     201           0 :                 a_cfg.nb_chan = a_cfg.nb_chan > 2 ? 1 : a_cfg.nb_chan;
     202             : 
     203           0 :                 gf_m4a_write_config(&a_cfg, &dsi, &dsi_len);
     204           0 :                 res = NeAACDecInit2(ctx->codec, (unsigned char *) dsi, dsi_len, (unsigned long *) &ctx->sample_rate, (u8 *) &ctx->num_channels);
     205           0 :                 gf_free(dsi);
     206           0 :                 if (res < 0)
     207             : #endif
     208             :                 {
     209           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error when initializing AAC decoder for stream\n"));
     210           0 :                         return GF_NOT_SUPPORTED;
     211             :                 }
     212             :         }
     213             : 
     214             : #ifndef GPAC_DISABLE_AV_PARSERS
     215           4 :         ctx->is_sbr = a_cfg.has_sbr;
     216             : #endif
     217           4 :         ctx->num_samples = 1024;
     218           4 :         ctx->signal_mc = ctx->num_channels>2 ? GF_TRUE : GF_FALSE;
     219             : 
     220           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(ctx->sample_rate) );
     221           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLES_PER_FRAME, &PROP_UINT(ctx->num_samples) );
     222           4 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(ctx->num_channels) );
     223             : 
     224             : #if 0
     225             :         if (!strcmp(FAAD2_VERSION, "unknown")) {
     226             :                 if (ctx->is_sbr) gf_filter_set_name(filter, "dec_faad:FAAD2-" FAAD2_VERSION "-SBR");
     227             :                 else gf_filter_set_name(filter,  "dec_faad:FAAD2-" FAAD2_VERSION);
     228             :         } else
     229             : #endif
     230             :         {
     231           4 :                 if (ctx->is_sbr) gf_filter_set_name(filter, "dec_faad:FAAD2-SBR");
     232           4 :                 else gf_filter_set_name(filter,  "dec_faad:FAAD2");
     233             :         }
     234           4 :         gf_filter_pid_set_framing_mode(pid, GF_TRUE);
     235             : 
     236             : 
     237           4 :         return GF_OK;
     238             : }
     239             : 
     240          18 : static s8 faaddec_get_channel_pos(GF_FAADCtx *ffd, u32 ch_cfg)
     241             : {
     242             :         u32 i;
     243          84 :         for (i=0; i<ffd->info.channels; i++) {
     244          78 :                 switch (ffd->info.channel_position[i]) {
     245          18 :                 case FRONT_CHANNEL_CENTER:
     246          18 :                         if (ch_cfg==GF_AUDIO_CH_FRONT_CENTER) return i;
     247             :                         break;
     248          16 :                 case FRONT_CHANNEL_LEFT:
     249          16 :                         if (ch_cfg==GF_AUDIO_CH_FRONT_LEFT) return i;
     250             :                         break;
     251          14 :                 case FRONT_CHANNEL_RIGHT:
     252          14 :                         if (ch_cfg==GF_AUDIO_CH_FRONT_RIGHT) return i;
     253             :                         break;
     254           0 :                 case SIDE_CHANNEL_LEFT:
     255           0 :                         if (ch_cfg==GF_AUDIO_CH_REAR_SURROUND_LEFT) return i;
     256             :                         break;
     257           0 :                 case SIDE_CHANNEL_RIGHT:
     258           0 :                         if (ch_cfg==GF_AUDIO_CH_REAR_SURROUND_RIGHT) return i;
     259             :                         break;
     260          12 :                 case BACK_CHANNEL_LEFT:
     261          12 :                         if (ch_cfg==GF_AUDIO_CH_SURROUND_LEFT) return i;
     262             :                         break;
     263          10 :                 case BACK_CHANNEL_RIGHT:
     264          10 :                         if (ch_cfg==GF_AUDIO_CH_SURROUND_RIGHT) return i;
     265             :                         break;
     266           0 :                 case BACK_CHANNEL_CENTER:
     267           0 :                         if (ch_cfg==GF_AUDIO_CH_REAR_CENTER) return i;
     268             :                         break;
     269           8 :                 case LFE_CHANNEL:
     270           8 :                         if (ch_cfg==GF_AUDIO_CH_LFE) return i;
     271             :                         break;
     272             :                 }
     273             :         }
     274             :         return -1;
     275             : }
     276             : 
     277        1122 : static GF_Err faaddec_process(GF_Filter *filter)
     278             : {
     279        1122 :         GF_FAADCtx *ctx = gf_filter_get_udta(filter);
     280             :         void *buffer;
     281             :         u8 *output;
     282             :         u32 i, j;
     283             :         Bool is_eos = GF_FALSE;
     284             :         GF_FilterPacket *dst_pck;
     285        1122 :         GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
     286             : 
     287        1122 :         if (!pck) {
     288         586 :                 is_eos = gf_filter_pid_is_eos(ctx->ipid);
     289         586 :                 if (!is_eos) return GF_OK;
     290             :         }
     291             : 
     292         538 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Decoding AU\n"));
     293         538 :         if (!pck) {
     294           2 :                 buffer = NeAACDecDecode(ctx->codec, &ctx->info, NULL, 0);
     295             :         } else {
     296             :                 Bool start, end;
     297             :                 u32 size;
     298         536 :                 const char *data = gf_filter_pck_get_data(pck, &size);
     299         536 :                 buffer = NeAACDecDecode(ctx->codec, &ctx->info, (char *) data, size);
     300             : 
     301         536 :                 gf_filter_pck_get_framing(pck, &start, &end);
     302             :                 assert(start && end);
     303             :         }
     304             : 
     305         538 :         if (ctx->info.error>0) {
     306           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FAAD] Error decoding AU %s\n", NeAACDecGetErrorMessage(ctx->info.error) ));
     307           0 :                 if (pck) gf_filter_pid_drop_packet(ctx->ipid);
     308             :                 return GF_NON_COMPLIANT_BITSTREAM;
     309             :         }
     310         538 :         if (!ctx->info.samples || !buffer || !ctx->info.bytesconsumed) {
     311           6 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] empty/non complete AU\n"));
     312           6 :                 if (is_eos) gf_filter_pid_set_eos(ctx->opid);
     313           6 :                 if (pck) {
     314           4 :                         if (!ctx->first_priming_cts_plus_one) {
     315           4 :                                 ctx->first_priming_cts_plus_one = gf_filter_pck_get_cts(pck) + 1;
     316             : 
     317             :                         }
     318           4 :                         gf_filter_pid_drop_packet(ctx->ipid);
     319             :                 }
     320             :                 return GF_OK;
     321             :         }
     322         532 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] AU decoded\n"));
     323             : 
     324             :         /*FAAD froces us to decode a frame to get channel cfg*/
     325         532 :         if (ctx->signal_mc) {
     326             :                 s32 ch, idx;
     327           2 :                 ctx->signal_mc = GF_FALSE;
     328             :                 idx = 0;
     329             :                 /*NOW WATCH OUT!! FAAD may very well decide to output more channels than indicated!!!*/
     330           2 :                 ctx->num_channels = ctx->info.channels;
     331             : 
     332             :                 /*get cfg*/
     333           2 :                 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_FRONT_LEFT);
     334           2 :                 if (ch>=0) {
     335           2 :                         ctx->ch_reorder[idx] = ch;
     336             :                         idx++;
     337             :                 }
     338           2 :                 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_FRONT_RIGHT);
     339           2 :                 if (ch>=0) {
     340           2 :                         ctx->ch_reorder[idx] = ch;
     341           2 :                         idx++;
     342             :                 }
     343           2 :                 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_FRONT_CENTER);
     344           2 :                 if (ch>=0) {
     345           2 :                         ctx->ch_reorder[idx] = ch;
     346           2 :                         idx++;
     347             :                 }
     348           2 :                 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_LFE);
     349           2 :                 if (ch>=0) {
     350           2 :                         ctx->ch_reorder[idx] = ch;
     351           2 :                         idx++;
     352             :                 }
     353           2 :                 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_SURROUND_LEFT);
     354           2 :                 if (ch>=0) {
     355           2 :                         ctx->ch_reorder[idx] = ch;
     356           2 :                         idx++;
     357             :                 }
     358           2 :                 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_SURROUND_RIGHT);
     359           2 :                 if (ch>=0) {
     360           2 :                         ctx->ch_reorder[idx] = ch;
     361           2 :                         idx++;
     362             :                 }
     363           2 :                 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_REAR_CENTER);
     364           2 :                 if (ch>=0) {
     365           0 :                         ctx->ch_reorder[idx] = ch;
     366           0 :                         idx++;
     367             :                 }
     368           2 :                 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_REAR_SURROUND_LEFT);
     369           2 :                 if (ch>=0) {
     370           0 :                         ctx->ch_reorder[idx] = ch;
     371           0 :                         idx++;
     372             :                 }
     373           2 :                 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_REAR_SURROUND_RIGHT);
     374           2 :                 if (ch>=0) {
     375           0 :                         ctx->ch_reorder[idx] = ch;
     376             :                         //last one, no need to increment idx++;
     377             :                 }
     378           2 :                 faaddec_check_mc_config(ctx);
     379             :         }
     380             : 
     381         532 :         if (ctx->timescale && pck && gf_filter_pid_eos_received(ctx->ipid)) {
     382          24 :                 u64 odur = gf_filter_pck_get_duration(pck);
     383          24 :                 if (ctx->timescale != ctx->sample_rate) {
     384           7 :                         odur *= ctx->sample_rate;
     385           7 :                         odur /= ctx->timescale;
     386             :                 }
     387          24 :                 if (odur * ctx->info.channels < ctx->info.samples) {
     388           0 :                         ctx->info.samples = (unsigned long) (odur * ctx->info.channels);
     389             :                 }
     390             :         }
     391             : 
     392         532 :         dst_pck = gf_filter_pck_new_alloc(ctx->opid, (u32) (sizeof(short) * ctx->info.samples), &output);
     393         532 :         if (!dst_pck) {
     394           0 :                 if (pck) gf_filter_pid_drop_packet(ctx->ipid);
     395             :                 return GF_OUT_OF_MEM;
     396             :         }
     397         532 :         if (pck) {
     398         532 :                 ctx->last_cts = gf_filter_pck_get_cts(pck);
     399         532 :                 if (ctx->first_priming_cts_plus_one && !ctx->ts_offset) {
     400           4 :                         if (ctx->last_cts + 1 >= ctx->first_priming_cts_plus_one)
     401           4 :                                 ctx->ts_offset = (u32) (ctx->last_cts - (ctx->first_priming_cts_plus_one-1));
     402             :                         else
     403             :                                 //neg speed
     404           0 :                                 ctx->ts_offset = (u32) ((ctx->first_priming_cts_plus_one-1) - ctx->last_cts);
     405           4 :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DELAY, NULL);
     406             :                 }
     407         532 :                 ctx->last_cts -= ctx->ts_offset;
     408         532 :                 ctx->timescale = gf_filter_pck_get_timescale(pck);
     409         532 :                 gf_filter_pck_merge_properties(pck, dst_pck);
     410             :         }
     411         532 :         gf_filter_pck_set_cts(dst_pck, ctx->last_cts);
     412         532 :         if (ctx->timescale != ctx->sample_rate) {
     413         261 :                 u64 dur =ctx->info.samples * ctx->timescale;
     414         261 :                 dur /= ctx->sample_rate;
     415         261 :                 gf_filter_pck_set_duration(dst_pck, (u32) dur);
     416         261 :                 ctx->last_cts += dur;
     417             :         } else {
     418         271 :                 gf_filter_pck_set_duration(dst_pck, (u32) ctx->info.samples);
     419         271 :                 ctx->last_cts += ctx->info.samples;
     420             :         }
     421             :         /*we assume left/right order*/
     422         532 :         if (ctx->num_channels<=2) {
     423         271 :                 memcpy(output, buffer, sizeof(short)* ctx->info.samples);
     424             :         } else {
     425             :                 unsigned short *conv_in, *conv_out;
     426             :                 conv_in = (unsigned short *) buffer;
     427         261 :                 conv_out = (unsigned short *) output;
     428      534789 :                 for (i=0; i<ctx->info.samples; i+=ctx->info.channels) {
     429     3207168 :                         for (j=0; j<ctx->info.channels; j++) {
     430     3207168 :                                 conv_out[i + j] = conv_in[i + ctx->ch_reorder[j]];
     431             :                         }
     432             :                 }
     433             :         }
     434         532 :         gf_filter_pck_send(dst_pck);
     435         532 :         if (pck) gf_filter_pid_drop_packet(ctx->ipid);
     436             :         return GF_OK;
     437             : }
     438             : 
     439           4 : static void faaddec_finalize(GF_Filter *filter)
     440             : {
     441           4 :         GF_FAADCtx *ctx = gf_filter_get_udta(filter);
     442           4 :         if (ctx->codec) NeAACDecClose(ctx->codec);
     443           4 : }
     444             : static const GF_FilterCapability FAADCaps[] =
     445             : {
     446             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     447             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
     448             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
     449             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
     450             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
     451             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
     452             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
     453             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
     454             : };
     455             : 
     456             : GF_FilterRegister FAADRegister = {
     457             :         .name = "faad",
     458             :         GF_FS_SET_DESCRIPTION("FAAD decoder")
     459             :         GF_FS_SET_HELP("This filter decodes AAC streams through faad library.")
     460             :         .private_size = sizeof(GF_FAADCtx),
     461             :         .priority = 200, //lower priority than ffdec, as faad support for multichannel is not really good
     462             :         SETCAPS(FAADCaps),
     463             :         .configure_pid = faaddec_configure_pid,
     464             :         .finalize = faaddec_finalize,
     465             :         .process = faaddec_process,
     466             : };
     467             : 
     468             : #endif
     469             : 
     470        2877 : const GF_FilterRegister *faad_register(GF_FilterSession *session)
     471             : {
     472             : #ifdef GPAC_HAS_FAAD
     473        2877 :         return &FAADRegister;
     474             : #else
     475             :         return NULL;
     476             : #endif
     477             : }

Generated by: LCOV version 1.13