/src/vlc/modules/codec/uleaddvaudio.c
Line | Count | Source (jump to first uncovered line) |
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 | 100 | vlc_module_begin() |
39 | 50 | set_description(N_("Ulead DV audio decoder")) |
40 | 50 | set_capability("audio decoder", 50) |
41 | 50 | set_subcategory(SUBCAT_INPUT_ACODEC) |
42 | 50 | set_callback(Open) |
43 | 50 | 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_ptr) |
62 | 274k | { |
63 | 274k | decoder_sys_t *sys = dec->p_sys; |
64 | | |
65 | 274k | if (!*block_ptr) |
66 | 0 | return NULL; |
67 | | |
68 | 274k | block_t *block = *block_ptr; |
69 | 274k | if (block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) { |
70 | 0 | Flush(dec); |
71 | 0 | if (block->i_flags & BLOCK_FLAG_CORRUPTED) { |
72 | 0 | block_Release(block); |
73 | 0 | *block_ptr = NULL; |
74 | 0 | return NULL; |
75 | 0 | } |
76 | 0 | } |
77 | | |
78 | 274k | if (block->i_pts != VLC_TICK_INVALID && |
79 | 274k | block->i_pts != date_Get(&sys->end_date)) |
80 | 274k | date_Set(&sys->end_date, block->i_pts); |
81 | 274k | block->i_pts = VLC_TICK_INVALID; |
82 | 274k | if (date_Get(&sys->end_date) == VLC_TICK_INVALID) { |
83 | | /* We've just started the stream, wait for the first PTS. */ |
84 | 0 | block_Release(block); |
85 | 0 | return NULL; |
86 | 0 | } |
87 | | |
88 | 274k | const unsigned int block_size = sys->is_pal ? 8640 : 7200; |
89 | 274k | if (block->i_buffer >= block_size) { |
90 | 26.8k | uint8_t *src = block->p_buffer; |
91 | | |
92 | 26.8k | block->i_buffer -= block_size; |
93 | 26.8k | block->p_buffer += block_size; |
94 | | |
95 | 26.8k | int sample_count = dv_get_audio_sample_count(&src[244], sys->is_pal); |
96 | | |
97 | 26.8k | if( decoder_UpdateAudioFormat(dec)) |
98 | 26.8k | return NULL; |
99 | 0 | block_t *output = decoder_NewAudioBuffer(dec, sample_count); |
100 | 0 | if (!output) |
101 | 0 | return NULL; |
102 | 0 | output->i_pts = date_Get(&sys->end_date); |
103 | 0 | output->i_length = date_Increment(&sys->end_date, sample_count) - output->i_pts; |
104 | |
|
105 | 0 | int16_t *dst = (int16_t*)output->p_buffer; |
106 | 0 | for (int i = 0; i < sample_count; i++) { |
107 | 0 | const uint8_t *v = &src[sys->shuffle[i]]; |
108 | 0 | if (sys->is_12bit) { |
109 | 0 | *dst++ = dv_audio_12to16((v[0] << 4) | ((v[2] >> 4) & 0x0f)); |
110 | 0 | *dst++ = dv_audio_12to16((v[1] << 4) | ((v[2] >> 0) & 0x0f)); |
111 | 0 | } else { |
112 | 0 | *dst++ = GetWBE(&v[0]); |
113 | 0 | *dst++ = GetWBE(&v[sys->is_pal ? 4320 : 3600]); |
114 | 0 | } |
115 | 0 | } |
116 | 0 | return output; |
117 | 0 | } |
118 | 247k | block_Release(block); |
119 | 247k | return NULL; |
120 | 274k | } |
121 | | |
122 | | static int DecodeAudio(decoder_t *dec, block_t *block) |
123 | 549k | { |
124 | 549k | if (block == NULL) /* No Drain */ |
125 | 274k | return VLCDEC_SUCCESS; |
126 | | |
127 | 274k | block_t **block_ptr = &block, *out; |
128 | 274k | while ((out = DecodeBlock(dec, block_ptr)) != NULL) |
129 | 0 | decoder_QueueAudio(dec,out); |
130 | 274k | return VLCDEC_SUCCESS; |
131 | 549k | } |
132 | | |
133 | | static int Open(vlc_object_t *object) |
134 | 582k | { |
135 | 582k | decoder_t *dec = (decoder_t*)object; |
136 | | |
137 | 582k | if (dec->fmt_in->i_codec != VLC_CODEC_ULEAD_DV_AUDIO_NTSC && |
138 | 582k | dec->fmt_in->i_codec != VLC_CODEC_ULEAD_DV_AUDIO_PAL) |
139 | 582k | return VLC_EGENERIC; |
140 | 138 | if (dec->fmt_in->audio.i_bitspersample != 12 && dec->fmt_in->audio.i_bitspersample != 16) |
141 | 10 | return VLC_EGENERIC; |
142 | 128 | if (dec->fmt_in->audio.i_channels != 2) |
143 | 2 | return VLC_EGENERIC; |
144 | 126 | if (dec->fmt_in->audio.i_rate <= 0) |
145 | 1 | return VLC_EGENERIC; |
146 | | |
147 | 125 | decoder_sys_t *sys = dec->p_sys = vlc_obj_malloc(object, sizeof(*sys)); |
148 | 125 | if (!sys) |
149 | 0 | return VLC_ENOMEM; |
150 | | |
151 | 125 | sys->is_pal = dec->fmt_in->i_codec == VLC_CODEC_ULEAD_DV_AUDIO_PAL; |
152 | 125 | sys->is_12bit = dec->fmt_in->audio.i_bitspersample == 12; |
153 | | |
154 | 125 | date_Init(&sys->end_date, dec->fmt_in->audio.i_rate, 1); |
155 | | |
156 | 250k | for (unsigned i = 0; i < sizeof(sys->shuffle) / sizeof(*sys->shuffle); i++) { |
157 | 250k | const unsigned a = sys->is_pal ? 18 : 15; |
158 | 250k | const unsigned b = 3 * a; |
159 | 250k | sys->shuffle[i] = 80 * ((21 * (i % 3) + 9 * (i / 3) + ((i / a) % 3)) % b) + |
160 | 250k | (2 + sys->is_12bit) * (i / b) + 8; |
161 | 250k | } |
162 | | |
163 | 125 | dec->fmt_out.i_codec = VLC_CODEC_S16N; |
164 | 125 | dec->fmt_out.audio.i_rate = dec->fmt_in->audio.i_rate; |
165 | 125 | dec->fmt_out.audio.i_channels = 2; |
166 | 125 | dec->fmt_out.audio.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; |
167 | | |
168 | 125 | dec->pf_decode = DecodeAudio; |
169 | 125 | dec->pf_flush = Flush; |
170 | | |
171 | 125 | return VLC_SUCCESS; |
172 | 125 | } |