/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 | 116 | vlc_module_begin() |
39 | 58 | set_description(N_("Ulead DV audio decoder")) |
40 | 58 | set_capability("audio decoder", 50) |
41 | 58 | set_subcategory(SUBCAT_INPUT_ACODEC) |
42 | 58 | set_callback(Open) |
43 | 58 | 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 | 60.5k | { |
63 | 60.5k | decoder_sys_t *sys = dec->p_sys; |
64 | 60.5k | block_t *output = NULL; |
65 | | |
66 | 60.5k | 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 | 60.5k | if (block->i_pts != VLC_TICK_INVALID && |
74 | 60.5k | block->i_pts != date_Get(&sys->end_date)) |
75 | 58.7k | date_Set(&sys->end_date, block->i_pts); |
76 | 60.5k | block->i_pts = VLC_TICK_INVALID; |
77 | 60.5k | 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 | 60.5k | const unsigned int block_size = sys->is_pal ? 8640 : 7200; |
83 | 60.5k | if (block->i_buffer >= block_size) { |
84 | 52.3k | uint8_t *src = block->p_buffer; |
85 | | |
86 | 52.3k | block->i_buffer -= block_size; |
87 | 52.3k | block->p_buffer += block_size; |
88 | | |
89 | 52.3k | int sample_count = dv_get_audio_sample_count(&src[244], sys->is_pal); |
90 | | |
91 | 52.3k | if( decoder_UpdateAudioFormat(dec)) |
92 | 52.3k | 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 | 60.5k | done: |
112 | 60.5k | block_Release(block); |
113 | 60.5k | return output; |
114 | 60.5k | } |
115 | | |
116 | | static int DecodeAudio(decoder_t *dec, block_t *block) |
117 | 121k | { |
118 | 121k | if (block == NULL) /* No Drain */ |
119 | 60.6k | return VLCDEC_SUCCESS; |
120 | | |
121 | 60.5k | block_t *out; |
122 | 60.5k | while ((out = DecodeBlock(dec, block)) != NULL) |
123 | 0 | decoder_QueueAudio(dec,out); |
124 | 60.5k | return VLCDEC_SUCCESS; |
125 | 121k | } |
126 | | |
127 | | static int Open(vlc_object_t *object) |
128 | 32.9k | { |
129 | 32.9k | decoder_t *dec = (decoder_t*)object; |
130 | | |
131 | 32.9k | if (dec->fmt_in->i_codec != VLC_CODEC_ULEAD_DV_AUDIO_NTSC && |
132 | 32.9k | dec->fmt_in->i_codec != VLC_CODEC_ULEAD_DV_AUDIO_PAL) |
133 | 32.9k | return VLC_EGENERIC; |
134 | 47 | if (dec->fmt_in->audio.i_bitspersample != 12 && dec->fmt_in->audio.i_bitspersample != 16) |
135 | 15 | return VLC_EGENERIC; |
136 | 32 | if (dec->fmt_in->audio.i_channels != 2) |
137 | 2 | return VLC_EGENERIC; |
138 | 30 | if (dec->fmt_in->audio.i_rate <= 0) |
139 | 0 | return VLC_EGENERIC; |
140 | | |
141 | 30 | decoder_sys_t *sys = dec->p_sys = vlc_obj_malloc(object, sizeof(*sys)); |
142 | 30 | if (!sys) |
143 | 0 | return VLC_ENOMEM; |
144 | | |
145 | 30 | sys->is_pal = dec->fmt_in->i_codec == VLC_CODEC_ULEAD_DV_AUDIO_PAL; |
146 | 30 | sys->is_12bit = dec->fmt_in->audio.i_bitspersample == 12; |
147 | | |
148 | 30 | date_Init(&sys->end_date, dec->fmt_in->audio.i_rate, 1); |
149 | | |
150 | 60.0k | for (unsigned i = 0; i < ARRAY_SIZE(sys->shuffle); i++) { |
151 | 60.0k | const unsigned a = sys->is_pal ? 18 : 15; |
152 | 60.0k | const unsigned b = 3 * a; |
153 | 60.0k | sys->shuffle[i] = 80 * ((21 * (i % 3) + 9 * (i / 3) + ((i / a) % 3)) % b) + |
154 | 60.0k | (2 + sys->is_12bit) * (i / b) + 8; |
155 | 60.0k | } |
156 | | |
157 | 30 | dec->fmt_out.i_codec = VLC_CODEC_S16N; |
158 | 30 | dec->fmt_out.audio.i_rate = dec->fmt_in->audio.i_rate; |
159 | 30 | dec->fmt_out.audio.i_channels = 2; |
160 | 30 | dec->fmt_out.audio.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; |
161 | | |
162 | 30 | dec->pf_decode = DecodeAudio; |
163 | 30 | dec->pf_flush = Flush; |
164 | | |
165 | 30 | return VLC_SUCCESS; |
166 | 30 | } |