/src/vlc/modules/demux/mpeg/es.c
Line | Count | Source (jump to first uncovered line) |
1 | | /***************************************************************************** |
2 | | * es.c : Generic audio ES input module for vlc |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2001-2008 VLC authors and VideoLAN |
5 | | * 2022 VideoLabs |
6 | | * |
7 | | * Authors: Laurent Aimar <fenrir@via.ecp.fr> |
8 | | * Gildas Bazin <gbazin@videolan.org> |
9 | | * |
10 | | * This program is free software; you can redistribute it and/or modify it |
11 | | * under the terms of the GNU Lesser General Public License as published by |
12 | | * the Free Software Foundation; either version 2.1 of the License, or |
13 | | * (at your option) any later version. |
14 | | * |
15 | | * This program is distributed in the hope that it will be useful, |
16 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | | * GNU Lesser General Public License for more details. |
19 | | * |
20 | | * You should have received a copy of the GNU Lesser General Public License |
21 | | * along with this program; if not, write to the Free Software Foundation, |
22 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
23 | | *****************************************************************************/ |
24 | | |
25 | | /***************************************************************************** |
26 | | * Preamble |
27 | | *****************************************************************************/ |
28 | | |
29 | | #ifdef HAVE_CONFIG_H |
30 | | # include "config.h" |
31 | | #endif |
32 | | |
33 | | #include <math.h> |
34 | | |
35 | | #include <vlc_common.h> |
36 | | #include <vlc_arrays.h> |
37 | | #include <vlc_plugin.h> |
38 | | #include <vlc_demux.h> |
39 | | #include <vlc_codec.h> |
40 | | #include <vlc_codecs.h> |
41 | | #include <vlc_input.h> |
42 | | #include <vlc_replay_gain.h> |
43 | | |
44 | | #include "../../packetizer/a52.h" |
45 | | #include "../../packetizer/dts_header.h" |
46 | | #include "../../packetizer/mpegaudio.h" |
47 | | #include "../../meta_engine/ID3Tag.h" |
48 | | #include "../../meta_engine/ID3Text.h" |
49 | | #include "../../meta_engine/ID3Meta.h" |
50 | | |
51 | | /***************************************************************************** |
52 | | * Module descriptor |
53 | | *****************************************************************************/ |
54 | | static int OpenAudio( vlc_object_t * ); |
55 | | static int OpenVideo( vlc_object_t * ); |
56 | | static void Close ( vlc_object_t * ); |
57 | | |
58 | | #define FPS_TEXT N_("Frames per Second") |
59 | | #define FPS_LONGTEXT N_("This is the frame rate used as a fallback when " \ |
60 | | "playing MPEG video elementary streams.") |
61 | | |
62 | 104 | vlc_module_begin () |
63 | 52 | set_subcategory( SUBCAT_INPUT_DEMUX ) |
64 | 52 | set_description( N_("MPEG-I/II/4 / A52 / DTS / MLP audio" ) ) |
65 | 52 | set_shortname( N_("Audio ES") ) |
66 | 52 | set_capability( "demux", 155 ) |
67 | 104 | set_callbacks( OpenAudio, Close ) |
68 | | |
69 | 52 | add_shortcut( "mpga", "mp3", |
70 | 52 | "m4a", "mp4a", "aac", |
71 | 52 | "ac3", "a52", |
72 | 52 | "eac3", |
73 | 52 | "dts", |
74 | 52 | "mlp", "thd" ) |
75 | | |
76 | 52 | add_submodule() |
77 | 52 | set_description( N_("MPEG-4 video" ) ) |
78 | 52 | set_capability( "demux", 7 ) |
79 | 104 | set_callbacks( OpenVideo, Close ) |
80 | 52 | add_float( "es-fps", 25, FPS_TEXT, FPS_LONGTEXT ) |
81 | | |
82 | 52 | add_shortcut( "m4v" ) |
83 | 52 | add_shortcut( "mp4v" ) |
84 | 52 | vlc_module_end () |
85 | | |
86 | | /***************************************************************************** |
87 | | * Local prototypes |
88 | | *****************************************************************************/ |
89 | | static int Demux ( demux_t * ); |
90 | | static int Control( demux_t *, int, va_list ); |
91 | | |
92 | 1.59M | #define WAV_PROBE_SIZE (512*1024) |
93 | 3.91k | #define BASE_PROBE_SIZE (8000) |
94 | 22.7k | #define WAV_EXTRA_PROBE_SIZE (44000/2*2*2) |
95 | | |
96 | | typedef struct |
97 | | { |
98 | | vlc_fourcc_t i_codec; |
99 | | bool b_use_word; |
100 | | const char *psz_name; |
101 | | int (*pf_probe)( demux_t *p_demux, uint64_t *pi_offset ); |
102 | | int (*pf_init)( demux_t *p_demux ); |
103 | | } codec_t; |
104 | | |
105 | | typedef struct |
106 | | { |
107 | | vlc_tick_t i_time; |
108 | | uint64_t i_pos; |
109 | | bs_t br; |
110 | | } sync_table_ctx_t; |
111 | | |
112 | | typedef struct |
113 | | { |
114 | | uint16_t i_frames_btw_refs; |
115 | | uint32_t i_bytes_btw_refs; |
116 | | uint32_t i_ms_btw_refs; |
117 | | uint8_t i_bits_per_bytes_dev; |
118 | | uint8_t i_bits_per_ms_dev; |
119 | | uint8_t *p_bits; |
120 | | size_t i_bits; |
121 | | sync_table_ctx_t current; |
122 | | } sync_table_t; |
123 | | |
124 | | typedef struct |
125 | | { |
126 | | uint32_t i_offset; |
127 | | seekpoint_t *p_seekpoint; |
128 | | } chap_entry_t; |
129 | | |
130 | | /* Mpga specific */ |
131 | 469 | #define XING_FIELD_STREAMFRAMES (1 << 0) |
132 | 469 | #define XING_FIELD_STREAMBYTES (1 << 1) |
133 | 469 | #define XING_FIELD_TOC (1 << 2) |
134 | 469 | #define XING_FIELD_QUALITY (1 << 3) |
135 | 3.09k | #define XING_MIN_TAG_SIZE 42 |
136 | 210 | #define XING_TOC_COUNTBYTES 100 |
137 | | #define XING_MAX_TAG_SIZE (XING_MIN_TAG_SIZE + 4 + 4 + XING_TOC_COUNTBYTES + 4 + 2) |
138 | | #define XING_SUB_ETE_NOK_OTAE XING_MIN_TAG_SIZE |
139 | | |
140 | | struct xing_info_s |
141 | | { |
142 | | uint32_t i_frames; |
143 | | uint32_t i_bytes; |
144 | | uint32_t i_quality; |
145 | | vlc_fourcc_t infotag; |
146 | | vlc_fourcc_t encoder; |
147 | | uint8_t rgi_toc[XING_TOC_COUNTBYTES]; |
148 | | float f_peak_signal; |
149 | | float f_radio_replay_gain; |
150 | | float f_audiophile_replay_gain; |
151 | | enum |
152 | | { |
153 | | XING_MODE_UNKNOWN = 0, |
154 | | XING_MODE_CBR = 1, |
155 | | XING_MODE_ABR = 2, |
156 | | XING_MODE_VBR1 = 3, |
157 | | XING_MODE_VBR2 = 4, |
158 | | XING_MODE_VBR3 = 5, |
159 | | XING_MODE_VBR4 = 6, |
160 | | XING_MODE_CBR_2PASS = 8, |
161 | | XING_MODE_ABR_2PASS = 9, |
162 | | } brmode; |
163 | | enum |
164 | | { |
165 | | XING_AUDIOMODE_UNKNOWN = 0, |
166 | | XING_AUDIOMODE_DPL = 1, |
167 | | XING_AUDIOMODE_DPL2 = 2, |
168 | | XING_AUDIOMODE_AMBISONICS = 3, |
169 | | } audiomode; |
170 | | uint8_t bitrate_avg; |
171 | | uint16_t i_delay_samples; |
172 | | uint16_t i_padding_samples; |
173 | | uint32_t i_music_length; |
174 | | }; |
175 | | |
176 | | static int ParseXing( const uint8_t *p_buf, size_t i_buf, struct xing_info_s *xing ) |
177 | 2.62k | { |
178 | 2.62k | if( i_buf < XING_MIN_TAG_SIZE ) |
179 | 243 | return VLC_EGENERIC; |
180 | | |
181 | 2.38k | vlc_fourcc_t infotag = VLC_FOURCC(p_buf[0], p_buf[1], p_buf[2], p_buf[3]); |
182 | | |
183 | | /* L3Enc VBR info */ |
184 | 2.38k | if( infotag == VLC_FOURCC('V','B','R','I') ) |
185 | 231 | { |
186 | 231 | if( GetWBE( &p_buf[4] ) != 0x0001 ) |
187 | 42 | return VLC_EGENERIC; |
188 | 189 | xing->i_bytes = GetDWBE( &p_buf[10] ); |
189 | 189 | xing->i_frames = GetDWBE( &p_buf[14] ); |
190 | 189 | xing->infotag = infotag; |
191 | 189 | return VLC_SUCCESS; |
192 | 231 | } |
193 | | /* Xing VBR/CBR tags */ |
194 | 2.15k | else if( infotag != VLC_FOURCC('X','i','n','g') && |
195 | 2.15k | infotag != VLC_FOURCC('I','n','f','o') ) |
196 | 1.67k | { |
197 | 1.67k | return VLC_EGENERIC; |
198 | 1.67k | } |
199 | | |
200 | 475 | xing->infotag = infotag; |
201 | | |
202 | 475 | const uint32_t i_flags = GetDWBE( &p_buf[4] ); |
203 | | /* compute our variable struct size for early checks */ |
204 | 475 | const unsigned varsz[4] = { ((i_flags & 0x01) ? 4 : 0), |
205 | 475 | ((i_flags & 0x02) ? 4 : 0), |
206 | 475 | ((i_flags & 0x04) ? XING_TOC_COUNTBYTES : 0), |
207 | 475 | ((i_flags & 0x08) ? 4 : 0) }; |
208 | 475 | const unsigned i_varallsz = varsz[0] + varsz[1] + varsz[2] + varsz[3]; |
209 | 475 | const unsigned i_tag_total = XING_MIN_TAG_SIZE + i_varallsz; |
210 | | |
211 | 475 | if( i_buf < i_tag_total ) |
212 | 6 | return VLC_EGENERIC; |
213 | | |
214 | 469 | if( i_flags & XING_FIELD_STREAMFRAMES ) |
215 | 228 | xing->i_frames = GetDWBE( &p_buf[8] ); |
216 | 469 | if( i_flags & XING_FIELD_STREAMBYTES ) |
217 | 221 | xing->i_bytes = GetDWBE( &p_buf[8 + varsz[0]] ); |
218 | 469 | if( i_flags & XING_FIELD_TOC ) |
219 | 104 | memcpy( xing->rgi_toc, &p_buf[8 + varsz[0] + varsz[1]], XING_TOC_COUNTBYTES ); |
220 | 469 | if( i_flags & XING_FIELD_QUALITY ) |
221 | 144 | xing->i_quality = GetDWBE( &p_buf[8 + varsz[0] + varsz[1] + varsz[2]] ); |
222 | | |
223 | | /* pointer past optional members */ |
224 | 469 | const uint8_t *p_fixed = &p_buf[8 + i_varallsz]; |
225 | | |
226 | | /* Original Xing encoder header stops here */ |
227 | | |
228 | 469 | xing->encoder = VLC_FOURCC(p_fixed[0], p_fixed[1], p_fixed[2], p_fixed[3]); /* char version[9] start */ |
229 | | |
230 | 469 | if( xing->encoder != VLC_FOURCC('L','A','M','E') && |
231 | 469 | xing->encoder != VLC_FOURCC('L','a','v','c') && |
232 | 469 | xing->encoder != VLC_FOURCC('L','a','v','f') ) |
233 | 398 | return VLC_SUCCESS; |
234 | | |
235 | 71 | xing->brmode = p_fixed[9] & 0x0f; /* version upper / mode lower */ |
236 | 71 | uint32_t peak_signal = GetDWBE( &p_fixed[11] ); |
237 | 71 | xing->f_peak_signal = peak_signal / 8388608.0; /* pow(2, 23) */ |
238 | 71 | uint16_t gain = GetWBE( &p_fixed[15] ); |
239 | 71 | xing->f_radio_replay_gain = (gain & 0x1FF) / /* 9bits val stored x10 */ |
240 | 71 | ((gain & 0x200) ? -10.0 : 10.0); /* -sign bit on bit 6 */ |
241 | 71 | gain = GetWBE( &p_fixed[17] ); |
242 | 71 | xing->f_radio_replay_gain = (gain & 0x1FF) / /* 9bits val stored x10 */ |
243 | 71 | ((gain & 0x200) ? -10.0 : 10.0); /* -sign bit on bit 6 */ |
244 | | /* flags @19 */ |
245 | 71 | xing->bitrate_avg = (p_fixed[20] != 0xFF) ? p_fixed[20] : 0; /* clipped to 255, so it's unknown from there */ |
246 | 71 | xing->i_delay_samples = (p_fixed[21] << 4) | (p_fixed[22] >> 4); /* upper 12bits */ |
247 | 71 | xing->i_padding_samples = ((p_fixed[22] & 0x0F) << 8) | p_fixed[23]; /* lower 12bits */ |
248 | 71 | xing->audiomode = (p_fixed[26] >> 3) & 0x07; /* over 16bits, 2b unused / 3b mode / 11b preset */ |
249 | 71 | xing->i_music_length = GetDWBE( &p_fixed[28] ); |
250 | | |
251 | 71 | return VLC_SUCCESS; |
252 | 469 | } |
253 | | |
254 | | static int MpgaGetCBRSeekpoint( const struct mpga_frameheader_s *mpgah, |
255 | | const struct xing_info_s *xing, |
256 | | uint64_t i_seekablesize, |
257 | | double f_pos, vlc_tick_t *pi_time, uint64_t *pi_offset ) |
258 | 0 | { |
259 | 0 | if( xing->infotag != 0 && |
260 | 0 | xing->infotag != VLC_FOURCC('I','n','f','o') && |
261 | 0 | xing->brmode != XING_MODE_CBR && |
262 | 0 | xing->brmode != XING_MODE_CBR_2PASS ) |
263 | 0 | return -1; |
264 | | |
265 | 0 | if( !mpgah->i_sample_rate || !mpgah->i_samples_per_frame || !mpgah->i_frame_size ) |
266 | 0 | return -1; |
267 | | |
268 | 0 | uint32_t i_total_frames = xing->i_frames ? xing->i_frames |
269 | 0 | : i_seekablesize / mpgah->i_frame_size; |
270 | | |
271 | | /* xing must be optional here */ |
272 | 0 | uint32_t i_frame = i_total_frames * f_pos; |
273 | 0 | *pi_offset = i_frame * mpgah->i_frame_size; |
274 | 0 | *pi_time = vlc_tick_from_samples( i_frame * mpgah->i_samples_per_frame, |
275 | 0 | mpgah->i_sample_rate ) + VLC_TICK_0; |
276 | |
|
277 | 0 | return 0; |
278 | 0 | } |
279 | | |
280 | | static int SeekByPosUsingXingTOC( const struct mpga_frameheader_s *mpgah, |
281 | | const struct xing_info_s *xing,double pos, |
282 | | vlc_tick_t *pi_time, uint64_t *pi_offset ) |
283 | 0 | { |
284 | 0 | if( !xing->rgi_toc[XING_TOC_COUNTBYTES - 1] || |
285 | 0 | !mpgah->i_sample_rate || !mpgah->i_samples_per_frame ) |
286 | 0 | return -1; |
287 | | |
288 | 0 | unsigned syncentry = pos * XING_TOC_COUNTBYTES; |
289 | 0 | syncentry = VLC_CLIP(syncentry, 0, XING_TOC_COUNTBYTES - 1); |
290 | 0 | unsigned syncframe = syncentry * xing->i_frames / XING_TOC_COUNTBYTES; |
291 | |
|
292 | 0 | *pi_time = vlc_tick_from_samples( syncframe * mpgah->i_samples_per_frame, |
293 | 0 | mpgah->i_sample_rate ) + VLC_TICK_0; |
294 | 0 | *pi_offset = xing->rgi_toc[syncentry] * xing->i_bytes / 256; |
295 | |
|
296 | 0 | return 0; |
297 | 0 | } |
298 | | |
299 | | static int SeekByTimeUsingXingTOC( const struct mpga_frameheader_s *mpgah, |
300 | | const struct xing_info_s *xing, |
301 | | vlc_tick_t *pi_time, uint64_t *pi_offset ) |
302 | 0 | { |
303 | 0 | if( !mpgah->i_sample_rate || !mpgah->i_samples_per_frame || !xing->i_frames || |
304 | 0 | *pi_time < VLC_TICK_0 ) |
305 | 0 | return -1; |
306 | | |
307 | 0 | uint32_t sample = samples_from_vlc_tick( *pi_time - VLC_TICK_0, mpgah->i_sample_rate ); |
308 | 0 | uint64_t totalsamples = mpgah->i_samples_per_frame * (uint64_t) xing->i_frames; |
309 | |
|
310 | 0 | return SeekByPosUsingXingTOC( mpgah, xing, (double)sample / totalsamples, |
311 | 0 | pi_time, pi_offset ); |
312 | 0 | } |
313 | | |
314 | | static int MpgaSeek( const struct mpga_frameheader_s *mpgah, |
315 | | const struct xing_info_s *xing, |
316 | | uint64_t i_seekablesize, double f_pos, |
317 | | vlc_tick_t *pi_time, uint64_t *pi_offset ) |
318 | 0 | { |
319 | 0 | if( f_pos >= 0 ) /* Set Pos */ |
320 | 0 | { |
321 | 0 | if( !MpgaGetCBRSeekpoint( mpgah, xing, i_seekablesize, |
322 | 0 | f_pos, pi_time, pi_offset ) ) |
323 | 0 | { |
324 | 0 | return 0; |
325 | 0 | } |
326 | 0 | } |
327 | | |
328 | 0 | if( *pi_time != VLC_TICK_INVALID && |
329 | 0 | !SeekByTimeUsingXingTOC( mpgah, xing, pi_time, pi_offset ) ) |
330 | 0 | return 0; |
331 | | |
332 | 0 | return SeekByPosUsingXingTOC( mpgah, xing, f_pos, pi_time, pi_offset ); |
333 | 0 | } |
334 | | |
335 | | typedef struct |
336 | | { |
337 | | codec_t codec; |
338 | | vlc_fourcc_t i_original; |
339 | | |
340 | | es_out_id_t *p_es; |
341 | | |
342 | | bool b_start; |
343 | | decoder_t *p_packetizer; |
344 | | block_t *p_packetized_data; |
345 | | |
346 | | vlc_tick_t i_pts; |
347 | | vlc_tick_t i_time_offset; |
348 | | uint64_t i_bytes; |
349 | | |
350 | | bool b_big_endian; |
351 | | bool b_estimate_bitrate; |
352 | | unsigned i_bitrate; /* extracted from Xing header */ |
353 | | vlc_tick_t i_duration; |
354 | | |
355 | | bool b_initial_sync_failed; |
356 | | |
357 | | unsigned i_packet_size; |
358 | | |
359 | | uint64_t i_stream_offset; |
360 | | unsigned i_demux_flags; |
361 | | |
362 | | float f_fps; |
363 | | |
364 | | /* Mpga specific */ |
365 | | struct mpga_frameheader_s mpgah; |
366 | | struct xing_info_s xing; |
367 | | |
368 | | audio_replay_gain_t audio_replay_gain; |
369 | | |
370 | | sync_table_t mllt; |
371 | | struct |
372 | | { |
373 | | size_t i_count; |
374 | | size_t i_current; |
375 | | chap_entry_t *p_entry; |
376 | | } chapters; |
377 | | } demux_sys_t; |
378 | | |
379 | | static int MpgaProbe( demux_t *p_demux, uint64_t *pi_offset ); |
380 | | static int MpgaInit( demux_t *p_demux ); |
381 | | |
382 | | static int AacProbe( demux_t *p_demux, uint64_t *pi_offset ); |
383 | | static int AacInit( demux_t *p_demux ); |
384 | | |
385 | | static int EA52Probe( demux_t *p_demux, uint64_t *pi_offset ); |
386 | | static int A52Probe( demux_t *p_demux, uint64_t *pi_offset ); |
387 | | static int A52Init( demux_t *p_demux ); |
388 | | |
389 | | static int DtsProbe( demux_t *p_demux, uint64_t *pi_offset ); |
390 | | static int DtsInit( demux_t *p_demux ); |
391 | | |
392 | | static int MlpProbe( demux_t *p_demux, uint64_t *pi_offset ); |
393 | | static int ThdProbe( demux_t *p_demux, uint64_t *pi_offset ); |
394 | | static int MlpInit( demux_t *p_demux ); |
395 | | |
396 | | static bool Parse( demux_t *p_demux, block_t **pp_output ); |
397 | | static int SeekByMlltTable( sync_table_t *, vlc_tick_t *, uint64_t * ); |
398 | | |
399 | | static const codec_t p_codecs[] = { |
400 | | { VLC_CODEC_MP4A, false, "mp4 audio", AacProbe, AacInit }, |
401 | | { VLC_CODEC_MPGA, false, "mpeg audio", MpgaProbe, MpgaInit }, |
402 | | { VLC_CODEC_A52, true, "a52 audio", A52Probe, A52Init }, |
403 | | { VLC_CODEC_EAC3, true, "eac3 audio", EA52Probe, A52Init }, |
404 | | { VLC_CODEC_DTS, false, "dts audio", DtsProbe, DtsInit }, |
405 | | { VLC_CODEC_MLP, false, "mlp audio", MlpProbe, MlpInit }, |
406 | | { VLC_CODEC_TRUEHD, false, "TrueHD audio", ThdProbe, MlpInit }, |
407 | | |
408 | | { 0, false, NULL, NULL, NULL } |
409 | | }; |
410 | | |
411 | | static int VideoInit( demux_t *p_demux ); |
412 | | |
413 | | static const codec_t codec_m4v = { |
414 | | VLC_CODEC_MP4V, false, "mp4 video", NULL, VideoInit |
415 | | }; |
416 | | |
417 | | /***************************************************************************** |
418 | | * OpenCommon: initializes demux structures |
419 | | *****************************************************************************/ |
420 | | static int OpenCommon( demux_t *p_demux, |
421 | | int i_cat, const codec_t *p_codec, uint64_t i_bs_offset ) |
422 | 9.33k | { |
423 | 9.33k | demux_sys_t *p_sys; |
424 | | |
425 | 9.33k | es_format_t fmt; |
426 | | |
427 | 9.33k | DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys; |
428 | 9.33k | memset( p_sys, 0, sizeof( demux_sys_t ) ); |
429 | 9.33k | p_sys->codec = *p_codec; |
430 | 9.33k | p_sys->p_es = NULL; |
431 | 9.33k | p_sys->b_start = true; |
432 | 9.33k | p_sys->i_stream_offset = i_bs_offset; |
433 | 9.33k | p_sys->b_estimate_bitrate = true; |
434 | 9.33k | p_sys->i_bitrate = 0; |
435 | 9.33k | p_sys->i_duration = 0; |
436 | 9.33k | p_sys->b_big_endian = false; |
437 | 9.33k | p_sys->f_fps = var_InheritFloat( p_demux, "es-fps" ); |
438 | 9.33k | p_sys->p_packetized_data = NULL; |
439 | 9.33k | p_sys->chapters.i_current = 0; |
440 | 9.33k | p_sys->xing.f_peak_signal = NAN; |
441 | 9.33k | p_sys->xing.f_radio_replay_gain = NAN; |
442 | 9.33k | p_sys->xing.f_audiophile_replay_gain = NAN; |
443 | 9.33k | TAB_INIT(p_sys->chapters.i_count, p_sys->chapters.p_entry); |
444 | | |
445 | 9.33k | if( vlc_stream_Seek( p_demux->s, p_sys->i_stream_offset ) ) |
446 | 0 | { |
447 | 0 | free( p_sys ); |
448 | 0 | return VLC_EGENERIC; |
449 | 0 | } |
450 | | |
451 | 9.33k | if( p_sys->codec.pf_init( p_demux ) ) |
452 | 0 | { |
453 | 0 | free( p_sys ); |
454 | 0 | return VLC_EGENERIC; |
455 | 0 | } |
456 | | |
457 | 9.33k | if( vlc_stream_Seek( p_demux->s, p_sys->i_stream_offset ) ) |
458 | 0 | { |
459 | 0 | free( p_sys ); |
460 | 0 | return VLC_EGENERIC; |
461 | 0 | } |
462 | | |
463 | 9.33k | msg_Dbg( p_demux, "detected format %4.4s", (const char*)&p_sys->codec.i_codec ); |
464 | | |
465 | | /* Load the audio packetizer */ |
466 | 9.33k | es_format_Init( &fmt, i_cat, p_sys->codec.i_codec ); |
467 | 9.33k | fmt.i_original_fourcc = p_sys->i_original; |
468 | 9.33k | p_sys->p_packetizer = demux_PacketizerNew( VLC_OBJECT(p_demux), &fmt, p_sys->codec.psz_name ); |
469 | 9.33k | if( !p_sys->p_packetizer ) |
470 | 0 | { |
471 | 0 | free( p_sys ); |
472 | 0 | return VLC_EGENERIC; |
473 | 0 | } |
474 | | |
475 | 9.33k | es_format_t *p_fmt = &p_sys->p_packetizer->fmt_out; |
476 | 9.33k | replay_gain_Merge( &p_fmt->audio_replay_gain, &p_sys->audio_replay_gain ); |
477 | | |
478 | 9.33k | for( ;; ) |
479 | 77.4k | { |
480 | 77.4k | if( Parse( p_demux, &p_sys->p_packetized_data ) ) |
481 | 5.07k | break; |
482 | 72.4k | if( p_sys->p_packetized_data ) |
483 | 4.25k | break; |
484 | 72.4k | } |
485 | | |
486 | 9.33k | return VLC_SUCCESS; |
487 | 9.33k | } |
488 | | static int OpenAudio( vlc_object_t *p_this ) |
489 | 10.3k | { |
490 | 10.3k | demux_t *p_demux = (demux_t*)p_this; |
491 | 44.5k | for( int i = 0; p_codecs[i].i_codec != 0; i++ ) |
492 | 43.5k | { |
493 | 43.5k | uint64_t i_offset; |
494 | 43.5k | if( !p_codecs[i].pf_probe( p_demux, &i_offset ) ) |
495 | 9.33k | return OpenCommon( p_demux, AUDIO_ES, &p_codecs[i], i_offset ); |
496 | 43.5k | } |
497 | 1.02k | return VLC_EGENERIC; |
498 | 10.3k | } |
499 | | static int OpenVideo( vlc_object_t *p_this ) |
500 | 0 | { |
501 | 0 | demux_t *p_demux = (demux_t*)p_this; |
502 | | |
503 | | /* Only m4v is supported for the moment */ |
504 | 0 | bool b_m4v_ext = demux_IsPathExtension( p_demux, ".m4v" ); |
505 | 0 | bool b_re4_ext = !b_m4v_ext && demux_IsPathExtension( p_demux, ".re4" ); |
506 | 0 | bool b_m4v_forced = demux_IsForced( p_demux, "m4v" ) || |
507 | 0 | demux_IsForced( p_demux, "mp4v" ); |
508 | |
|
509 | 0 | if( !b_m4v_ext && !b_m4v_forced && !b_re4_ext ) |
510 | 0 | return VLC_EGENERIC; |
511 | | |
512 | 0 | ssize_t i_off = b_re4_ext ? 220 : 0; |
513 | 0 | const uint8_t *p_peek; |
514 | 0 | if( vlc_stream_Peek( p_demux->s, &p_peek, i_off + 4 ) < i_off + 4 ) |
515 | 0 | return VLC_EGENERIC; |
516 | 0 | if( p_peek[i_off + 0] != 0x00 || p_peek[i_off + 1] != 0x00 || p_peek[i_off + 2] != 0x01 ) |
517 | 0 | { |
518 | 0 | if( !b_m4v_forced) |
519 | 0 | return VLC_EGENERIC; |
520 | 0 | msg_Warn( p_demux, |
521 | 0 | "this doesn't look like an MPEG ES stream, continuing anyway" ); |
522 | 0 | } |
523 | 0 | return OpenCommon( p_demux, VIDEO_ES, &codec_m4v, i_off ); |
524 | 0 | } |
525 | | |
526 | | static void IncreaseChapter( demux_t *p_demux, vlc_tick_t i_time ) |
527 | 70.9k | { |
528 | 70.9k | demux_sys_t *p_sys = p_demux->p_sys; |
529 | 70.9k | while( p_sys->chapters.i_current + 1 < p_sys->chapters.i_count ) |
530 | 0 | { |
531 | 0 | const chap_entry_t *p = &p_sys->chapters.p_entry[p_sys->chapters.i_current + 1]; |
532 | 0 | if( (p->i_offset != UINT32_MAX && vlc_stream_Tell( p_demux->s ) < p->i_offset) || |
533 | 0 | (i_time == VLC_TICK_INVALID || p->p_seekpoint->i_time_offset + VLC_TICK_0 > i_time) ) |
534 | 0 | break; |
535 | 0 | ++p_sys->chapters.i_current; |
536 | 0 | p_sys->i_demux_flags |= INPUT_UPDATE_SEEKPOINT; |
537 | 0 | } |
538 | 70.9k | } |
539 | | |
540 | | /***************************************************************************** |
541 | | * Demux: reads and demuxes data packets |
542 | | ***************************************************************************** |
543 | | * Returns -1 in case of error, 0 in case of EOF, 1 otherwise |
544 | | *****************************************************************************/ |
545 | | static int Demux( demux_t *p_demux ) |
546 | 70.9k | { |
547 | 70.9k | int ret = 1; |
548 | 70.9k | demux_sys_t *p_sys = p_demux->p_sys; |
549 | | |
550 | 70.9k | block_t *p_block_out = p_sys->p_packetized_data; |
551 | 70.9k | if( p_block_out ) |
552 | 5.37k | p_sys->p_packetized_data = NULL; |
553 | 65.5k | else |
554 | 65.5k | ret = Parse( p_demux, &p_block_out ) ? 0 : 1; |
555 | | |
556 | | /* Update chapter if any */ |
557 | 70.9k | IncreaseChapter( p_demux, |
558 | 70.9k | p_block_out ? p_sys->i_time_offset + p_block_out->i_dts |
559 | 70.9k | : VLC_TICK_INVALID ); |
560 | | |
561 | 1.42M | while( p_block_out ) |
562 | 1.35M | { |
563 | 1.35M | block_t *p_next = p_block_out->p_next; |
564 | | |
565 | | /* Correct timestamp */ |
566 | 1.35M | if( p_sys->p_packetizer->fmt_out.i_cat == VIDEO_ES ) |
567 | 0 | { |
568 | 0 | if( p_block_out->i_pts == VLC_TICK_INVALID && |
569 | 0 | p_block_out->i_dts == VLC_TICK_INVALID ) |
570 | 0 | p_block_out->i_dts = VLC_TICK_0 + p_sys->i_pts + VLC_TICK_FROM_SEC(1) / p_sys->f_fps; |
571 | 0 | if( p_block_out->i_dts != VLC_TICK_INVALID ) |
572 | 0 | p_sys->i_pts = p_block_out->i_dts - VLC_TICK_0; |
573 | 0 | } |
574 | 1.35M | else |
575 | 1.35M | { |
576 | 1.35M | p_sys->i_pts = p_block_out->i_pts - VLC_TICK_0; |
577 | 1.35M | } |
578 | | |
579 | 1.35M | if( p_block_out->i_pts != VLC_TICK_INVALID ) |
580 | 1.34M | { |
581 | 1.34M | p_block_out->i_pts += p_sys->i_time_offset; |
582 | 1.34M | } |
583 | 1.35M | if( p_block_out->i_dts != VLC_TICK_INVALID ) |
584 | 1.34M | { |
585 | 1.34M | p_block_out->i_dts += p_sys->i_time_offset; |
586 | 1.34M | es_out_SetPCR( p_demux->out, p_block_out->i_dts ); |
587 | 1.34M | } |
588 | | /* Re-estimate bitrate */ |
589 | 1.35M | if( p_sys->b_estimate_bitrate && p_sys->i_pts > VLC_TICK_FROM_MS(500) ) |
590 | 1.29M | p_sys->i_bitrate = 8 * CLOCK_FREQ * p_sys->i_bytes |
591 | 1.29M | / (p_sys->i_pts - 1); |
592 | 1.35M | p_sys->i_bytes += p_block_out->i_buffer; |
593 | | |
594 | | |
595 | 1.35M | p_block_out->p_next = NULL; |
596 | 1.35M | es_out_Send( p_demux->out, p_sys->p_es, p_block_out ); |
597 | | |
598 | 1.35M | p_block_out = p_next; |
599 | 1.35M | } |
600 | 70.9k | return ret; |
601 | 70.9k | } |
602 | | |
603 | | /***************************************************************************** |
604 | | * Close: frees unused data |
605 | | *****************************************************************************/ |
606 | | static void Close( vlc_object_t * p_this ) |
607 | 9.33k | { |
608 | 9.33k | demux_t *p_demux = (demux_t*)p_this; |
609 | 9.33k | demux_sys_t *p_sys = p_demux->p_sys; |
610 | | |
611 | 9.33k | if( p_sys->p_packetized_data ) |
612 | 0 | block_ChainRelease( p_sys->p_packetized_data ); |
613 | 9.33k | for( size_t i=0; i< p_sys->chapters.i_count; i++ ) |
614 | 0 | vlc_seekpoint_Delete( p_sys->chapters.p_entry[i].p_seekpoint ); |
615 | 9.33k | TAB_CLEAN( p_sys->chapters.i_count, p_sys->chapters.p_entry ); |
616 | 9.33k | if( p_sys->mllt.p_bits ) |
617 | 0 | free( p_sys->mllt.p_bits ); |
618 | 9.33k | demux_PacketizerDestroy( p_sys->p_packetizer ); |
619 | 9.33k | free( p_sys ); |
620 | 9.33k | } |
621 | | |
622 | | /***************************************************************************** |
623 | | * Time seek: |
624 | | *****************************************************************************/ |
625 | | static void PostSeekCleanup( demux_sys_t *p_sys, vlc_tick_t i_time ) |
626 | 0 | { |
627 | | /* Fix time_offset */ |
628 | 0 | if( i_time >= 0 ) |
629 | 0 | p_sys->i_time_offset = i_time - p_sys->i_pts; |
630 | | /* And reset buffered data */ |
631 | 0 | if( p_sys->p_packetized_data ) |
632 | 0 | block_ChainRelease( p_sys->p_packetized_data ); |
633 | 0 | p_sys->p_packetized_data = NULL; |
634 | | /* Reset chapter if any */ |
635 | 0 | p_sys->chapters.i_current = 0; |
636 | 0 | p_sys->i_demux_flags |= INPUT_UPDATE_SEEKPOINT; |
637 | 0 | } |
638 | | |
639 | | static int MovetoTimePos( demux_t *p_demux, vlc_tick_t i_time, uint64_t i_pos ) |
640 | 0 | { |
641 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
642 | 0 | int i_ret = vlc_stream_Seek( p_demux->s, p_sys->i_stream_offset + i_pos ); |
643 | 0 | if( i_ret != VLC_SUCCESS ) |
644 | 0 | return i_ret; |
645 | 0 | PostSeekCleanup( p_sys, i_time ); |
646 | 0 | return VLC_SUCCESS; |
647 | 0 | } |
648 | | |
649 | | /***************************************************************************** |
650 | | * Control: |
651 | | *****************************************************************************/ |
652 | | static int Control( demux_t *p_demux, int i_query, va_list args ) |
653 | 0 | { |
654 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
655 | 0 | bool *pb_bool; |
656 | |
|
657 | 0 | switch( i_query ) |
658 | 0 | { |
659 | 0 | case DEMUX_HAS_UNSUPPORTED_META: |
660 | 0 | pb_bool = va_arg( args, bool * ); |
661 | 0 | *pb_bool = true; |
662 | 0 | return VLC_SUCCESS; |
663 | | |
664 | 0 | case DEMUX_GET_TIME: |
665 | 0 | *va_arg( args, vlc_tick_t * ) = p_sys->i_pts + p_sys->i_time_offset; |
666 | 0 | return VLC_SUCCESS; |
667 | | |
668 | 0 | case DEMUX_GET_LENGTH: |
669 | 0 | { |
670 | 0 | if( p_sys->i_duration > 0 ) |
671 | 0 | { |
672 | 0 | *va_arg( args, vlc_tick_t * ) = p_sys->i_duration; |
673 | 0 | return VLC_SUCCESS; |
674 | 0 | } |
675 | | /* compute length from bitrate */ |
676 | 0 | va_list ap; |
677 | 0 | int i_ret; |
678 | |
|
679 | 0 | va_copy ( ap, args ); |
680 | 0 | i_ret = demux_vaControlHelper( p_demux->s, p_sys->i_stream_offset, |
681 | 0 | -1, p_sys->i_bitrate, 1, i_query, ap ); |
682 | 0 | va_end( ap ); |
683 | | |
684 | | /* No bitrate, we can't have it precisely, but we can compute |
685 | | * a raw approximation with time/position */ |
686 | 0 | if( i_ret && !p_sys->i_bitrate ) |
687 | 0 | { |
688 | 0 | float f_pos = (double)(uint64_t)( vlc_stream_Tell( p_demux->s ) ) / |
689 | 0 | (double)(uint64_t)( stream_Size( p_demux->s ) ); |
690 | | /* The first few seconds are guaranteed to be very whacky, |
691 | | * don't bother trying ... Too bad */ |
692 | 0 | if( f_pos < 0.01f || |
693 | 0 | (p_sys->i_pts + p_sys->i_time_offset) < VLC_TICK_FROM_SEC(8) ) |
694 | 0 | { |
695 | 0 | return VLC_EGENERIC; |
696 | 0 | } |
697 | | |
698 | 0 | *va_arg( args, vlc_tick_t * ) = |
699 | 0 | (p_sys->i_pts + p_sys->i_time_offset) / f_pos; |
700 | 0 | return VLC_SUCCESS; |
701 | 0 | } |
702 | 0 | return i_ret; |
703 | 0 | } |
704 | | |
705 | 0 | case DEMUX_SET_TIME: |
706 | 0 | case DEMUX_SET_POSITION: |
707 | 0 | { |
708 | 0 | vlc_tick_t i_time; |
709 | 0 | double f_pos; |
710 | 0 | uint64_t i_offset; |
711 | |
|
712 | 0 | va_list ap; |
713 | 0 | va_copy ( ap, args ); /* don't break args for helper fallback */ |
714 | 0 | if( i_query == DEMUX_SET_TIME ) |
715 | 0 | { |
716 | 0 | i_time = va_arg(ap, vlc_tick_t); |
717 | 0 | f_pos = p_sys->i_duration ? i_time / (double) p_sys->i_duration : -1.0; |
718 | 0 | if( f_pos > 1.0 ) |
719 | 0 | f_pos = 1.0; |
720 | 0 | } |
721 | 0 | else |
722 | 0 | { |
723 | 0 | f_pos = va_arg(ap, double); |
724 | 0 | i_time = p_sys->i_duration ? p_sys->i_duration * f_pos : VLC_TICK_INVALID; |
725 | 0 | } |
726 | 0 | va_end( ap ); |
727 | | |
728 | | /* Try to use ID3 table */ |
729 | 0 | if( !SeekByMlltTable( &p_sys->mllt, &i_time, &i_offset ) ) |
730 | 0 | return MovetoTimePos( p_demux, i_time, i_offset ); |
731 | | |
732 | 0 | if( p_sys->codec.i_codec == VLC_CODEC_MPGA ) |
733 | 0 | { |
734 | 0 | uint64_t streamsize; |
735 | 0 | if( !vlc_stream_GetSize( p_demux->s, &streamsize ) && |
736 | 0 | streamsize > p_sys->i_stream_offset ) |
737 | 0 | streamsize -= p_sys->i_stream_offset; |
738 | 0 | else |
739 | 0 | streamsize = 0; |
740 | |
|
741 | 0 | if( !MpgaSeek( &p_sys->mpgah, &p_sys->xing, |
742 | 0 | streamsize, f_pos, &i_time, &i_offset ) ) |
743 | 0 | { |
744 | 0 | return MovetoTimePos( p_demux, i_time, i_offset ); |
745 | 0 | } |
746 | 0 | } |
747 | | |
748 | | /* fallback on bitrate / file position seeking */ |
749 | 0 | i_time = VLC_TICK_INVALID; |
750 | 0 | int ret = demux_vaControlHelper( p_demux->s, p_sys->i_stream_offset, -1, |
751 | 0 | p_sys->i_bitrate, 1, i_query, args ); |
752 | 0 | if( ret != VLC_SUCCESS ) |
753 | 0 | return ret; /* not much we can do */ |
754 | | |
755 | 0 | if( p_sys->i_bitrate > 0 ) |
756 | 0 | { |
757 | 0 | i_offset = vlc_stream_Tell( p_demux->s ); /* new pos */ |
758 | 0 | i_time = VLC_TICK_0; |
759 | 0 | if( likely(i_offset > p_sys->i_stream_offset) ) |
760 | 0 | { |
761 | 0 | i_offset -= p_sys->i_stream_offset; |
762 | 0 | i_time += vlc_tick_from_samples( i_offset * 8, p_sys->i_bitrate ); |
763 | 0 | } |
764 | 0 | } |
765 | 0 | PostSeekCleanup( p_sys, i_time ); |
766 | | |
767 | | /* FIXME TODO: implement a high precision seek (with mp3 parsing) |
768 | | * needed for multi-input */ |
769 | 0 | return VLC_SUCCESS; |
770 | 0 | } |
771 | | |
772 | 0 | case DEMUX_GET_TITLE_INFO: |
773 | 0 | { |
774 | 0 | if( p_sys->chapters.i_count == 0 ) |
775 | 0 | return VLC_EGENERIC; |
776 | 0 | input_title_t **pp_title = malloc( sizeof(*pp_title) ); |
777 | 0 | if( !pp_title ) |
778 | 0 | return VLC_EGENERIC; |
779 | 0 | *pp_title = vlc_input_title_New(); |
780 | 0 | if( !*pp_title ) |
781 | 0 | { |
782 | 0 | free( pp_title ); |
783 | 0 | return VLC_EGENERIC; |
784 | 0 | } |
785 | 0 | (*pp_title)->seekpoint = vlc_alloc( p_sys->chapters.i_count, sizeof(seekpoint_t) ); |
786 | 0 | if( !(*pp_title)->seekpoint ) |
787 | 0 | { |
788 | 0 | free( *pp_title ); |
789 | 0 | free( pp_title ); |
790 | 0 | return VLC_EGENERIC; |
791 | 0 | } |
792 | 0 | for( size_t i=0; i<p_sys->chapters.i_count; i++ ) |
793 | 0 | { |
794 | 0 | seekpoint_t *s = vlc_seekpoint_Duplicate( p_sys->chapters.p_entry[i].p_seekpoint ); |
795 | 0 | if( s ) |
796 | 0 | (*pp_title)->seekpoint[(*pp_title)->i_seekpoint++] = s; |
797 | 0 | } |
798 | 0 | *(va_arg( args, input_title_t *** )) = pp_title; |
799 | 0 | *(va_arg( args, int* )) = 1; |
800 | 0 | *(va_arg( args, int* )) = 0; |
801 | 0 | *(va_arg( args, int* )) = 0; |
802 | 0 | return VLC_SUCCESS; |
803 | 0 | } |
804 | 0 | break; |
805 | | |
806 | 0 | case DEMUX_GET_TITLE: |
807 | 0 | if( p_sys->chapters.i_count == 0 ) |
808 | 0 | return VLC_EGENERIC; |
809 | 0 | *(va_arg( args, int* )) = 0; |
810 | 0 | return VLC_SUCCESS; |
811 | | |
812 | 0 | case DEMUX_GET_SEEKPOINT: |
813 | 0 | if( p_sys->chapters.i_count == 0 ) |
814 | 0 | return VLC_EGENERIC; |
815 | 0 | *(va_arg( args, int* )) = p_sys->chapters.i_current; |
816 | 0 | return VLC_SUCCESS; |
817 | | |
818 | 0 | case DEMUX_SET_TITLE: |
819 | 0 | return va_arg( args, int) == 0 ? VLC_SUCCESS : VLC_EGENERIC; |
820 | | |
821 | 0 | case DEMUX_SET_SEEKPOINT: |
822 | 0 | { |
823 | 0 | int i = va_arg( args, int ); |
824 | 0 | if( (size_t)i>=p_sys->chapters.i_count ) |
825 | 0 | return VLC_EGENERIC; |
826 | 0 | const chap_entry_t *p = &p_sys->chapters.p_entry[i]; |
827 | 0 | if( p_sys->chapters.p_entry[i].i_offset == UINT32_MAX ) |
828 | 0 | return demux_Control( p_demux, DEMUX_SET_TIME, p->p_seekpoint->i_time_offset ); |
829 | 0 | int i_ret= MovetoTimePos( p_demux, p->p_seekpoint->i_time_offset, p->i_offset ); |
830 | 0 | if( i_ret == VLC_SUCCESS ) |
831 | 0 | p_sys->chapters.i_current = i; |
832 | 0 | return i_ret; |
833 | 0 | } |
834 | | |
835 | 0 | case DEMUX_TEST_AND_CLEAR_FLAGS: |
836 | 0 | { |
837 | 0 | unsigned *restrict flags = va_arg( args, unsigned * ); |
838 | 0 | *flags &= p_sys->i_demux_flags; |
839 | 0 | p_sys->i_demux_flags &= ~*flags; |
840 | 0 | return VLC_SUCCESS; |
841 | 0 | } |
842 | 0 | } |
843 | | |
844 | 0 | return demux_vaControlHelper( p_demux->s, p_sys->i_stream_offset, -1, |
845 | 0 | p_sys->i_bitrate, 1, i_query, args ); |
846 | 0 | } |
847 | | |
848 | | /***************************************************************************** |
849 | | * Makes a link list of buffer of parsed data |
850 | | * Returns true if EOF |
851 | | *****************************************************************************/ |
852 | | static bool Parse( demux_t *p_demux, block_t **pp_output ) |
853 | 143k | { |
854 | 143k | demux_sys_t *p_sys = p_demux->p_sys; |
855 | 143k | block_t *p_block_in, *p_block_out; |
856 | | |
857 | 143k | *pp_output = NULL; |
858 | | |
859 | 143k | if( p_sys->codec.b_use_word ) |
860 | 61.0k | { |
861 | | /* Make sure we are word aligned */ |
862 | 61.0k | int64_t i_pos = vlc_stream_Tell( p_demux->s ); |
863 | 61.0k | if( (i_pos & 1) && vlc_stream_Read( p_demux->s, NULL, 1 ) != 1 ) |
864 | 1.04k | return true; |
865 | 61.0k | } |
866 | | |
867 | 142k | p_block_in = vlc_stream_Block( p_demux->s, p_sys->i_packet_size ); |
868 | 142k | bool b_eof = p_block_in == NULL; |
869 | | |
870 | 142k | if( p_block_in ) |
871 | 128k | { |
872 | 128k | if( p_sys->codec.b_use_word && !p_sys->b_big_endian && p_block_in->i_buffer > 0 ) |
873 | 20.4k | { |
874 | | /* Convert to big endian */ |
875 | 20.4k | block_t *old = p_block_in; |
876 | 20.4k | p_block_in = block_Alloc( p_block_in->i_buffer ); |
877 | 20.4k | if( p_block_in ) |
878 | 20.4k | { |
879 | 20.4k | block_CopyProperties( p_block_in, old ); |
880 | 20.4k | swab( old->p_buffer, p_block_in->p_buffer, old->i_buffer ); |
881 | 20.4k | } |
882 | 20.4k | block_Release( old ); |
883 | 20.4k | } |
884 | | |
885 | 128k | if( p_block_in ) |
886 | 128k | { |
887 | 128k | p_block_in->i_pts = |
888 | 128k | p_block_in->i_dts = (p_sys->b_start || p_sys->b_initial_sync_failed) ? |
889 | 128k | VLC_TICK_0 : VLC_TICK_INVALID; |
890 | 128k | } |
891 | 128k | } |
892 | 142k | p_sys->b_initial_sync_failed = p_sys->b_start; /* Only try to resync once */ |
893 | | |
894 | 142k | decoder_t *p_packetizer = p_sys->p_packetizer; |
895 | 1.49M | while( ( p_block_out = p_packetizer->pf_packetize( p_packetizer, p_block_in ? &p_block_in : NULL ) ) ) |
896 | 1.35M | { |
897 | 1.35M | p_sys->b_initial_sync_failed = false; |
898 | 2.70M | while( p_block_out ) |
899 | 1.35M | { |
900 | 1.35M | if( !p_sys->p_es ) |
901 | 5.37k | { |
902 | 5.37k | es_format_t fmt; |
903 | 5.37k | es_format_Init( &fmt, p_packetizer->fmt_out.i_cat, p_packetizer->fmt_out.i_codec ); |
904 | 5.37k | es_format_Copy( &fmt, &p_packetizer->fmt_out ); |
905 | | |
906 | 5.37k | switch( p_sys->xing.audiomode ) |
907 | 5.37k | { |
908 | 2 | case XING_AUDIOMODE_AMBISONICS: |
909 | 2 | fmt.audio.channel_type = AUDIO_CHANNEL_TYPE_AMBISONICS; |
910 | 2 | break; |
911 | 5.36k | default: |
912 | 5.36k | break; |
913 | 5.37k | } |
914 | | |
915 | 5.37k | fmt.b_packetized = true; |
916 | 5.37k | fmt.i_id = 0; |
917 | 5.37k | p_sys->p_es = es_out_Add( p_demux->out, &fmt ); |
918 | | |
919 | | /* Use the bitrate as initual value */ |
920 | 5.37k | if( p_sys->b_estimate_bitrate ) |
921 | 5.23k | p_sys->i_bitrate = fmt.i_bitrate; |
922 | | |
923 | 5.37k | es_format_Clean( &fmt ); |
924 | 5.37k | } |
925 | | |
926 | 1.35M | block_t *p_next = p_block_out->p_next; |
927 | 1.35M | p_block_out->p_next = NULL; |
928 | | |
929 | 1.35M | block_ChainLastAppend( &pp_output, p_block_out ); |
930 | | |
931 | 1.35M | p_block_out = p_next; |
932 | 1.35M | } |
933 | 1.35M | } |
934 | | |
935 | 142k | if( p_sys->b_initial_sync_failed ) |
936 | 142k | msg_Dbg( p_demux, "did not sync on first block" ); |
937 | 142k | p_sys->b_start = false; |
938 | | |
939 | 142k | return b_eof; |
940 | 142k | } |
941 | | |
942 | | /* Check to apply to WAVE fmt header */ |
943 | | static int GenericFormatCheck( int i_format, const uint8_t *p_head ) |
944 | 11.2k | { |
945 | 11.2k | if ( i_format == WAVE_FORMAT_PCM ) |
946 | 8.44k | { |
947 | 8.44k | if( GetWLE( p_head /* nChannels */ ) != 2 ) |
948 | 3.34k | return VLC_EGENERIC; |
949 | 5.10k | if( GetDWLE( p_head + 2 /* nSamplesPerSec */ ) != 44100 ) |
950 | 690 | return VLC_EGENERIC; |
951 | 5.10k | } |
952 | 7.23k | return VLC_SUCCESS; |
953 | 11.2k | } |
954 | | |
955 | | /***************************************************************************** |
956 | | * Wav header skipper |
957 | | *****************************************************************************/ |
958 | | static int WavSkipHeader( demux_t *p_demux, uint64_t *pi_skip, |
959 | | const uint16_t rgi_twocc[], |
960 | | int (*pf_format_check)( int, const uint8_t * ) ) |
961 | 33.1k | { |
962 | 33.1k | const uint8_t *p_peek; |
963 | 33.1k | size_t i_peek = 0; |
964 | 33.1k | uint32_t i_len; |
965 | | |
966 | | /* */ |
967 | 33.1k | *pi_skip = 0; |
968 | | |
969 | | /* Check if we are dealing with a WAV file */ |
970 | 33.1k | if( vlc_stream_Peek( p_demux->s, &p_peek, 12+8 ) != 12 + 8 ) |
971 | 2.08k | return VLC_SUCCESS; |
972 | | |
973 | 31.0k | if( memcmp( p_peek, "RIFF", 4 ) || memcmp( &p_peek[8], "WAVE", 4 ) ) |
974 | 10.4k | return VLC_SUCCESS; |
975 | | |
976 | | /* Find the wave format header */ |
977 | 20.5k | i_peek = 12 + 8; |
978 | 404k | while( memcmp( p_peek + i_peek - 8, "fmt ", 4 ) ) |
979 | 385k | { |
980 | 385k | i_len = GetDWLE( p_peek + i_peek - 4 ); |
981 | 385k | if( i_len > WAV_PROBE_SIZE || i_peek + i_len > WAV_PROBE_SIZE ) |
982 | 334 | return VLC_EGENERIC; |
983 | | |
984 | 384k | i_peek += i_len + 8; |
985 | 384k | if( vlc_stream_Peek( p_demux->s, &p_peek, i_peek ) != (ssize_t) i_peek ) |
986 | 608 | return VLC_EGENERIC; |
987 | 384k | } |
988 | | |
989 | | /* Sanity check the wave format header */ |
990 | 19.6k | i_len = GetDWLE( p_peek + i_peek - 4 ); |
991 | 19.6k | if( i_len > WAV_PROBE_SIZE ) |
992 | 208 | return VLC_EGENERIC; |
993 | | |
994 | 19.4k | i_peek += i_len + 8; |
995 | 19.4k | if( vlc_stream_Peek( p_demux->s, &p_peek, i_peek ) != (ssize_t) i_peek ) |
996 | 340 | return VLC_EGENERIC; |
997 | 19.0k | const uint16_t i_twocc = GetWLE( p_peek + i_peek - i_len - 8 /* wFormatTag */ ); |
998 | 19.0k | int i_format_idx; |
999 | 31.7k | for( i_format_idx = 0; rgi_twocc[i_format_idx] != WAVE_FORMAT_UNKNOWN; i_format_idx++ ) |
1000 | 26.6k | { |
1001 | 26.6k | if( i_twocc == rgi_twocc[i_format_idx] ) |
1002 | 13.9k | break; |
1003 | 26.6k | } |
1004 | 19.0k | if( rgi_twocc[i_format_idx] == WAVE_FORMAT_UNKNOWN ) |
1005 | 5.12k | return VLC_EGENERIC; |
1006 | | |
1007 | 13.9k | if( pf_format_check && |
1008 | 13.9k | pf_format_check( i_twocc, p_peek + i_peek - i_len - 6 ) != VLC_SUCCESS ) |
1009 | 4.03k | return VLC_EGENERIC; |
1010 | | |
1011 | | /* Skip the wave header */ |
1012 | 150k | while( memcmp( p_peek + i_peek - 8, "data", 4 ) ) |
1013 | 141k | { |
1014 | 141k | i_len = GetDWLE( p_peek + i_peek - 4 ); |
1015 | 141k | if( i_len > WAV_PROBE_SIZE || i_peek + i_len > WAV_PROBE_SIZE ) |
1016 | 142 | return VLC_EGENERIC; |
1017 | | |
1018 | 140k | i_peek += i_len + 8; |
1019 | 140k | if( vlc_stream_Peek( p_demux->s, &p_peek, i_peek ) != (ssize_t) i_peek ) |
1020 | 137 | return VLC_EGENERIC; |
1021 | 140k | } |
1022 | 9.64k | *pi_skip = i_peek; |
1023 | 9.64k | return VLC_SUCCESS; |
1024 | 9.92k | } |
1025 | | |
1026 | | static int GenericProbe( demux_t *p_demux, uint64_t *pi_offset, |
1027 | | const char * ppsz_name[], |
1028 | | int (*pf_check)( const uint8_t *, unsigned * ), |
1029 | | unsigned i_check_size, |
1030 | | unsigned i_base_probing, |
1031 | | unsigned i_wav_extra_probing, |
1032 | | bool b_use_word, |
1033 | | const uint16_t pi_twocc[], |
1034 | | int (*pf_format_check)( int, const uint8_t * ) ) |
1035 | 22.7k | { |
1036 | 22.7k | bool b_forced_demux; |
1037 | | |
1038 | 22.7k | uint64_t i_offset; |
1039 | 22.7k | const uint8_t *p_peek; |
1040 | 22.7k | uint64_t i_skip; |
1041 | | |
1042 | 22.7k | b_forced_demux = false; |
1043 | 52.8k | for( size_t i = 0; ppsz_name[i] != NULL; i++ ) |
1044 | 30.0k | { |
1045 | 30.0k | b_forced_demux |= demux_IsForced( p_demux, ppsz_name[i] ); |
1046 | 30.0k | } |
1047 | | |
1048 | 22.7k | i_offset = vlc_stream_Tell( p_demux->s ); |
1049 | | |
1050 | 22.7k | if( WavSkipHeader( p_demux, &i_skip, pi_twocc, pf_format_check ) ) |
1051 | 6.38k | { |
1052 | 6.38k | if( !b_forced_demux ) |
1053 | 5.97k | return VLC_EGENERIC; |
1054 | 6.38k | } |
1055 | 16.8k | const bool b_wav = i_skip > 0; |
1056 | | |
1057 | | /* peek the beginning |
1058 | | * It is common that wav files have some sort of garbage at the beginning |
1059 | | * We will accept probing 0.5s of data in this case. |
1060 | | */ |
1061 | 16.8k | const size_t i_probe = i_skip + i_check_size + i_base_probing + ( b_wav ? i_wav_extra_probing : 0); |
1062 | 16.8k | const ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, i_probe ); |
1063 | | |
1064 | 16.8k | if( i_peek < 0 || (size_t)i_peek < i_skip + i_check_size ) |
1065 | 458 | return VLC_EGENERIC; |
1066 | | |
1067 | 16.3k | for( ;; ) |
1068 | 41.4M | { |
1069 | | /* i_peek > 0 so we can cast into size_t. */ |
1070 | 41.4M | if( i_skip + i_check_size > (size_t)i_peek ) |
1071 | 7.18k | { |
1072 | 7.18k | if( !b_forced_demux ) |
1073 | 6.35k | return VLC_EGENERIC; |
1074 | 824 | break; |
1075 | 7.18k | } |
1076 | 41.4M | unsigned i_samples = 0; |
1077 | 41.4M | int i_size = pf_check( &p_peek[i_skip], &i_samples ); |
1078 | 41.4M | if( i_size >= 0 ) |
1079 | 59.5k | { |
1080 | 59.5k | if( i_size == 0 || /* 0 sized frame ?? */ |
1081 | 59.5k | i_skip == 0 /* exact match from start, we're not WAVE either, so skip multiple checks (would break if padding) */ ) |
1082 | 3.05k | break; |
1083 | | |
1084 | | /* If we have the frame size, check the next frame for |
1085 | | * extra robustness |
1086 | | * The second test is because some .wav have paddings |
1087 | | */ |
1088 | 56.4k | bool b_ok = false; |
1089 | 157k | for( int t = 0; t < 1 + !!b_wav; t++ ) |
1090 | 105k | { |
1091 | 105k | if( t == 1 ) |
1092 | 49.4k | { |
1093 | 49.4k | if(!i_samples) |
1094 | 2.93k | break; |
1095 | 46.4k | i_size = i_samples * 2 * 2; |
1096 | 46.4k | } |
1097 | | |
1098 | 102k | if( i_skip + i_check_size + i_size <= (size_t)i_peek ) |
1099 | 76.9k | { |
1100 | 76.9k | b_ok = pf_check( &p_peek[i_skip+i_size], NULL ) >= 0; |
1101 | 76.9k | if( b_ok ) |
1102 | 2.31k | break; |
1103 | 76.9k | } |
1104 | 102k | } |
1105 | 56.4k | if( b_ok ) |
1106 | 2.31k | break; |
1107 | 56.4k | } |
1108 | 41.4M | if( b_use_word ) |
1109 | 20.1M | i_skip += ((i_offset + i_skip) % 2 == 0) ? 2 : 1; |
1110 | 21.2M | else |
1111 | 21.2M | i_skip++; |
1112 | 41.4M | if( !b_wav && !b_forced_demux ) |
1113 | 3.81k | return VLC_EGENERIC; |
1114 | 41.4M | } |
1115 | | |
1116 | 6.19k | *pi_offset = i_offset + i_skip; |
1117 | 6.19k | return VLC_SUCCESS; |
1118 | 16.3k | } |
1119 | | |
1120 | | /***************************************************************************** |
1121 | | * Mpeg I/II Audio |
1122 | | *****************************************************************************/ |
1123 | | static int MpgaCheckSync( const uint8_t *p_peek ) |
1124 | 167k | { |
1125 | 167k | uint32_t h = GetDWBE( p_peek ); |
1126 | | |
1127 | 167k | if( ((( h >> 21 )&0x07FF) != 0x07FF ) /* header sync */ |
1128 | 167k | || (((h >> 19)&0x03) == 1 ) /* valid version ID ? */ |
1129 | 167k | || (((h >> 17)&0x03) == 0 ) /* valid layer ?*/ |
1130 | 167k | || (((h >> 12)&0x0F) == 0x0F ) /* valid bitrate ?*/ |
1131 | 167k | || (((h >> 10) & 0x03) == 0x03 ) /* valid sampling freq ? */ |
1132 | 167k | || ((h & 0x03) == 0x02 )) /* valid emphasis ? */ |
1133 | 162k | { |
1134 | 162k | return false; |
1135 | 162k | } |
1136 | 5.60k | return true; |
1137 | 167k | } |
1138 | | |
1139 | 2.64k | #define MPGA_VERSION( h ) ( 1 - (((h)>>19)&0x01) ) |
1140 | 2.64k | #define MPGA_MODE(h) (((h)>> 6)&0x03) |
1141 | | |
1142 | | static int MpgaProbe( demux_t *p_demux, uint64_t *pi_offset ) |
1143 | 10.3k | { |
1144 | 10.3k | const uint16_t rgi_twocc[] = { WAVE_FORMAT_MPEG, WAVE_FORMAT_MPEGLAYER3, WAVE_FORMAT_UNKNOWN }; |
1145 | 10.3k | bool b_forced; |
1146 | 10.3k | bool b_forced_demux; |
1147 | 10.3k | uint64_t i_offset; |
1148 | | |
1149 | 10.3k | const uint8_t *p_peek; |
1150 | 10.3k | uint64_t i_skip; |
1151 | 10.3k | ssize_t i_peek; |
1152 | | |
1153 | 10.3k | b_forced = demux_IsPathExtension( p_demux, ".mp3" ); |
1154 | 10.3k | b_forced_demux = demux_IsForced( p_demux, "mp3" ) || |
1155 | 10.3k | demux_IsForced( p_demux, "mpga" ); |
1156 | | |
1157 | 10.3k | i_offset = vlc_stream_Tell( p_demux->s ); |
1158 | | |
1159 | 10.3k | if( WavSkipHeader( p_demux, &i_skip, rgi_twocc, NULL ) ) |
1160 | 4.54k | { |
1161 | 4.54k | if( !b_forced_demux ) |
1162 | 575 | return VLC_EGENERIC; |
1163 | | |
1164 | 3.96k | return VLC_EGENERIC; |
1165 | 4.54k | } |
1166 | | |
1167 | 5.81k | i_peek = vlc_stream_Peek( p_demux->s, &p_peek, i_skip + 4 ); |
1168 | 5.81k | if( i_peek <= 0 || (uint64_t) i_peek < i_skip + 4 ) |
1169 | 11 | return VLC_EGENERIC; |
1170 | | |
1171 | 5.80k | if( !MpgaCheckSync( &p_peek[i_skip] ) ) |
1172 | 3.14k | { |
1173 | 3.14k | bool b_ok = false; |
1174 | | |
1175 | 3.14k | if( !b_forced_demux && !b_forced ) |
1176 | 2.66k | return VLC_EGENERIC; |
1177 | | |
1178 | 483 | i_peek = vlc_stream_Peek( p_demux->s, &p_peek, i_skip + 8096 ); |
1179 | 159k | while( i_peek > 0 && i_skip + 4 < (uint64_t) i_peek ) |
1180 | 159k | { |
1181 | 159k | if( MpgaCheckSync( &p_peek[i_skip] ) ) |
1182 | 298 | { |
1183 | 298 | b_ok = true; |
1184 | 298 | break; |
1185 | 298 | } |
1186 | 159k | i_skip++; |
1187 | 159k | } |
1188 | 483 | if( !b_ok && !b_forced_demux ) |
1189 | 0 | return VLC_EGENERIC; |
1190 | 483 | } |
1191 | 3.14k | *pi_offset = i_offset + i_skip; |
1192 | 3.14k | return VLC_SUCCESS; |
1193 | 5.80k | } |
1194 | | |
1195 | | static int SeekByMlltTable( sync_table_t *mllt, vlc_tick_t *pi_time, uint64_t *pi_offset ) |
1196 | 0 | { |
1197 | 0 | if( !mllt->p_bits ) |
1198 | 0 | return -1; |
1199 | | |
1200 | 0 | sync_table_ctx_t *p_cur = &mllt->current; |
1201 | | |
1202 | | /* reset or init context */ |
1203 | 0 | if( *pi_time < p_cur->i_time || !p_cur->br.p ) |
1204 | 0 | { |
1205 | 0 | p_cur->i_time = 0; |
1206 | 0 | p_cur->i_pos = 0; |
1207 | 0 | bs_init(&p_cur->br, mllt->p_bits, mllt->i_bits); |
1208 | 0 | } |
1209 | |
|
1210 | 0 | while(!bs_eof(&p_cur->br)) |
1211 | 0 | { |
1212 | 0 | const uint32_t i_bytesdev = bs_read(&p_cur->br, mllt->i_bits_per_bytes_dev); |
1213 | 0 | const uint32_t i_msdev = bs_read(&p_cur->br, mllt->i_bits_per_ms_dev); |
1214 | 0 | if(bs_error(&p_cur->br)) |
1215 | 0 | break; |
1216 | 0 | const vlc_tick_t i_deltatime = VLC_TICK_FROM_MS(mllt->i_ms_btw_refs + i_msdev); |
1217 | 0 | if( p_cur->i_time + i_deltatime > *pi_time ) |
1218 | 0 | break; |
1219 | 0 | p_cur->i_time += i_deltatime; |
1220 | 0 | p_cur->i_pos += mllt->i_bytes_btw_refs + i_bytesdev; |
1221 | 0 | } |
1222 | 0 | *pi_time = p_cur->i_time; |
1223 | 0 | *pi_offset = p_cur->i_pos; |
1224 | |
|
1225 | 0 | return 0; |
1226 | 0 | } |
1227 | | |
1228 | | static int ID3TAG_Parse_Handler( uint32_t i_tag, const uint8_t *p_payload, size_t i_payload, void *p_priv ) |
1229 | 0 | { |
1230 | 0 | demux_t *p_demux = (demux_t *) p_priv; |
1231 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
1232 | |
|
1233 | 0 | if( i_tag == VLC_FOURCC('M', 'L', 'L', 'T') ) |
1234 | 0 | { |
1235 | 0 | if( i_payload > 20 ) |
1236 | 0 | { |
1237 | 0 | p_sys->mllt.i_frames_btw_refs = GetWBE(p_payload); |
1238 | 0 | p_sys->mllt.i_bytes_btw_refs = GetDWBE(&p_payload[1]) & 0x00FFFFFF; |
1239 | 0 | p_sys->mllt.i_ms_btw_refs = GetDWBE(&p_payload[4]) & 0x00FFFFFF; |
1240 | 0 | if( !p_sys->mllt.i_frames_btw_refs || !p_sys->mllt.i_bytes_btw_refs || |
1241 | 0 | !p_sys->mllt.i_ms_btw_refs || |
1242 | 0 | p_payload[8] > 31 || p_payload[9] > 31 || /* bits length sanity check */ |
1243 | 0 | ((p_payload[8] + p_payload[9]) % 4) || p_payload[8] + p_payload[9] < 4 ) |
1244 | 0 | return VLC_EGENERIC; |
1245 | 0 | p_sys->mllt.i_bits_per_bytes_dev = p_payload[8]; |
1246 | 0 | p_sys->mllt.i_bits_per_ms_dev = p_payload[9]; |
1247 | 0 | p_sys->mllt.p_bits = malloc(i_payload - 10); |
1248 | 0 | if( likely(p_sys->mllt.p_bits) ) |
1249 | 0 | { |
1250 | 0 | p_sys->mllt.i_bits = i_payload - 10; |
1251 | 0 | memcpy(p_sys->mllt.p_bits, &p_payload[10], p_sys->mllt.i_bits); |
1252 | 0 | msg_Dbg(p_demux, "read MLLT sync table with %zu entries", |
1253 | 0 | (p_sys->mllt.i_bits * 8) / (p_sys->mllt.i_bits_per_bytes_dev + p_sys->mllt.i_bits_per_ms_dev) ); |
1254 | 0 | } |
1255 | 0 | } |
1256 | 0 | return VLC_EGENERIC; |
1257 | 0 | } |
1258 | 0 | else if( i_tag == VLC_FOURCC('T', 'X', 'X', 'X') ) |
1259 | 0 | { |
1260 | 0 | vlc_meta_t *p_meta = vlc_meta_New(); |
1261 | 0 | if( p_meta ) |
1262 | 0 | { |
1263 | 0 | bool b_updated; |
1264 | 0 | if( ID3HandleTag( p_payload, i_payload, i_tag, p_meta, &b_updated ) ) |
1265 | 0 | { |
1266 | 0 | vlc_replay_gain_CopyFromMeta( &p_sys->audio_replay_gain, p_meta ); |
1267 | 0 | } |
1268 | 0 | vlc_meta_Delete( p_meta ); |
1269 | 0 | } |
1270 | 0 | } |
1271 | 0 | else if ( i_tag == VLC_FOURCC('C', 'H', 'A', 'P') && i_payload >= 17 ) |
1272 | 0 | { |
1273 | 0 | char *psz_title = strndup( (const char *)p_payload, i_payload - 16 ); |
1274 | 0 | size_t i_offset = psz_title ? strlen( psz_title ) : 0; |
1275 | 0 | if( p_payload[i_offset] != 0 ) |
1276 | 0 | { |
1277 | 0 | free( psz_title ); |
1278 | 0 | return VLC_EGENERIC; |
1279 | 0 | } |
1280 | 0 | chap_entry_t e; |
1281 | 0 | e.p_seekpoint = vlc_seekpoint_New(); |
1282 | 0 | if( e.p_seekpoint ) |
1283 | 0 | { |
1284 | 0 | e.p_seekpoint->psz_name = psz_title; |
1285 | 0 | e.p_seekpoint->i_time_offset = VLC_TICK_FROM_MS(GetDWBE(&p_payload[1 + i_offset])); |
1286 | 0 | e.i_offset = GetDWBE(&p_payload[1 + i_offset + 8]); |
1287 | 0 | p_payload += i_offset + 1 + 16; |
1288 | 0 | i_payload -= i_offset + 1 + 16; |
1289 | 0 | if( 12 < i_payload && !memcmp("TIT2", p_payload, 4) ) |
1290 | 0 | { |
1291 | 0 | psz_title = NULL; /* optional alloc */ |
1292 | 0 | const char *psz = ID3TextConvert(&p_payload[10], i_payload-12, &psz_title); |
1293 | 0 | if( psz ) /* replace with TIT2 */ |
1294 | 0 | { |
1295 | 0 | free( e.p_seekpoint->psz_name ); |
1296 | 0 | e.p_seekpoint->psz_name = (psz_title) ? psz_title : strdup( psz ); |
1297 | 0 | } |
1298 | 0 | } |
1299 | 0 | TAB_APPEND(p_sys->chapters.i_count, p_sys->chapters.p_entry, e); |
1300 | 0 | } else free( psz_title ); |
1301 | 0 | } |
1302 | | |
1303 | 0 | return VLC_SUCCESS; |
1304 | 0 | } |
1305 | | |
1306 | | static int ID3Parse( demux_t *p_demux, |
1307 | | int (*pf_callback)(uint32_t, const uint8_t *, size_t, void *) ) |
1308 | 3.14k | { |
1309 | 3.14k | const block_t *p_tags = NULL; |
1310 | | |
1311 | 3.14k | if( vlc_stream_Control( p_demux->s, STREAM_GET_TAGS, &p_tags ) != VLC_SUCCESS ) |
1312 | 3.14k | return VLC_EGENERIC; |
1313 | | |
1314 | 0 | for( ; p_tags; p_tags = p_tags->p_next ) |
1315 | 0 | ID3TAG_Parse( p_tags->p_buffer, p_tags->i_buffer, pf_callback, (void *) p_demux ); |
1316 | |
|
1317 | 0 | return VLC_SUCCESS; |
1318 | 3.14k | } |
1319 | | |
1320 | | static int MpgaInit( demux_t *p_demux ) |
1321 | 3.14k | { |
1322 | 3.14k | demux_sys_t *p_sys = p_demux->p_sys; |
1323 | | |
1324 | 3.14k | const uint8_t *p_peek; |
1325 | 3.14k | int i_peek; |
1326 | | |
1327 | | /* */ |
1328 | 3.14k | p_sys->i_packet_size = 1024; |
1329 | | |
1330 | 3.14k | ID3Parse( p_demux, ID3TAG_Parse_Handler ); |
1331 | | |
1332 | | /* Load a potential xing header */ |
1333 | 3.14k | i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 4 + 1024 ); |
1334 | 3.14k | if( i_peek < 4 + 21 ) |
1335 | 484 | return VLC_SUCCESS; |
1336 | | |
1337 | 2.65k | const uint32_t header = GetDWBE( p_peek ); |
1338 | 2.65k | if( !MpgaCheckSync( p_peek ) || mpga_decode_frameheader( header, &p_sys->mpgah ) ) |
1339 | 10 | return VLC_SUCCESS; |
1340 | | |
1341 | 2.64k | if( p_sys->mpgah.i_layer == 3 ) |
1342 | 1.33k | p_sys->codec.i_codec = VLC_CODEC_MP3; |
1343 | | |
1344 | | /* Xing header */ |
1345 | 2.64k | int i_skip; |
1346 | | |
1347 | 2.64k | if( MPGA_VERSION( header ) == 0 ) |
1348 | 1.07k | i_skip = MPGA_MODE( header ) != 3 ? 36 : 21; |
1349 | 1.57k | else |
1350 | 1.57k | i_skip = MPGA_MODE( header ) != 3 ? 21 : 13; |
1351 | | |
1352 | 2.64k | if( i_skip >= i_peek ) |
1353 | 24 | return VLC_SUCCESS; |
1354 | | |
1355 | 2.62k | struct xing_info_s *xing = &p_sys->xing; |
1356 | 2.62k | if( ParseXing( &p_peek[i_skip], i_peek - i_skip, xing ) == VLC_SUCCESS ) |
1357 | 658 | { |
1358 | 658 | const uint64_t i_total_samples = xing->i_frames * (uint64_t) p_sys->mpgah.i_samples_per_frame; |
1359 | 658 | const uint64_t i_dropped_samples = xing->i_delay_samples + xing->i_padding_samples; |
1360 | | |
1361 | 658 | if( p_sys->mpgah.i_sample_rate && i_dropped_samples < i_total_samples ) |
1362 | 411 | { |
1363 | 411 | uint64_t i_stream_size; |
1364 | | /* We only set duration if we can't check (then compute it using bitrate/size) |
1365 | | or if we verified the file isn't truncated */ |
1366 | 411 | if( xing->i_bytes == 0 || |
1367 | 411 | vlc_stream_GetSize( p_demux->s, &i_stream_size ) || |
1368 | 411 | (i_stream_size >= xing->i_bytes && |
1369 | 382 | i_stream_size <= xing->i_bytes + p_sys->mpgah.i_frame_size) ) |
1370 | 45 | { |
1371 | 45 | p_sys->i_duration = vlc_tick_from_samples( i_total_samples - i_dropped_samples, |
1372 | 45 | p_sys->mpgah.i_sample_rate ); |
1373 | 45 | } |
1374 | 411 | } |
1375 | | |
1376 | 658 | unsigned i_bitrate = 0; |
1377 | 658 | if( xing->brmode == XING_MODE_ABR || xing->brmode == XING_MODE_ABR_2PASS ) |
1378 | 28 | i_bitrate = xing->bitrate_avg * 1000; |
1379 | | |
1380 | 658 | if( !i_bitrate && p_sys->mpgah.i_sample_rate && |
1381 | 658 | xing->i_bytes > p_sys->mpgah.i_frame_size ) |
1382 | 361 | { |
1383 | 361 | unsigned d = vlc_tick_from_samples( i_total_samples, p_sys->mpgah.i_sample_rate ); |
1384 | 361 | if( d ) |
1385 | 346 | i_bitrate = (xing->i_bytes - p_sys->mpgah.i_frame_size) * 8 * CLOCK_FREQ / d; |
1386 | 361 | } |
1387 | | |
1388 | 658 | if( i_bitrate ) |
1389 | 301 | { |
1390 | 301 | p_sys->i_bitrate = i_bitrate; |
1391 | 301 | p_sys->b_estimate_bitrate = false; |
1392 | 301 | } |
1393 | | |
1394 | 658 | if( isfinite(xing->f_radio_replay_gain) ) |
1395 | 71 | { |
1396 | 71 | p_sys->audio_replay_gain.pb_gain[AUDIO_REPLAY_GAIN_TRACK] = true; |
1397 | 71 | p_sys->audio_replay_gain.pf_gain[AUDIO_REPLAY_GAIN_TRACK] = xing->f_radio_replay_gain; |
1398 | 71 | } |
1399 | | |
1400 | 658 | if( isfinite(xing->f_peak_signal) ) |
1401 | 71 | { |
1402 | 71 | p_sys->audio_replay_gain.pb_peak[AUDIO_REPLAY_GAIN_TRACK] = true; |
1403 | 71 | p_sys->audio_replay_gain.pf_peak[AUDIO_REPLAY_GAIN_TRACK] = xing->f_peak_signal; |
1404 | 71 | } |
1405 | | |
1406 | 658 | if( isfinite(xing->f_audiophile_replay_gain) ) |
1407 | 0 | { |
1408 | 0 | p_sys->audio_replay_gain.pb_gain[AUDIO_REPLAY_GAIN_ALBUM] = true; |
1409 | 0 | p_sys->audio_replay_gain.pf_gain[AUDIO_REPLAY_GAIN_ALBUM] = xing->f_audiophile_replay_gain; |
1410 | 0 | } |
1411 | | |
1412 | 658 | msg_Dbg( p_demux, "Using '%4.4s' infotag" |
1413 | 658 | "(%"PRIu32" bytes, %"PRIu32" frames, %u samples/frame)", |
1414 | 658 | (char *) &xing->infotag, |
1415 | 658 | xing->i_bytes, xing->i_frames, |
1416 | 658 | p_sys->mpgah.i_samples_per_frame ); |
1417 | | |
1418 | | /* We'll need to skip that part for playback |
1419 | | * and avoid using it as container frame could be different rate/size */ |
1420 | 658 | p_sys->i_stream_offset += p_sys->mpgah.i_frame_size; |
1421 | 658 | } |
1422 | | |
1423 | 2.62k | return VLC_SUCCESS; |
1424 | 2.64k | } |
1425 | | |
1426 | | /***************************************************************************** |
1427 | | * AAC |
1428 | | *****************************************************************************/ |
1429 | | static int AacProbe( demux_t *p_demux, uint64_t *pi_offset ) |
1430 | 10.3k | { |
1431 | 10.3k | bool b_forced; |
1432 | 10.3k | bool b_forced_demux; |
1433 | | |
1434 | 10.3k | uint64_t i_offset; |
1435 | 10.3k | const uint8_t *p_peek; |
1436 | | |
1437 | 10.3k | b_forced = demux_IsPathExtension( p_demux, ".aac" ) || |
1438 | 10.3k | demux_IsPathExtension( p_demux, ".aacp" ); |
1439 | 10.3k | b_forced_demux = demux_IsForced( p_demux, "m4a" ) || |
1440 | 10.3k | demux_IsForced( p_demux, "aac" ) || |
1441 | 10.3k | demux_IsForced( p_demux, "mp4a" ); |
1442 | | |
1443 | 10.3k | if( !b_forced_demux && !b_forced ) |
1444 | 10.3k | return VLC_EGENERIC; |
1445 | | |
1446 | 0 | i_offset = vlc_stream_Tell( p_demux->s ); |
1447 | | |
1448 | | /* peek the beginning (10 is for adts header) */ |
1449 | 0 | if( vlc_stream_Peek( p_demux->s, &p_peek, 10 ) < 10 ) |
1450 | 0 | return VLC_EGENERIC; |
1451 | | |
1452 | 0 | if( !strncmp( (char *)p_peek, "ADIF", 4 ) ) |
1453 | 0 | { |
1454 | 0 | msg_Err( p_demux, "ADIF file. Not yet supported. (Please report)" ); |
1455 | 0 | return VLC_EGENERIC; |
1456 | 0 | } |
1457 | | |
1458 | 0 | *pi_offset = i_offset; |
1459 | 0 | return VLC_SUCCESS; |
1460 | 0 | } |
1461 | | static int AacInit( demux_t *p_demux ) |
1462 | 0 | { |
1463 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
1464 | |
|
1465 | 0 | p_sys->i_packet_size = 4096; |
1466 | 0 | p_sys->i_original = VLC_FOURCC('H','E','A','D'); |
1467 | |
|
1468 | 0 | return VLC_SUCCESS; |
1469 | 0 | } |
1470 | | |
1471 | | |
1472 | | /***************************************************************************** |
1473 | | * A52 |
1474 | | *****************************************************************************/ |
1475 | | static int A52CheckSync( const uint8_t *p_peek, bool *p_big_endian, unsigned *pi_samples, bool b_eac3 ) |
1476 | 20.2M | { |
1477 | 20.2M | vlc_a52_header_t header; |
1478 | 20.2M | uint8_t p_tmp[VLC_A52_MIN_HEADER_SIZE]; |
1479 | | |
1480 | 20.2M | *p_big_endian = p_peek[0] == 0x0b && p_peek[1] == 0x77; |
1481 | 20.2M | if( !*p_big_endian ) |
1482 | 20.0M | { |
1483 | 20.0M | swab( p_peek, p_tmp, VLC_A52_MIN_HEADER_SIZE ); |
1484 | 20.0M | p_peek = p_tmp; |
1485 | 20.0M | } |
1486 | | |
1487 | 20.2M | if( vlc_a52_header_Parse( &header, p_peek, VLC_A52_MIN_HEADER_SIZE ) ) |
1488 | 19.7M | return VLC_EGENERIC; |
1489 | | |
1490 | 450k | if( !header.b_eac3 != !b_eac3 ) |
1491 | 402k | return VLC_EGENERIC; |
1492 | 47.9k | if( pi_samples ) |
1493 | 44.9k | *pi_samples = header.i_samples; |
1494 | 47.9k | return header.i_size; |
1495 | 450k | } |
1496 | | static int EA52CheckSyncProbe( const uint8_t *p_peek, unsigned *pi_samples ) |
1497 | 7.41M | { |
1498 | 7.41M | bool b_dummy; |
1499 | 7.41M | return A52CheckSync( p_peek, &b_dummy, pi_samples, true ); |
1500 | 7.41M | } |
1501 | | |
1502 | | static int EA52Probe( demux_t *p_demux, uint64_t *pi_offset ) |
1503 | 6.75k | { |
1504 | 6.75k | const char *ppsz_name[] = { "eac3", NULL }; |
1505 | 6.75k | const uint16_t rgi_twocc[] = { WAVE_FORMAT_PCM, WAVE_FORMAT_A52, WAVE_FORMAT_UNKNOWN }; |
1506 | | |
1507 | 6.75k | return GenericProbe( p_demux, pi_offset, ppsz_name, EA52CheckSyncProbe, |
1508 | 6.75k | VLC_A52_MIN_HEADER_SIZE, |
1509 | 6.75k | 1920 + VLC_A52_MIN_HEADER_SIZE + 1, |
1510 | 6.75k | WAV_EXTRA_PROBE_SIZE, |
1511 | 6.75k | true, rgi_twocc, GenericFormatCheck ); |
1512 | 6.75k | } |
1513 | | |
1514 | | static int A52CheckSyncProbe( const uint8_t *p_peek, unsigned *pi_samples ) |
1515 | 12.8M | { |
1516 | 12.8M | bool b_dummy; |
1517 | 12.8M | return A52CheckSync( p_peek, &b_dummy, pi_samples, false ); |
1518 | 12.8M | } |
1519 | | |
1520 | | static int A52Probe( demux_t *p_demux, uint64_t *pi_offset ) |
1521 | 7.21k | { |
1522 | 7.21k | const char *ppsz_name[] = { "a52", "ac3", NULL }; |
1523 | 7.21k | const uint16_t rgi_twocc[] = { WAVE_FORMAT_PCM, WAVE_FORMAT_A52, WAVE_FORMAT_UNKNOWN }; |
1524 | | |
1525 | 7.21k | return GenericProbe( p_demux, pi_offset, ppsz_name, A52CheckSyncProbe, |
1526 | 7.21k | VLC_A52_MIN_HEADER_SIZE, |
1527 | 7.21k | 1920 + VLC_A52_MIN_HEADER_SIZE + 1, |
1528 | 7.21k | WAV_EXTRA_PROBE_SIZE, |
1529 | 7.21k | true, rgi_twocc, GenericFormatCheck ); |
1530 | 7.21k | } |
1531 | | |
1532 | | static int A52Init( demux_t *p_demux ) |
1533 | 2.30k | { |
1534 | 2.30k | demux_sys_t *p_sys = p_demux->p_sys; |
1535 | | |
1536 | 2.30k | p_sys->b_big_endian = false; |
1537 | 2.30k | p_sys->i_packet_size = 1024; |
1538 | | |
1539 | 2.30k | const uint8_t *p_peek; |
1540 | | |
1541 | | /* peek the beginning */ |
1542 | 2.30k | if( vlc_stream_Peek( p_demux->s, &p_peek, VLC_A52_MIN_HEADER_SIZE ) >= VLC_A52_MIN_HEADER_SIZE ) |
1543 | 2.30k | { |
1544 | 2.30k | A52CheckSync( p_peek, &p_sys->b_big_endian, NULL, true ); |
1545 | 2.30k | } |
1546 | 2.30k | return VLC_SUCCESS; |
1547 | 2.30k | } |
1548 | | |
1549 | | /***************************************************************************** |
1550 | | * DTS |
1551 | | *****************************************************************************/ |
1552 | | static int DtsCheckSync( const uint8_t *p_peek, unsigned *pi_samples ) |
1553 | 12.9M | { |
1554 | 12.9M | VLC_UNUSED(pi_samples); |
1555 | | |
1556 | 12.9M | vlc_dts_header_t dts; |
1557 | 12.9M | if( vlc_dts_header_Parse( &dts, p_peek, VLC_DTS_HEADER_SIZE ) == VLC_SUCCESS |
1558 | 12.9M | && dts.i_frame_size > 0 && dts.i_frame_size <= 8192 ) |
1559 | 14.7k | { |
1560 | 14.7k | if( pi_samples ) |
1561 | 13.6k | *pi_samples = dts.i_frame_length; |
1562 | 14.7k | return dts.i_frame_size; |
1563 | 14.7k | } |
1564 | 12.8M | else |
1565 | 12.8M | return VLC_EGENERIC; |
1566 | 12.9M | } |
1567 | | |
1568 | | static int DtsProbe( demux_t *p_demux, uint64_t *pi_offset ) |
1569 | 4.91k | { |
1570 | 4.91k | const char *ppsz_name[] = { "dts", NULL }; |
1571 | 4.91k | const uint16_t rgi_twocc[] = { WAVE_FORMAT_PCM, WAVE_FORMAT_DTSINC_DTS, WAVE_FORMAT_UNKNOWN }; |
1572 | | |
1573 | 4.91k | return GenericProbe( p_demux, pi_offset, ppsz_name, DtsCheckSync, |
1574 | 4.91k | VLC_DTS_HEADER_SIZE, |
1575 | 4.91k | 16384 + VLC_DTS_HEADER_SIZE + 1, |
1576 | 4.91k | WAV_EXTRA_PROBE_SIZE, |
1577 | 4.91k | false, rgi_twocc, NULL ); |
1578 | 4.91k | } |
1579 | | static int DtsInit( demux_t *p_demux ) |
1580 | 2.92k | { |
1581 | 2.92k | demux_sys_t *p_sys = p_demux->p_sys; |
1582 | | |
1583 | 2.92k | p_sys->i_packet_size = 16384; |
1584 | | |
1585 | 2.92k | return VLC_SUCCESS; |
1586 | 2.92k | } |
1587 | | |
1588 | | /***************************************************************************** |
1589 | | * MLP |
1590 | | *****************************************************************************/ |
1591 | | static int MlpCheckSync( const uint8_t *p_peek, unsigned *pi_samples ) |
1592 | 8.33M | { |
1593 | 8.33M | if( p_peek[4+0] != 0xf8 || p_peek[4+1] != 0x72 || p_peek[4+2] != 0x6f ) |
1594 | 8.17M | return -1; |
1595 | | |
1596 | 164k | if( p_peek[4+3] != 0xbb ) |
1597 | 163k | return -1; |
1598 | | |
1599 | | /* TODO checksum and real size for robustness */ |
1600 | 69 | VLC_UNUSED(pi_samples); |
1601 | 69 | return 0; |
1602 | 164k | } |
1603 | | static int ThdCheckSync( const uint8_t *p_peek, unsigned *pi_samples ) |
1604 | 65.2k | { |
1605 | 65.2k | if( p_peek[4+0] != 0xf8 || p_peek[4+1] != 0x72 || p_peek[4+2] != 0x6f ) |
1606 | 64.0k | return -1; |
1607 | | |
1608 | 1.12k | if( p_peek[4+3] != 0xba ) |
1609 | 226 | return -1; |
1610 | | |
1611 | | /* TODO checksum and real size for robustness */ |
1612 | 896 | VLC_UNUSED(pi_samples); |
1613 | 896 | return 0; |
1614 | 1.12k | } |
1615 | | static int MlpProbe( demux_t *p_demux, uint64_t *pi_offset ) |
1616 | 1.99k | { |
1617 | 1.99k | const char *ppsz_name[] = { "mlp", NULL }; |
1618 | 1.99k | const uint16_t rgi_twocc[] = { WAVE_FORMAT_PCM, WAVE_FORMAT_UNKNOWN }; |
1619 | | |
1620 | 1.99k | return GenericProbe( p_demux, pi_offset, ppsz_name, MlpCheckSync, |
1621 | 1.99k | 4+28+16*4, BASE_PROBE_SIZE, WAV_EXTRA_PROBE_SIZE, |
1622 | 1.99k | false, rgi_twocc, GenericFormatCheck ); |
1623 | 1.99k | } |
1624 | | static int ThdProbe( demux_t *p_demux, uint64_t *pi_offset ) |
1625 | 1.92k | { |
1626 | 1.92k | const char *ppsz_name[] = { "thd", NULL }; |
1627 | 1.92k | const uint16_t rgi_twocc[] = { WAVE_FORMAT_PCM, WAVE_FORMAT_UNKNOWN }; |
1628 | | |
1629 | 1.92k | return GenericProbe( p_demux, pi_offset, ppsz_name, ThdCheckSync, |
1630 | 1.92k | 4+28+16*4, BASE_PROBE_SIZE, WAV_EXTRA_PROBE_SIZE, |
1631 | 1.92k | false, rgi_twocc, GenericFormatCheck ); |
1632 | 1.92k | } |
1633 | | static int MlpInit( demux_t *p_demux ) |
1634 | | |
1635 | 965 | { |
1636 | 965 | demux_sys_t *p_sys = p_demux->p_sys; |
1637 | | |
1638 | 965 | p_sys->i_packet_size = 4096; |
1639 | | |
1640 | 965 | return VLC_SUCCESS; |
1641 | 965 | } |
1642 | | |
1643 | | /***************************************************************************** |
1644 | | * Video |
1645 | | *****************************************************************************/ |
1646 | | static int VideoInit( demux_t *p_demux ) |
1647 | 0 | { |
1648 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
1649 | |
|
1650 | 0 | p_sys->i_packet_size = 4096; |
1651 | |
|
1652 | 0 | return VLC_SUCCESS; |
1653 | 0 | } |