]> git.sesse.net Git - vlc/blob - modules/codec/uleaddvaudio.c
mediacodec: fix warning
[vlc] / modules / codec / uleaddvaudio.c
1 /*****************************************************************************
2  * uleaddvaudio.c
3  *****************************************************************************
4  * Copyright (C) 2012 Laurent Aimar
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <vlc_common.h>
29 #include <vlc_plugin.h>
30 #include <vlc_codec.h>
31
32 #include "../demux/rawdv.h"
33
34 /*****************************************************************************
35  * Module descriptor
36  *****************************************************************************/
37 static int  Open(vlc_object_t *);
38 static void Close(vlc_object_t *);
39
40 vlc_module_begin()
41     set_description(N_("Ulead DV audio decoder"))
42     set_capability("decoder", 50)
43     set_category(CAT_INPUT)
44     set_subcategory(SUBCAT_INPUT_ACODEC)
45     set_callbacks(Open, Close)
46 vlc_module_end()
47
48 struct decoder_sys_t
49 {
50     date_t end_date;
51
52     bool     is_pal;
53     bool     is_12bit;
54     uint16_t shuffle[2000];
55 };
56
57 static block_t *Decode(decoder_t *dec, block_t **block_ptr)
58 {
59     decoder_sys_t *sys  = dec->p_sys;
60
61     if (!block_ptr || !*block_ptr)
62         return NULL;
63
64     block_t *block = *block_ptr;
65     if (block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED)) {
66         if (block->i_flags & BLOCK_FLAG_CORRUPTED) {
67         }
68         date_Set(&sys->end_date, 0);
69         block_Release(block);
70         return NULL;
71     }
72
73     if (block->i_pts > VLC_TS_INVALID &&
74         block->i_pts != date_Get(&sys->end_date))
75         date_Set(&sys->end_date, block->i_pts);
76     block->i_pts = VLC_TS_INVALID;
77     if (!date_Get(&sys->end_date)) {
78         /* We've just started the stream, wait for the first PTS. */
79         block_Release(block);
80         return NULL;
81     }
82
83     const unsigned int block_size = sys->is_pal ? 8640 : 7200;
84     if (block->i_buffer >= block_size) {
85         uint8_t *src = block->p_buffer;
86
87         block->i_buffer -= block_size;
88         block->p_buffer += block_size;
89
90         int sample_count = dv_get_audio_sample_count(&src[244], sys->is_pal);
91
92         block_t *output = decoder_NewAudioBuffer(dec, sample_count);
93         if (!output)
94             return NULL;
95         output->i_pts    = date_Get(&sys->end_date);
96         output->i_length = date_Increment(&sys->end_date, sample_count) - output->i_pts;
97
98         int16_t *dst = (int16_t*)output->p_buffer;
99         for (int i = 0; i < sample_count; i++) {
100           const uint8_t *v = &src[sys->shuffle[i]];
101           if (sys->is_12bit) {
102               *dst++ = dv_audio_12to16((v[0] << 4) | ((v[2] >> 4) & 0x0f));
103               *dst++ = dv_audio_12to16((v[1] << 4) | ((v[2] >> 0) & 0x0f));
104           } else {
105               *dst++ = GetWBE(&v[0]);
106               *dst++ = GetWBE(&v[sys->is_pal ? 4320 : 3600]);
107           }
108         }
109         return output;
110     }
111     block_Release(block);
112     return NULL;
113 }
114
115 static int Open(vlc_object_t *object)
116 {
117     decoder_t *dec = (decoder_t*)object;
118
119     if (dec->fmt_in.i_codec != VLC_CODEC_ULEAD_DV_AUDIO_NTSC &&
120         dec->fmt_in.i_codec != VLC_CODEC_ULEAD_DV_AUDIO_PAL)
121         return VLC_EGENERIC;
122     if (dec->fmt_in.audio.i_bitspersample != 12 && dec->fmt_in.audio.i_bitspersample != 16)
123         return VLC_EGENERIC;
124     if (dec->fmt_in.audio.i_channels != 2)
125         return VLC_EGENERIC;
126     if (dec->fmt_in.audio.i_rate <= 0)
127         return VLC_EGENERIC;
128
129     decoder_sys_t *sys = dec->p_sys = malloc(sizeof(*sys));
130     if (!sys)
131         return VLC_ENOMEM;
132
133     sys->is_pal = dec->fmt_in.i_codec == VLC_CODEC_ULEAD_DV_AUDIO_PAL;
134     sys->is_12bit = dec->fmt_in.audio.i_bitspersample == 12;
135
136     date_Init(&sys->end_date, dec->fmt_in.audio.i_rate, 1);
137     date_Set(&sys->end_date, 0);
138
139     for (unsigned i = 0; i < sizeof(sys->shuffle) / sizeof(*sys->shuffle); i++) {
140         const unsigned a = sys->is_pal ? 18 : 15;
141         const unsigned b = 3 * a;
142         sys->shuffle[i] = 80 * ((21 * (i % 3) + 9 * (i / 3) + ((i / a) % 3)) % b) +
143                           (2 + sys->is_12bit) * (i / b) + 8;
144     }
145
146     es_format_Init(&dec->fmt_out, AUDIO_ES, VLC_CODEC_S16N);
147     dec->fmt_out.audio.i_rate = dec->fmt_in.audio.i_rate;
148     dec->fmt_out.audio.i_channels = 2;
149     dec->fmt_out.audio.i_physical_channels =
150     dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
151
152     dec->pf_decode_audio = Decode;
153
154     return VLC_SUCCESS;
155 }
156
157 static void Close(vlc_object_t *object)
158 {
159     decoder_t *dec = (decoder_t *)object;
160
161     free(dec->p_sys);
162 }
163