Coverage Report

Created: 2025-10-12 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/aes3.c
Line
Count
Source
1
/*****************************************************************************
2
 * aes3.c: aes3 decoder/packetizer module
3
 *****************************************************************************
4
 * Copyright (C) 2008 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@videolan.org>
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program 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
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
22
23
/*****************************************************************************
24
 * Preamble
25
 *****************************************************************************/
26
#ifdef HAVE_CONFIG_H
27
# include "config.h"
28
#endif
29
30
#include <vlc_common.h>
31
#include <vlc_plugin.h>
32
#include <vlc_codec.h>
33
#include <assert.h>
34
35
/*****************************************************************************
36
 * Module descriptor
37
 *****************************************************************************/
38
static int  OpenDecoder   ( vlc_object_t * );
39
static int  OpenPacketizer( vlc_object_t * );
40
41
108
vlc_module_begin ()
42
43
54
    set_subcategory( SUBCAT_INPUT_ACODEC )
44
54
    set_description( N_("AES3/SMPTE 302M audio decoder") )
45
54
    set_capability( "audio decoder", 100 )
46
54
    set_callback( OpenDecoder )
47
48
54
    add_submodule ()
49
54
    set_description( N_("AES3/SMPTE 302M audio packetizer") )
50
54
    set_capability( "audio packetizer", 100 )
51
54
    set_callback( OpenPacketizer )
52
53
54
vlc_module_end ()
54
55
/*****************************************************************************
56
 * decoder_sys_t : aes3 decoder descriptor
57
 *****************************************************************************/
58
typedef struct
59
{
60
    /*
61
     * Output properties
62
     */
63
    date_t end_date;
64
} decoder_sys_t;
65
66
165k
#define AES3_HEADER_LEN 4
67
68
/*****************************************************************************
69
 * Local prototypes
70
 *****************************************************************************/
71
static int Open( decoder_t *p_dec, bool b_packetizer );
72
73
static block_t *Parse( decoder_t *p_dec, int *pi_frame_length, int *pi_bits,
74
                       block_t *p_block, bool b_packetizer );
75
76
/*****************************************************************************
77
 * OpenDecoder:
78
 *****************************************************************************/
79
static int OpenDecoder( vlc_object_t *p_this )
80
2.73M
{
81
2.73M
    decoder_t *p_dec = (decoder_t*)p_this;
82
83
2.73M
    return Open( p_dec, false );
84
2.73M
}
85
86
/*****************************************************************************
87
 * OpenPacketizer:
88
 *****************************************************************************/
89
static int OpenPacketizer( vlc_object_t *p_this )
90
2.73M
{
91
2.73M
    decoder_t *p_dec = (decoder_t*)p_this;
92
93
2.73M
    return Open( p_dec, true );
94
2.73M
}
95
96
static const uint8_t reverse[256] = {
97
    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
98
    0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
99
    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
100
    0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
101
    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
102
    0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
103
    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
104
    0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
105
    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
106
    0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
107
    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
108
    0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
109
    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
110
    0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
111
    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
112
    0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
113
    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
114
    0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
115
    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
116
    0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
117
    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
118
    0x3f, 0xbf, 0x7f, 0xff
119
};
120
121
/*****************************************************************************
122
 * Decode: decodes an aes3 frame.
123
 ****************************************************************************
124
 * Beware, this function must be fed with complete frames (PES packet).
125
 *****************************************************************************/
126
static int Decode( decoder_t *p_dec, block_t *p_block )
127
72.4k
{
128
72.4k
    decoder_sys_t *p_sys = p_dec->p_sys;
129
72.4k
    block_t       *p_aout_buffer;
130
72.4k
    int            i_frame_length, i_bits;
131
132
72.4k
    p_block = Parse( p_dec, &i_frame_length, &i_bits, p_block, false );
133
72.4k
    if( !p_block )
134
61.4k
        return VLCDEC_SUCCESS;
135
136
11.0k
    if( decoder_UpdateAudioFormat( p_dec ) )
137
11.0k
    {
138
11.0k
        p_aout_buffer = NULL;
139
11.0k
        goto exit;
140
11.0k
    }
141
142
0
    p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_frame_length );
143
0
    if( p_aout_buffer == NULL )
144
0
        goto exit;
145
146
0
    p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
147
0
    p_aout_buffer->i_length = date_Increment( &p_sys->end_date,
148
0
                                      i_frame_length ) - p_aout_buffer->i_pts;
149
150
0
    p_block->i_buffer -= AES3_HEADER_LEN;
151
0
    p_block->p_buffer += AES3_HEADER_LEN;
152
153
0
    if( i_bits == 24 )
154
0
    {
155
0
        uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer;
156
157
0
        while( p_block->i_buffer / 7 )
158
0
        {
159
0
            *(p_out++) =  (reverse[p_block->p_buffer[0]] <<  8)
160
0
                        | (reverse[p_block->p_buffer[1]] << 16)
161
0
                        | (reverse[p_block->p_buffer[2]] << 24);
162
0
            *(p_out++) = ((reverse[p_block->p_buffer[3]] <<  4)
163
0
                        | (reverse[p_block->p_buffer[4]] << 12)
164
0
                        | (reverse[p_block->p_buffer[5]] << 20)
165
0
                        | (reverse[p_block->p_buffer[6]] << 28)) & 0xFFFFFF00;
166
167
0
            p_block->i_buffer -= 7;
168
0
            p_block->p_buffer += 7;
169
0
        }
170
171
0
    }
172
0
    else if( i_bits == 20 )
173
0
    {
174
0
        uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer;
175
176
0
        while( p_block->i_buffer / 6 )
177
0
        {
178
0
            *(p_out++) = (reverse[p_block->p_buffer[0]] << 12)
179
0
                       | (reverse[p_block->p_buffer[1]] << 20)
180
0
                       | (reverse[p_block->p_buffer[2]] << 28);
181
0
            *(p_out++) = (reverse[p_block->p_buffer[3]] << 12)
182
0
                       | (reverse[p_block->p_buffer[4]] << 20)
183
0
                       | (reverse[p_block->p_buffer[5]] << 28);
184
185
0
            p_block->i_buffer -= 6;
186
0
            p_block->p_buffer += 6;
187
0
        }
188
0
    }
189
0
    else
190
0
    {
191
0
        uint16_t *p_out = (uint16_t *)p_aout_buffer->p_buffer;
192
193
0
        assert( i_bits == 16 );
194
195
0
        while( p_block->i_buffer / 5 )
196
0
        {
197
0
            *(p_out++) =  reverse[p_block->p_buffer[0]]
198
0
                        |(reverse[p_block->p_buffer[1]] <<  8);
199
0
            *(p_out++) = (reverse[p_block->p_buffer[2]] >>  4)
200
0
                       | (reverse[p_block->p_buffer[3]] <<  4)
201
0
                       | (reverse[p_block->p_buffer[4]] << 12);
202
203
0
            p_block->i_buffer -= 5;
204
0
            p_block->p_buffer += 5;
205
0
        }
206
0
    }
207
208
11.0k
exit:
209
11.0k
    block_Release( p_block );
210
11.0k
    if( p_aout_buffer != NULL )
211
0
        decoder_QueueAudio( p_dec, p_aout_buffer );
212
11.0k
    return VLCDEC_SUCCESS;
213
0
}
214
215
/*****************************************************************************
216
 * Flush:
217
 *****************************************************************************/
218
static void Flush( decoder_t *p_dec )
219
0
{
220
0
    decoder_sys_t *p_sys = p_dec->p_sys;
221
222
0
    date_Set( &p_sys->end_date, VLC_TICK_INVALID );
223
0
}
224
225
/*****************************************************************************
226
 * Packetize: packetizes an aes3 frame.
227
 ****************************************************************************
228
 * Beware, this function must be fed with complete frames (PES packet).
229
 *****************************************************************************/
230
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
231
71.9k
{
232
71.9k
    decoder_sys_t *p_sys = p_dec->p_sys;
233
71.9k
    block_t       *p_block;
234
71.9k
    int           i_frame_length, i_bits;
235
236
71.9k
    if( !pp_block ) /* No Drain */
237
50
        return NULL;
238
71.8k
    p_block = *pp_block;
239
71.8k
    *pp_block = NULL; /* So the packet doesn't get re-sent */
240
241
71.8k
    p_block = Parse( p_dec, &i_frame_length, &i_bits, p_block, true );
242
71.8k
    if( !p_block )
243
60.8k
        return NULL;
244
245
11.0k
    p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
246
11.0k
    p_block->i_length = date_Increment( &p_sys->end_date, i_frame_length ) - p_block->i_pts;
247
248
    /* Just pass on the incoming frame */
249
11.0k
    return p_block;
250
71.8k
}
251
252
/*****************************************************************************
253
 *
254
 ****************************************************************************/
255
static int Open( decoder_t *p_dec, bool b_packetizer )
256
5.46M
{
257
5.46M
    decoder_sys_t *p_sys;
258
259
5.46M
    if( p_dec->fmt_in->i_codec != VLC_CODEC_302M )
260
5.46M
        return VLC_EGENERIC;
261
262
    /* Allocate the memory needed to store the decoder's structure */
263
641
    p_sys = vlc_obj_malloc( VLC_OBJECT(p_dec), sizeof(*p_sys) );
264
265
641
    if( unlikely( !p_sys ) )
266
0
        return VLC_EGENERIC;
267
268
    /* Misc init */
269
641
    date_Init( &p_sys->end_date, 48000, 1 );
270
271
    /* Set output properties */
272
641
    p_dec->fmt_out.audio.i_rate = 48000;
273
274
    /* Set callback */
275
641
    if( b_packetizer )
276
50
    {
277
50
        p_dec->fmt_out.i_codec = VLC_CODEC_302M;
278
279
50
        p_dec->pf_packetize    = Packetize;
280
50
    }
281
591
    else
282
591
    {
283
591
        p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
284
591
        p_dec->fmt_out.audio.i_bitspersample = 16;
285
286
591
        p_dec->pf_decode    = Decode;
287
591
    }
288
641
    p_dec->pf_flush            = Flush;
289
641
    p_dec->p_sys = p_sys;
290
641
    return VLC_SUCCESS;
291
641
}
292
293
static const unsigned int pi_original_channels[4] = {
294
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
295
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
296
        AOUT_CHAN_CENTER | AOUT_CHAN_LFE,
297
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
298
        AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
299
        AOUT_CHAN_CENTER | AOUT_CHAN_LFE,
300
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
301
        AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
302
        AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
303
        AOUT_CHAN_CENTER | AOUT_CHAN_LFE,
304
};
305
306
static block_t * Parse( decoder_t *p_dec, int *pi_frame_length, int *pi_bits,
307
                        block_t *p_block, bool b_packetizer )
308
144k
{
309
144k
    decoder_sys_t *p_sys = p_dec->p_sys;
310
144k
    uint32_t h;
311
144k
    unsigned int i_size;
312
144k
    int i_channels;
313
144k
    int i_bits;
314
315
144k
    if( !p_block ) /* No drain */
316
72.4k
        return NULL;
317
318
71.8k
    if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED|BLOCK_FLAG_DISCONTINUITY) )
319
0
    {
320
0
        Flush( p_dec );
321
0
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
322
0
        {
323
0
            block_Release( p_block );
324
0
            return NULL;
325
0
        }
326
0
    }
327
328
    /* Date management */
329
71.8k
    if( p_block->i_pts != VLC_TICK_INVALID &&
330
71.8k
        p_block->i_pts != date_Get( &p_sys->end_date ) )
331
58.5k
    {
332
58.5k
        date_Set( &p_sys->end_date, p_block->i_pts );
333
58.5k
    }
334
335
71.8k
    if( date_Get( &p_sys->end_date ) == VLC_TICK_INVALID )
336
0
    {
337
        /* We've just started the stream, wait for the first PTS. */
338
0
        block_Release( p_block );
339
0
        return NULL;
340
0
    }
341
342
71.8k
    if( p_block->i_buffer <= AES3_HEADER_LEN )
343
27
    {
344
27
        msg_Err(p_dec, "frame is too short");
345
27
        block_Release( p_block );
346
27
        return NULL;
347
27
    }
348
349
    /*
350
     * AES3 header :
351
     * size:            16
352
     * number channels   2
353
     * channel_id        8
354
     * bits per samples  2
355
     * alignments        4
356
     */
357
358
71.8k
    h = GetDWBE( p_block->p_buffer );
359
71.8k
    i_size = (h >> 16) & 0xffff;
360
71.8k
    i_channels = 2 + 2*( (h >> 14) & 0x03 );
361
71.8k
    i_bits = 16 + 4*( (h >> 4)&0x03 );
362
363
71.8k
    if( AES3_HEADER_LEN + i_size != p_block->i_buffer || i_bits > 24 )
364
49.8k
    {
365
49.8k
        msg_Err(p_dec, "frame has invalid header");
366
49.8k
        block_Release( p_block );
367
49.8k
        return NULL;
368
49.8k
    }
369
370
    /* Set output properties */
371
22.0k
    if( b_packetizer )
372
11.0k
    {
373
11.0k
        p_dec->fmt_out.audio.i_bitspersample = i_bits;
374
11.0k
    }
375
11.0k
    else
376
11.0k
    {
377
11.0k
        p_dec->fmt_out.i_codec = i_bits == 16 ? VLC_CODEC_S16N : VLC_CODEC_S32N;
378
11.0k
        p_dec->fmt_out.audio.i_bitspersample = i_bits == 16 ? 16 : 32;
379
11.0k
    }
380
381
22.0k
    p_dec->fmt_out.audio.i_channels = i_channels;
382
22.0k
    p_dec->fmt_out.audio.i_physical_channels = pi_original_channels[i_channels/2-1];
383
384
22.0k
    *pi_frame_length = (p_block->i_buffer - AES3_HEADER_LEN) / ( (4+i_bits) * i_channels / 8 );
385
22.0k
    *pi_bits = i_bits;
386
22.0k
    return p_block;
387
71.8k
}