Qt: Change almost all icons
[vlc.git] / modules / codec / dca.c
1 /*****************************************************************************
2  * dca.c: DTS Coherent Acoustics decoder plugin for VLC.
3  *   This plugin makes use of libdca to do the actual decoding
4  *   (http://developers.videolan.org/libdca.html).
5  *****************************************************************************
6  * Copyright (C) 2001, 2016 libdca VLC authors and VideoLAN
7  *
8  * Author: Gildas Bazin <gbazin@videolan.org>
9  *         Thomas Guillem <thomas@gllm.fr>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation; either version 2.1 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * NOTA BENE: this module requires the linking against a library which is
28  * known to require licensing under the GNU General Public License version 2
29  * (or later). Therefore, the result of compiling this module will normally
30  * be subject to the terms of that later license.
31  *****************************************************************************/
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <vlc_common.h>
38 #include <vlc_plugin.h>
39
40 #include <dca.h>                                       /* libdca header file */
41
42 #include <vlc_aout.h>
43 #include <vlc_block.h>
44 #include <vlc_codec.h>
45
46 static int  Open ( vlc_object_t * );
47 static void Close( vlc_object_t * );
48
49 struct decoder_sys_t
50 {
51     dca_state_t     *p_libdca; /* libdca internal structure */
52     bool            b_dynrng; /* see below */
53     int             i_flags; /* libdca flags, see dtsdec/doc/libdts.txt */
54     bool            b_dontwarn;
55     int             i_nb_channels; /* number of float32 per sample */
56
57     uint8_t         pi_chan_table[AOUT_CHAN_MAX]; /* channel reordering */
58     bool            b_synced;
59 };
60
61 #define DYNRNG_TEXT N_("DTS dynamic range compression")
62 #define DYNRNG_LONGTEXT N_( \
63     "Dynamic range compression makes the loud sounds softer, and the soft " \
64     "sounds louder, so you can more easily listen to the stream in a noisy " \
65     "environment without disturbing anyone. If you disable the dynamic range "\
66     "compression the playback will be more adapted to a movie theater or a " \
67     "listening room.")
68
69 vlc_module_begin ()
70     set_category( CAT_INPUT )
71     set_subcategory( SUBCAT_INPUT_ACODEC )
72     set_shortname( "DCA" )
73     set_description( N_("DTS Coherent Acoustics audio decoder") )
74     add_bool( "dts-dynrng", true, DYNRNG_TEXT, DYNRNG_LONGTEXT, false )
75     set_capability( "audio decoder", 60 )
76     set_callbacks( Open, Close )
77 vlc_module_end ()
78
79 /*
80  * helper function to interleave channels
81  */
82 static void Interleave( float * p_out, const float * p_in, int i_nb_channels,
83                         uint8_t *pi_chan_table )
84 {
85     /* We do not only have to interleave, but also reorder the channels. */
86
87     int i, j;
88     for ( j = 0; j < i_nb_channels; j++ )
89     {
90         for ( i = 0; i < 256; i++ )
91         {
92             p_out[i * i_nb_channels + pi_chan_table[j]] = p_in[j * 256 + i];
93         }
94     }
95 }
96
97 /*
98  * helper function to duplicate a unique channel
99  */
100 static void Duplicate( float * p_out, const float * p_in )
101 {
102     for ( int i = 256; i--; )
103     {
104         *p_out++ = *p_in;
105         *p_out++ = *p_in;
106         p_in++;
107     }
108 }
109
110 static int Decode( decoder_t *p_dec, block_t *p_in_buf )
111 {
112     decoder_sys_t  *p_sys = p_dec->p_sys;
113
114     if (p_in_buf == NULL) /* No Drain */
115         return VLCDEC_SUCCESS;
116
117     sample_t i_sample_level = 1;
118     int  i_flags = p_sys->i_flags;
119     size_t i_bytes_per_block = 256 * p_sys->i_nb_channels * sizeof(float);
120
121     block_t *p_out_buf = block_Alloc( 6 * i_bytes_per_block );
122     if( unlikely(p_out_buf == NULL) )
123         goto out;
124
125     /*
126      * Do the actual decoding now.
127      */
128
129     /* Needs to be called so the decoder knows which type of bitstream it is
130      * dealing with. */
131     int i_sample_rate, i_bit_rate, i_frame_length;
132     if( !dca_syncinfo( p_sys->p_libdca, p_in_buf->p_buffer, &i_flags,
133                        &i_sample_rate, &i_bit_rate, &i_frame_length ) )
134     {
135         msg_Warn( p_dec, "libdca couldn't sync on frame" );
136         p_out_buf->i_nb_samples = p_out_buf->i_buffer = 0;
137         goto out;
138     }
139
140     i_flags = p_sys->i_flags;
141     dca_frame( p_sys->p_libdca, p_in_buf->p_buffer,
142                &i_flags, &i_sample_level, 0 );
143
144     if ( (i_flags & DCA_CHANNEL_MASK) != (p_sys->i_flags & DCA_CHANNEL_MASK)
145           && !p_sys->b_dontwarn )
146     {
147         msg_Warn( p_dec,
148                   "libdca couldn't do the requested downmix 0x%x->0x%x",
149                   p_sys->i_flags  & DCA_CHANNEL_MASK,
150                   i_flags & DCA_CHANNEL_MASK );
151
152         p_sys->b_dontwarn = 1;
153     }
154
155     for( int i = 0; i < dca_blocks_num(p_sys->p_libdca); i++ )
156     {
157         sample_t * p_samples;
158
159         if( dca_block( p_sys->p_libdca ) )
160         {
161             msg_Warn( p_dec, "dca_block failed for block %d", i );
162             break;
163         }
164
165         p_samples = dca_samples( p_sys->p_libdca );
166
167         if ( (p_sys->i_flags & DCA_CHANNEL_MASK) == DCA_MONO
168               && (p_dec->fmt_out.audio.i_physical_channels
169                    & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
170         {
171             Duplicate( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
172                        p_samples );
173         }
174         else
175         {
176             /* Interleave the *$£%ù samples. */
177             Interleave( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
178                         p_samples, p_sys->i_nb_channels, p_sys->pi_chan_table);
179         }
180     }
181
182     p_out_buf->i_nb_samples = dca_blocks_num(p_sys->p_libdca) * 256;
183     p_out_buf->i_buffer = p_in_buf->i_nb_samples * sizeof(float) * p_sys->i_nb_channels;
184     p_out_buf->i_dts = p_in_buf->i_dts;
185     p_out_buf->i_pts = p_in_buf->i_pts;
186     p_out_buf->i_length = p_in_buf->i_length;
187 out:
188     if (p_out_buf != NULL)
189         decoder_QueueAudio(p_dec, p_out_buf);
190     block_Release( p_in_buf );
191     return VLCDEC_SUCCESS;
192 }
193
194 static int channels_vlc2dca( const audio_format_t *p_audio, int *p_flags )
195 {
196     int i_flags = 0;
197
198     switch ( p_audio->i_physical_channels & ~AOUT_CHAN_LFE )
199     {
200     case AOUT_CHAN_CENTER:
201         if ( (p_audio->i_physical_channels & AOUT_CHAN_CENTER)
202               || (p_audio->i_physical_channels
203                    & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
204             i_flags = DCA_MONO;
205         break;
206
207     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT:
208         if ( p_audio->i_chan_mode & AOUT_CHANMODE_DOLBYSTEREO )
209             i_flags = DCA_DOLBY;
210         else if ( p_audio->i_chan_mode & AOUT_CHANMODE_DUALMONO )
211             i_flags = DCA_CHANNEL;
212         else
213             i_flags = DCA_STEREO;
214         break;
215
216     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER:
217         i_flags = DCA_3F;
218         break;
219
220     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER:
221         i_flags = DCA_2F1R;
222         break;
223
224     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
225           | AOUT_CHAN_REARCENTER:
226         i_flags = DCA_3F1R;
227         break;
228
229     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
230           | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
231         i_flags = DCA_2F2R;
232         break;
233
234     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
235           | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
236         i_flags = DCA_3F2R;
237         break;
238
239     default:
240         return VLC_EGENERIC;
241     }
242
243     if ( p_audio->i_physical_channels & AOUT_CHAN_LFE )
244         i_flags |= DCA_LFE;
245     *p_flags = i_flags;
246     return VLC_SUCCESS;
247 }
248
249 static int Open( vlc_object_t *p_this )
250 {
251     decoder_t *p_dec = (decoder_t *)p_this;
252     decoder_sys_t *p_sys;
253
254     if( p_dec->fmt_in.i_codec != VLC_CODEC_DTS
255      || p_dec->fmt_in.audio.i_rate == 0
256      || p_dec->fmt_in.audio.i_physical_channels == 0
257      || p_dec->fmt_in.audio.i_bytes_per_frame == 0
258      || p_dec->fmt_in.audio.i_frame_length == 0 )
259         return VLC_EGENERIC;
260
261     /* Allocate the memory needed to store the module's structure */
262     p_sys = p_dec->p_sys = malloc( sizeof(decoder_sys_t) );
263     if( p_sys == NULL )
264         return VLC_ENOMEM;
265
266     p_sys->b_dynrng = var_InheritBool( p_this, "dts-dynrng" );
267     p_sys->b_dontwarn = 0;
268
269     /* We'll do our own downmixing, thanks. */
270     p_sys->i_nb_channels = aout_FormatNbChannels( &p_dec->fmt_in.audio );
271     if( channels_vlc2dca( &p_dec->fmt_in.audio, &p_sys->i_flags )
272         != VLC_SUCCESS )
273     {
274         msg_Warn( p_this, "unknown sample format!" );
275         free( p_sys );
276         return VLC_EGENERIC;
277     }
278     //p_sys->i_flags |= DCA_ADJUST_LEVEL;
279
280     /* Initialize libdca */
281     p_sys->p_libdca = dca_init( 0 );
282     if( p_sys->p_libdca == NULL )
283     {
284         msg_Err( p_this, "unable to initialize libdca" );
285         free( p_sys );
286         return VLC_EGENERIC;
287     }
288
289     /* libdca channel order
290      * libdca currently only decodes 5.1, even if you have a DTS-ES source. */
291     static const uint32_t pi_channels_in[] = {
292         AOUT_CHAN_CENTER, AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
293         AOUT_CHAN_REARCENTER, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
294         AOUT_CHAN_LFE, 0
295     };
296
297     aout_CheckChannelReorder( pi_channels_in, NULL,
298                               p_dec->fmt_in.audio.i_physical_channels,
299                               p_sys->pi_chan_table );
300
301     p_dec->fmt_out.audio = p_dec->fmt_in.audio;
302     p_dec->fmt_out.audio.i_format = VLC_CODEC_FL32;
303     p_dec->fmt_out.i_codec = p_dec->fmt_out.audio.i_format;
304
305     aout_FormatPrepare( &p_dec->fmt_out.audio );
306
307     if( decoder_UpdateAudioFormat( p_dec ) )
308     {
309         Close( p_this );
310         return VLC_EGENERIC;
311     }
312
313     p_dec->pf_decode = Decode;
314     p_dec->pf_flush  = NULL;
315     return VLC_SUCCESS;
316 }
317
318 static void Close( vlc_object_t *p_this )
319 {
320     decoder_t *p_dec = (decoder_t *)p_this;
321     decoder_sys_t *p_sys = p_dec->p_sys;
322
323     dca_free( p_sys->p_libdca );
324     free( p_sys );
325 }