Coverage Report

Created: 2026-09-03 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/uleaddvaudio.c
Line
Count
Source
1
/*****************************************************************************
2
 * uleaddvaudio.c
3
 *****************************************************************************
4
 * Copyright (C) 2012 Laurent Aimar
5
 *
6
 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ 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
#ifdef HAVE_CONFIG_H
24
# include "config.h"
25
#endif
26
27
#include <vlc_common.h>
28
#include <vlc_plugin.h>
29
#include <vlc_codec.h>
30
31
#include "../demux/rawdv.h"
32
33
/*****************************************************************************
34
 * Module descriptor
35
 *****************************************************************************/
36
static int  Open(vlc_object_t *);
37
38
174
vlc_module_begin()
39
87
    set_description(N_("Ulead DV audio decoder"))
40
87
    set_capability("audio decoder", 50)
41
87
    set_subcategory(SUBCAT_INPUT_ACODEC)
42
87
    set_callback(Open)
43
87
vlc_module_end()
44
45
typedef struct
46
{
47
    date_t end_date;
48
49
    bool     is_pal;
50
    bool     is_12bit;
51
    uint16_t shuffle[2000];
52
} decoder_sys_t;
53
54
static void Flush(decoder_t *dec)
55
0
{
56
0
    decoder_sys_t *sys = dec->p_sys;
57
58
0
    date_Set(&sys->end_date, VLC_TICK_INVALID);
59
0
}
60
61
static block_t *DecodeBlock(decoder_t *dec, block_t *block)
62
81.0k
{
63
81.0k
    decoder_sys_t *sys  = dec->p_sys;
64
81.0k
    block_t *output = NULL;
65
66
81.0k
    if (block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) {
67
0
        Flush(dec);
68
0
        if (block->i_flags & BLOCK_FLAG_CORRUPTED) {
69
0
            goto done;
70
0
        }
71
0
    }
72
73
81.0k
    if (block->i_pts != VLC_TICK_INVALID &&
74
81.0k
        block->i_pts != date_Get(&sys->end_date))
75
80.6k
        date_Set(&sys->end_date, block->i_pts);
76
81.0k
    block->i_pts = VLC_TICK_INVALID;
77
81.0k
    if (date_Get(&sys->end_date) == VLC_TICK_INVALID) {
78
        /* We've just started the stream, wait for the first PTS. */
79
0
        goto done;
80
0
    }
81
82
81.0k
    const unsigned int block_size = sys->is_pal ? 8640 : 7200;
83
81.0k
    if (block->i_buffer >= block_size) {
84
70.5k
        uint8_t *src = block->p_buffer;
85
86
70.5k
        block->i_buffer -= block_size;
87
70.5k
        block->p_buffer += block_size;
88
89
70.5k
        int sample_count = dv_get_audio_sample_count(&src[244], sys->is_pal);
90
91
70.5k
        if( decoder_UpdateAudioFormat(dec))
92
70.5k
            goto done;
93
0
        output = decoder_NewAudioBuffer(dec, sample_count);
94
0
        if (!output)
95
0
            goto done;
96
0
        output->i_pts    = date_Get(&sys->end_date);
97
0
        output->i_length = date_Increment(&sys->end_date, sample_count) - output->i_pts;
98
99
0
        int16_t *dst = (int16_t*)output->p_buffer;
100
0
        for (int i = 0; i < sample_count; i++) {
101
0
          const uint8_t *v = &src[sys->shuffle[i]];
102
0
          if (sys->is_12bit) {
103
0
              *dst++ = dv_audio_12to16((v[0] << 4) | ((v[2] >> 4) & 0x0f));
104
0
              *dst++ = dv_audio_12to16((v[1] << 4) | ((v[2] >> 0) & 0x0f));
105
0
          } else {
106
0
              *dst++ = GetWBE(&v[0]);
107
0
              *dst++ = GetWBE(&v[sys->is_pal ? 4320 : 3600]);
108
0
          }
109
0
        }
110
0
    }
111
81.0k
done:
112
81.0k
    block_Release(block);
113
81.0k
    return output;
114
81.0k
}
115
116
static int DecodeAudio(decoder_t *dec, block_t *block)
117
162k
{
118
162k
    if (block == NULL) /* No Drain */
119
81.2k
        return VLCDEC_SUCCESS;
120
121
81.0k
    block_t *out;
122
81.0k
    while ((out = DecodeBlock(dec, block)) != NULL)
123
0
        decoder_QueueAudio(dec,out);
124
81.0k
    return VLCDEC_SUCCESS;
125
162k
}
126
127
static int Open(vlc_object_t *object)
128
75.0k
{
129
75.0k
    decoder_t *dec = (decoder_t*)object;
130
131
75.0k
    if (dec->fmt_in->i_codec != VLC_CODEC_ULEAD_DV_AUDIO_NTSC &&
132
75.0k
        dec->fmt_in->i_codec != VLC_CODEC_ULEAD_DV_AUDIO_PAL)
133
74.9k
        return VLC_EGENERIC;
134
105
    if (dec->fmt_in->audio.i_bitspersample != 12 && dec->fmt_in->audio.i_bitspersample != 16)
135
3
        return VLC_EGENERIC;
136
102
    if (dec->fmt_in->audio.i_channels != 2)
137
1
        return VLC_EGENERIC;
138
101
    if (dec->fmt_in->audio.i_rate <= 0)
139
1
        return VLC_EGENERIC;
140
141
100
    decoder_sys_t *sys = dec->p_sys = vlc_obj_malloc(object, sizeof(*sys));
142
100
    if (!sys)
143
0
        return VLC_ENOMEM;
144
145
100
    sys->is_pal = dec->fmt_in->i_codec == VLC_CODEC_ULEAD_DV_AUDIO_PAL;
146
100
    sys->is_12bit = dec->fmt_in->audio.i_bitspersample == 12;
147
148
100
    date_Init(&sys->end_date, dec->fmt_in->audio.i_rate, 1);
149
150
200k
    for (unsigned i = 0; i < ARRAY_SIZE(sys->shuffle); i++) {
151
200k
        const unsigned a = sys->is_pal ? 18 : 15;
152
200k
        const unsigned b = 3 * a;
153
200k
        sys->shuffle[i] = 80 * ((21 * (i % 3) + 9 * (i / 3) + ((i / a) % 3)) % b) +
154
200k
                          (2 + sys->is_12bit) * (i / b) + 8;
155
200k
    }
156
157
100
    dec->fmt_out.i_codec = VLC_CODEC_S16N;
158
100
    dec->fmt_out.audio.i_rate = dec->fmt_in->audio.i_rate;
159
100
    dec->fmt_out.audio.i_channels = 2;
160
100
    dec->fmt_out.audio.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
161
162
100
    dec->pf_decode = DecodeAudio;
163
100
    dec->pf_flush  = Flush;
164
165
100
    return VLC_SUCCESS;
166
100
}