LCOV - code coverage report
Current view: top level - src/libavcodec - atrac3plusdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 121 188 64.4 %
Date: 2017-03-25 17:02:41 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * ATRAC3+ compatible decoder
       3             :  *
       4             :  * Copyright (c) 2010-2013 Maxim Poliakovski
       5             :  *
       6             :  * This file is part of FFmpeg.
       7             :  *
       8             :  * FFmpeg is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public
      10             :  * License as published by the Free Software Foundation; either
      11             :  * version 2.1 of the License, or (at your option) any later version.
      12             :  *
      13             :  * FFmpeg is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with FFmpeg; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : /**
      24             :  * @file
      25             :  * Sony ATRAC3+ compatible decoder.
      26             :  *
      27             :  * Container formats used to store its data:
      28             :  * RIFF WAV (.at3) and Sony OpenMG (.oma, .aa3).
      29             :  *
      30             :  * Technical description of this codec can be found here:
      31             :  * http://wiki.multimedia.cx/index.php?title=ATRAC3plus
      32             :  *
      33             :  * Kudos to Benjamin Larsson and Michael Karcher
      34             :  * for their precious technical help!
      35             :  */
      36             : 
      37             : #include <stdint.h>
      38             : #include <string.h>
      39             : 
      40             : #include "libavutil/channel_layout.h"
      41             : #include "libavutil/float_dsp.h"
      42             : #include "avcodec.h"
      43             : #include "get_bits.h"
      44             : #include "internal.h"
      45             : #include "atrac.h"
      46             : #include "atrac3plus.h"
      47             : 
      48             : typedef struct ATRAC3PContext {
      49             :     GetBitContext gb;
      50             :     AVFloatDSPContext *fdsp;
      51             : 
      52             :     DECLARE_ALIGNED(32, float, samples)[2][ATRAC3P_FRAME_SAMPLES];  ///< quantized MDCT spectrum
      53             :     DECLARE_ALIGNED(32, float, mdct_buf)[2][ATRAC3P_FRAME_SAMPLES]; ///< output of the IMDCT
      54             :     DECLARE_ALIGNED(32, float, time_buf)[2][ATRAC3P_FRAME_SAMPLES]; ///< output of the gain compensation
      55             :     DECLARE_ALIGNED(32, float, outp_buf)[2][ATRAC3P_FRAME_SAMPLES];
      56             : 
      57             :     AtracGCContext gainc_ctx;   ///< gain compensation context
      58             :     FFTContext mdct_ctx;
      59             :     FFTContext ipqf_dct_ctx;    ///< IDCT context used by IPQF
      60             : 
      61             :     Atrac3pChanUnitCtx *ch_units;   ///< global channel units
      62             : 
      63             :     int num_channel_blocks;     ///< number of channel blocks
      64             :     uint8_t channel_blocks[5];  ///< channel configuration descriptor
      65             :     uint64_t my_channel_layout; ///< current channel layout
      66             : } ATRAC3PContext;
      67             : 
      68           4 : static av_cold int atrac3p_decode_close(AVCodecContext *avctx)
      69             : {
      70           4 :     ATRAC3PContext *ctx = avctx->priv_data;
      71             : 
      72           4 :     av_freep(&ctx->ch_units);
      73           4 :     av_freep(&ctx->fdsp);
      74             : 
      75           4 :     ff_mdct_end(&ctx->mdct_ctx);
      76           4 :     ff_mdct_end(&ctx->ipqf_dct_ctx);
      77             : 
      78           4 :     return 0;
      79             : }
      80             : 
      81           4 : static av_cold int set_channel_params(ATRAC3PContext *ctx,
      82             :                                       AVCodecContext *avctx)
      83             : {
      84           4 :     memset(ctx->channel_blocks, 0, sizeof(ctx->channel_blocks));
      85             : 
      86           4 :     switch (avctx->channels) {
      87             :     case 1:
      88           0 :         if (avctx->channel_layout != AV_CH_FRONT_LEFT)
      89           0 :             avctx->channel_layout = AV_CH_LAYOUT_MONO;
      90             : 
      91           0 :         ctx->num_channel_blocks = 1;
      92           0 :         ctx->channel_blocks[0]  = CH_UNIT_MONO;
      93           0 :         break;
      94             :     case 2:
      95           4 :         avctx->channel_layout   = AV_CH_LAYOUT_STEREO;
      96           4 :         ctx->num_channel_blocks = 1;
      97           4 :         ctx->channel_blocks[0]  = CH_UNIT_STEREO;
      98           4 :         break;
      99             :     case 3:
     100           0 :         avctx->channel_layout   = AV_CH_LAYOUT_SURROUND;
     101           0 :         ctx->num_channel_blocks = 2;
     102           0 :         ctx->channel_blocks[0]  = CH_UNIT_STEREO;
     103           0 :         ctx->channel_blocks[1]  = CH_UNIT_MONO;
     104           0 :         break;
     105             :     case 4:
     106           0 :         avctx->channel_layout   = AV_CH_LAYOUT_4POINT0;
     107           0 :         ctx->num_channel_blocks = 3;
     108           0 :         ctx->channel_blocks[0]  = CH_UNIT_STEREO;
     109           0 :         ctx->channel_blocks[1]  = CH_UNIT_MONO;
     110           0 :         ctx->channel_blocks[2]  = CH_UNIT_MONO;
     111           0 :         break;
     112             :     case 6:
     113           0 :         avctx->channel_layout   = AV_CH_LAYOUT_5POINT1_BACK;
     114           0 :         ctx->num_channel_blocks = 4;
     115           0 :         ctx->channel_blocks[0]  = CH_UNIT_STEREO;
     116           0 :         ctx->channel_blocks[1]  = CH_UNIT_MONO;
     117           0 :         ctx->channel_blocks[2]  = CH_UNIT_STEREO;
     118           0 :         ctx->channel_blocks[3]  = CH_UNIT_MONO;
     119           0 :         break;
     120             :     case 7:
     121           0 :         avctx->channel_layout   = AV_CH_LAYOUT_6POINT1_BACK;
     122           0 :         ctx->num_channel_blocks = 5;
     123           0 :         ctx->channel_blocks[0]  = CH_UNIT_STEREO;
     124           0 :         ctx->channel_blocks[1]  = CH_UNIT_MONO;
     125           0 :         ctx->channel_blocks[2]  = CH_UNIT_STEREO;
     126           0 :         ctx->channel_blocks[3]  = CH_UNIT_MONO;
     127           0 :         ctx->channel_blocks[4]  = CH_UNIT_MONO;
     128           0 :         break;
     129             :     case 8:
     130           0 :         avctx->channel_layout   = AV_CH_LAYOUT_7POINT1;
     131           0 :         ctx->num_channel_blocks = 5;
     132           0 :         ctx->channel_blocks[0]  = CH_UNIT_STEREO;
     133           0 :         ctx->channel_blocks[1]  = CH_UNIT_MONO;
     134           0 :         ctx->channel_blocks[2]  = CH_UNIT_STEREO;
     135           0 :         ctx->channel_blocks[3]  = CH_UNIT_STEREO;
     136           0 :         ctx->channel_blocks[4]  = CH_UNIT_MONO;
     137           0 :         break;
     138             :     default:
     139           0 :         av_log(avctx, AV_LOG_ERROR,
     140             :                "Unsupported channel count: %d!\n", avctx->channels);
     141           0 :         return AVERROR_INVALIDDATA;
     142             :     }
     143             : 
     144           4 :     return 0;
     145             : }
     146             : 
     147           4 : static av_cold int atrac3p_decode_init(AVCodecContext *avctx)
     148             : {
     149           4 :     ATRAC3PContext *ctx = avctx->priv_data;
     150             :     int i, ch, ret;
     151             : 
     152           4 :     if (!avctx->block_align) {
     153           0 :         av_log(avctx, AV_LOG_ERROR, "block_align is not set\n");
     154           0 :         return AVERROR(EINVAL);
     155             :     }
     156             : 
     157           4 :     ff_atrac3p_init_vlcs();
     158             : 
     159             :     /* initialize IPQF */
     160           4 :     ff_mdct_init(&ctx->ipqf_dct_ctx, 5, 1, 32.0 / 32768.0);
     161             : 
     162           4 :     ff_atrac3p_init_imdct(avctx, &ctx->mdct_ctx);
     163             : 
     164           4 :     ff_atrac_init_gain_compensation(&ctx->gainc_ctx, 6, 2);
     165             : 
     166           4 :     ff_atrac3p_init_wave_synth();
     167             : 
     168           4 :     if ((ret = set_channel_params(ctx, avctx)) < 0)
     169           0 :         return ret;
     170             : 
     171           4 :     ctx->my_channel_layout = avctx->channel_layout;
     172             : 
     173           4 :     ctx->ch_units = av_mallocz_array(ctx->num_channel_blocks, sizeof(*ctx->ch_units));
     174           4 :     ctx->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
     175             : 
     176           4 :     if (!ctx->ch_units || !ctx->fdsp) {
     177           0 :         atrac3p_decode_close(avctx);
     178           0 :         return AVERROR(ENOMEM);
     179             :     }
     180             : 
     181           8 :     for (i = 0; i < ctx->num_channel_blocks; i++) {
     182          12 :         for (ch = 0; ch < 2; ch++) {
     183           8 :             ctx->ch_units[i].channels[ch].ch_num          = ch;
     184           8 :             ctx->ch_units[i].channels[ch].wnd_shape       = &ctx->ch_units[i].channels[ch].wnd_shape_hist[0][0];
     185           8 :             ctx->ch_units[i].channels[ch].wnd_shape_prev  = &ctx->ch_units[i].channels[ch].wnd_shape_hist[1][0];
     186           8 :             ctx->ch_units[i].channels[ch].gain_data       = &ctx->ch_units[i].channels[ch].gain_data_hist[0][0];
     187           8 :             ctx->ch_units[i].channels[ch].gain_data_prev  = &ctx->ch_units[i].channels[ch].gain_data_hist[1][0];
     188           8 :             ctx->ch_units[i].channels[ch].tones_info      = &ctx->ch_units[i].channels[ch].tones_info_hist[0][0];
     189           8 :             ctx->ch_units[i].channels[ch].tones_info_prev = &ctx->ch_units[i].channels[ch].tones_info_hist[1][0];
     190             :         }
     191             : 
     192           4 :         ctx->ch_units[i].waves_info      = &ctx->ch_units[i].wave_synth_hist[0];
     193           4 :         ctx->ch_units[i].waves_info_prev = &ctx->ch_units[i].wave_synth_hist[1];
     194             :     }
     195             : 
     196           4 :     avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
     197             : 
     198           4 :     return 0;
     199             : }
     200             : 
     201         813 : static void decode_residual_spectrum(Atrac3pChanUnitCtx *ctx,
     202             :                                      float out[2][ATRAC3P_FRAME_SAMPLES],
     203             :                                      int num_channels,
     204             :                                      AVCodecContext *avctx)
     205             : {
     206             :     int i, sb, ch, qu, nspeclines, RNG_index;
     207             :     float *dst, q;
     208             :     int16_t *src;
     209             :     /* calculate RNG table index for each subband */
     210         813 :     int sb_RNG_index[ATRAC3P_SUBBANDS] = { 0 };
     211             : 
     212         813 :     if (ctx->mute_flag) {
     213           0 :         for (ch = 0; ch < num_channels; ch++)
     214           0 :             memset(out[ch], 0, ATRAC3P_FRAME_SAMPLES * sizeof(*out[ch]));
     215           0 :         return;
     216             :     }
     217             : 
     218       22793 :     for (qu = 0, RNG_index = 0; qu < ctx->used_quant_units; qu++)
     219       43960 :         RNG_index += ctx->channels[0].qu_sf_idx[qu] +
     220       21980 :                      ctx->channels[1].qu_sf_idx[qu];
     221             : 
     222       10377 :     for (sb = 0; sb < ctx->num_coded_subbands; sb++, RNG_index += 128)
     223        9564 :         sb_RNG_index[sb] = RNG_index & 0x3FC;
     224             : 
     225             :     /* inverse quant and power compensation */
     226        2439 :     for (ch = 0; ch < num_channels; ch++) {
     227             :         /* clear channel's residual spectrum */
     228        1626 :         memset(out[ch], 0, ATRAC3P_FRAME_SAMPLES * sizeof(*out[ch]));
     229             : 
     230       45586 :         for (qu = 0; qu < ctx->used_quant_units; qu++) {
     231       43960 :             src        = &ctx->channels[ch].spectrum[ff_atrac3p_qu_to_spec_pos[qu]];
     232       43960 :             dst        = &out[ch][ff_atrac3p_qu_to_spec_pos[qu]];
     233       87920 :             nspeclines = ff_atrac3p_qu_to_spec_pos[qu + 1] -
     234       43960 :                          ff_atrac3p_qu_to_spec_pos[qu];
     235             : 
     236       43960 :             if (ctx->channels[ch].qu_wordlen[qu] > 0) {
     237       87920 :                 q = ff_atrac3p_sf_tab[ctx->channels[ch].qu_sf_idx[qu]] *
     238       43960 :                     ff_atrac3p_mant_tab[ctx->channels[ch].qu_wordlen[qu]];
     239     2492344 :                 for (i = 0; i < nspeclines; i++)
     240     2448384 :                     dst[i] = src[i] * q;
     241             :             }
     242             :         }
     243             : 
     244       20754 :         for (sb = 0; sb < ctx->num_coded_subbands; sb++)
     245       19128 :             ff_atrac3p_power_compensation(ctx, ch, &out[ch][0],
     246             :                                           sb_RNG_index[sb], sb);
     247             :     }
     248             : 
     249         813 :     if (ctx->unit_type == CH_UNIT_STEREO) {
     250       10377 :         for (sb = 0; sb < ctx->num_coded_subbands; sb++) {
     251        9564 :             if (ctx->swap_channels[sb]) {
     252           0 :                 for (i = 0; i < ATRAC3P_SUBBAND_SAMPLES; i++)
     253           0 :                     FFSWAP(float, out[0][sb * ATRAC3P_SUBBAND_SAMPLES + i],
     254             :                                   out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i]);
     255             :             }
     256             : 
     257             :             /* flip coefficients' sign if requested */
     258        9564 :             if (ctx->negate_coeffs[sb])
     259           0 :                 for (i = 0; i < ATRAC3P_SUBBAND_SAMPLES; i++)
     260           0 :                     out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i] = -(out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i]);
     261             :         }
     262             :     }
     263             : }
     264             : 
     265         813 : static void reconstruct_frame(ATRAC3PContext *ctx, Atrac3pChanUnitCtx *ch_unit,
     266             :                               int num_channels, AVCodecContext *avctx)
     267             : {
     268             :     int ch, sb;
     269             : 
     270        2439 :     for (ch = 0; ch < num_channels; ch++) {
     271       23298 :         for (sb = 0; sb < ch_unit->num_subbands; sb++) {
     272             :             /* inverse transform and windowing */
     273       65016 :             ff_atrac3p_imdct(ctx->fdsp, &ctx->mdct_ctx,
     274       21672 :                              &ctx->samples[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
     275       21672 :                              &ctx->mdct_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
     276       21672 :                              (ch_unit->channels[ch].wnd_shape_prev[sb] << 1) +
     277       21672 :                              ch_unit->channels[ch].wnd_shape[sb], sb);
     278             : 
     279             :             /* gain compensation and overlapping */
     280      108360 :             ff_atrac_gain_compensation(&ctx->gainc_ctx,
     281       21672 :                                        &ctx->mdct_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
     282       21672 :                                        &ch_unit->prev_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
     283       21672 :                                        &ch_unit->channels[ch].gain_data_prev[sb],
     284       21672 :                                        &ch_unit->channels[ch].gain_data[sb],
     285             :                                        ATRAC3P_SUBBAND_SAMPLES,
     286       21672 :                                        &ctx->time_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES]);
     287             :         }
     288             : 
     289             :         /* zero unused subbands in both output and overlapping buffers */
     290        1626 :         memset(&ch_unit->prev_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES],
     291             :                0,
     292        1626 :                (ATRAC3P_SUBBANDS - ch_unit->num_subbands) *
     293             :                ATRAC3P_SUBBAND_SAMPLES *
     294             :                sizeof(ch_unit->prev_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES]));
     295        1626 :         memset(&ctx->time_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES],
     296             :                0,
     297        1626 :                (ATRAC3P_SUBBANDS - ch_unit->num_subbands) *
     298             :                ATRAC3P_SUBBAND_SAMPLES *
     299             :                sizeof(ctx->time_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES]));
     300             : 
     301             :         /* resynthesize and add tonal signal */
     302        3252 :         if (ch_unit->waves_info->tones_present ||
     303        1626 :             ch_unit->waves_info_prev->tones_present) {
     304           0 :             for (sb = 0; sb < ch_unit->num_subbands; sb++)
     305           0 :                 if (ch_unit->channels[ch].tones_info[sb].num_wavs ||
     306           0 :                     ch_unit->channels[ch].tones_info_prev[sb].num_wavs) {
     307           0 :                     ff_atrac3p_generate_tones(ch_unit, ctx->fdsp, ch, sb,
     308           0 :                                               &ctx->time_buf[ch][sb * 128]);
     309             :                 }
     310             :         }
     311             : 
     312             :         /* subband synthesis and acoustic signal output */
     313        3252 :         ff_atrac3p_ipqf(&ctx->ipqf_dct_ctx, &ch_unit->ipqf_ctx[ch],
     314        1626 :                         &ctx->time_buf[ch][0], &ctx->outp_buf[ch][0]);
     315             :     }
     316             : 
     317             :     /* swap window shape and gain control buffers. */
     318        2439 :     for (ch = 0; ch < num_channels; ch++) {
     319        1626 :         FFSWAP(uint8_t *, ch_unit->channels[ch].wnd_shape,
     320             :                ch_unit->channels[ch].wnd_shape_prev);
     321        1626 :         FFSWAP(AtracGainInfo *, ch_unit->channels[ch].gain_data,
     322             :                ch_unit->channels[ch].gain_data_prev);
     323        1626 :         FFSWAP(Atrac3pWavesData *, ch_unit->channels[ch].tones_info,
     324             :                ch_unit->channels[ch].tones_info_prev);
     325             :     }
     326             : 
     327         813 :     FFSWAP(Atrac3pWaveSynthParams *, ch_unit->waves_info, ch_unit->waves_info_prev);
     328         813 : }
     329             : 
     330         813 : static int atrac3p_decode_frame(AVCodecContext *avctx, void *data,
     331             :                                 int *got_frame_ptr, AVPacket *avpkt)
     332             : {
     333         813 :     ATRAC3PContext *ctx = avctx->priv_data;
     334         813 :     AVFrame *frame      = data;
     335         813 :     int i, ret, ch_unit_id, ch_block = 0, out_ch_index = 0, channels_to_process;
     336         813 :     float **samples_p = (float **)frame->extended_data;
     337             : 
     338         813 :     frame->nb_samples = ATRAC3P_FRAME_SAMPLES;
     339         813 :     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
     340           0 :         return ret;
     341             : 
     342         813 :     if ((ret = init_get_bits8(&ctx->gb, avpkt->data, avpkt->size)) < 0)
     343           0 :         return ret;
     344             : 
     345         813 :     if (get_bits1(&ctx->gb)) {
     346           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid start bit!\n");
     347           0 :         return AVERROR_INVALIDDATA;
     348             :     }
     349             : 
     350        4064 :     while (get_bits_left(&ctx->gb) >= 2 &&
     351        1625 :            (ch_unit_id = get_bits(&ctx->gb, 2)) != CH_UNIT_TERMINATOR) {
     352         813 :         if (ch_unit_id == CH_UNIT_EXTENSION) {
     353           0 :             avpriv_report_missing_feature(avctx, "Channel unit extension");
     354           0 :             return AVERROR_PATCHWELCOME;
     355             :         }
     356        1626 :         if (ch_block >= ctx->num_channel_blocks ||
     357         813 :             ctx->channel_blocks[ch_block] != ch_unit_id) {
     358           0 :             av_log(avctx, AV_LOG_ERROR,
     359             :                    "Frame data doesn't match channel configuration!\n");
     360           0 :             return AVERROR_INVALIDDATA;
     361             :         }
     362             : 
     363         813 :         ctx->ch_units[ch_block].unit_type = ch_unit_id;
     364         813 :         channels_to_process               = ch_unit_id + 1;
     365             : 
     366         813 :         if ((ret = ff_atrac3p_decode_channel_unit(&ctx->gb,
     367         813 :                                                   &ctx->ch_units[ch_block],
     368             :                                                   channels_to_process,
     369             :                                                   avctx)) < 0)
     370           0 :             return ret;
     371             : 
     372         813 :         decode_residual_spectrum(&ctx->ch_units[ch_block], ctx->samples,
     373             :                                  channels_to_process, avctx);
     374         813 :         reconstruct_frame(ctx, &ctx->ch_units[ch_block],
     375             :                           channels_to_process, avctx);
     376             : 
     377        2439 :         for (i = 0; i < channels_to_process; i++)
     378        1626 :             memcpy(samples_p[out_ch_index + i], ctx->outp_buf[i],
     379             :                    ATRAC3P_FRAME_SAMPLES * sizeof(**samples_p));
     380             : 
     381         813 :         ch_block++;
     382         813 :         out_ch_index += channels_to_process;
     383             :     }
     384             : 
     385         813 :     *got_frame_ptr = 1;
     386             : 
     387         813 :     return avctx->codec_id == AV_CODEC_ID_ATRAC3P ? FFMIN(avctx->block_align, avpkt->size) : avpkt->size;
     388             : }
     389             : 
     390             : AVCodec ff_atrac3p_decoder = {
     391             :     .name           = "atrac3plus",
     392             :     .long_name      = NULL_IF_CONFIG_SMALL("ATRAC3+ (Adaptive TRansform Acoustic Coding 3+)"),
     393             :     .type           = AVMEDIA_TYPE_AUDIO,
     394             :     .id             = AV_CODEC_ID_ATRAC3P,
     395             :     .capabilities   = AV_CODEC_CAP_DR1,
     396             :     .priv_data_size = sizeof(ATRAC3PContext),
     397             :     .init           = atrac3p_decode_init,
     398             :     .close          = atrac3p_decode_close,
     399             :     .decode         = atrac3p_decode_frame,
     400             : };
     401             : 
     402             : AVCodec ff_atrac3pal_decoder = {
     403             :     .name           = "atrac3plusal",
     404             :     .long_name      = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"),
     405             :     .type           = AVMEDIA_TYPE_AUDIO,
     406             :     .id             = AV_CODEC_ID_ATRAC3PAL,
     407             :     .capabilities   = AV_CODEC_CAP_DR1,
     408             :     .priv_data_size = sizeof(ATRAC3PContext),
     409             :     .init           = atrac3p_decode_init,
     410             :     .close          = atrac3p_decode_close,
     411             :     .decode         = atrac3p_decode_frame,
     412             : };

Generated by: LCOV version 1.13