1 /*
2 * Copyright (C) 2000-2020 the xine project
3 *
4 * This file is part of xine, a free video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 */
20
21 /**
22 * @file
23 * @brief Declaration of internal, private functions for xine-lib.
24 *
25 * @internal These functions should not be used by neither plugins nor
26 * frontends.
27 */
28
29 #ifndef XINE_PRIVATE_H__
30 #define XINE_PRIVATE_H__
31
32 #ifndef XINE_LIBRARY_COMPILE
33 # error xine_private.h is for libxine private use only!
34 #endif
35 #if defined(HAVE_CONFIG_H) && !defined(__XINE_LIB_CONFIG_H__)
36 # error config.h not included
37 #endif
38
39 #include <xine/xine_internal.h>
40
41 #if SUPPORT_ATTRIBUTE_VISIBILITY_INTERNAL
42 # define INTERNAL __attribute__((visibility("internal")))
43 #elif SUPPORT_ATTRIBUTE_VISIBILITY_DEFAULT
44 # define INTERNAL __attribute__((__visibility__("default")))
45 #else
46 # define INTERNAL
47 #endif
48
49 #if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 ))
50 # define XINE_DISABLE_DEPRECATION_WARNINGS _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
51 # define XINE_ENABLE_DEPRECATION_WARNINGS _Pragma("GCC diagnostic warning \"-Wdeprecated-declarations\"")
52 #else
53 # define XINE_DISABLE_DEPRECATION_WARNINGS
54 # define XINE_ENABLE_DEPRECATION_WARNINGS
55 #endif
56
57 #ifdef __cplusplus
58 # define EXTERN_C_START extern "C" {
59 # define EXTERN_C_STOP }
60 #else
61 # define EXTERN_C_START
62 # define EXTERN_C_STOP
63 #endif
64
65 EXTERN_C_START
66
67 /* HAVE_ATOMIC_VARS: 0 = none, 1 = stdatomic.h, 2 = __atomic_*, 3 = __sync_* */
68 #if (HAVE_ATOMIC_VARS > 0)
69 # if (HAVE_ATOMIC_VARS == 1)
70 # include <stdatomic.h>
71 # define XINE_ATINT_T atomic_int
72 # define XINE_ATINIT(xatfa_refs,xatfa_n) atomic_init (&(xatfa_refs), (xatfa_n))
73 # define XINE_ATFA(xatfa_refs,xatfa_n) atomic_fetch_add_explicit (&(xatfa_refs), (xatfa_n), memory_order_acq_rel)
74 # define XINE_ATGET(xatfa_refs) atomic_load_explicit (&(xatfa_refs), memory_order_acquire)
75 # elif (HAVE_ATOMIC_VARS == 2)
76 # define XINE_ATINT_T int
77 # define XINE_ATINIT(xatfa_refs,xatfa_n) __atomic_store_n (&(xatfa_refs), (xatfa_n), __ATOMIC_RELAXED)
78 # define XINE_ATFA(xatfa_refs,xatfa_n) __atomic_fetch_add (&(xatfa_refs), (xatfa_n), __ATOMIC_ACQ_REL)
79 # define XINE_ATGET(xatfa_refs) __atomic_load_n (&(xatfa_refs), __ATOMIC_ACQUIRE)
80 # else /* HAVE_ATOMIC_VARS == 3 */
81 # define XINE_ATINT_T volatile int
82 # define XINE_ATINIT(xatfa_refs,xatfa_n) xatfa_refs = xatfa_n
83 # define XINE_ATFA(xatfa_refs,xatfa_n) __sync_fetch_and_add (&(xatfa_refs), (xatfa_n))
84 # if defined (ARCH_X86)
85 # define XINE_ATGET(xatfa_refs) (xatfa_refs)
86 # else
87 # define XINE_ATGET(xatfa_refs) __sync_fetch_and_add (&(xatfa_refs), 0)
88 # endif
89 # endif
90
91 typedef struct {
92 XINE_ATINT_T refs;
93 void (*destructor) (void *object);
94 void *object;
95 } xine_refs_t;
96
xine_refs_init(xine_refs_t * refs,void (* destructor)(void * object),void * object)97 static inline void xine_refs_init (xine_refs_t *refs,
98 void (*destructor) (void *object), void *object) {
99 refs->destructor = destructor;
100 refs->object = object;
101 XINE_ATINIT (refs->refs, 1);
102 }
103
xine_refs_add(xine_refs_t * refs,int n)104 static inline int xine_refs_add (xine_refs_t *refs, int n) {
105 return XINE_ATFA (refs->refs, n) + n;
106 }
107
xine_refs_sub(xine_refs_t * refs,int n)108 static inline int xine_refs_sub (xine_refs_t *refs, int n) {
109 int v = XINE_ATFA (refs->refs, -n) - n;
110 if (v == 0)
111 refs->destructor (refs->object);
112 return v;
113 }
114
xine_refs_get(xine_refs_t * refs)115 static inline int xine_refs_get (xine_refs_t *refs) {
116 return XINE_ATGET (refs->refs);
117 }
118
119 #else
120
121 typedef struct {
122 pthread_mutex_t mutex;
123 int refs;
124 void (*destructor) (void *object);
125 void *object;
126 } xine_refs_t;
127
128 static inline void xine_refs_init (xine_refs_t *refs,
129 void (*destructor) (void *object), void *object) {
130 refs->destructor = destructor;
131 refs->object = object;
132 refs->refs = 1;
133 pthread_mutex_init (&refs->mutex, NULL);
134 }
135
136 static inline int xine_refs_add (xine_refs_t *refs, int n) {
137 int v;
138 pthread_mutex_lock (&refs->mutex);
139 refs->refs += n;
140 v = refs->refs;
141 pthread_mutex_unlock (&refs->mutex);
142 return v;
143 }
144
145 static inline int xine_refs_sub (xine_refs_t *refs, int n) {
146 int v;
147 pthread_mutex_lock (&refs->mutex);
148 refs->refs -= n;
149 v = refs->refs;
150 pthread_mutex_unlock (&refs->mutex);
151 if (v == 0) {
152 pthread_mutex_destroy (&refs->mutex);
153 refs->destructor (refs->object);
154 }
155 return v;
156 }
157
158 static inline int xine_refs_get (xine_refs_t *refs) {
159 int v;
160 pthread_mutex_lock (&refs->mutex);
161 v = refs->refs;
162 pthread_mutex_unlock (&refs->mutex);
163 return v;
164 }
165
166 #endif
167
168 /**
169 * @defgroup load_plugins Plugins loading
170 * @brief Functions related with plugins loading.
171 */
172
173 /**
174 * @ingroup load_plugins
175 * @brief Load plugins into catalog
176 * @param this xine instance
177 *
178 * All input and demux plugins will be fully loaded and initialized.
179 * Decoder plugins are loaded on demand. Video/audio output plugins
180 * have special load/probe functions
181 */
182 int _x_scan_plugins (xine_t *this) INTERNAL;
183
184 /**
185 * @ingroup load_plugins
186 * @brief Dispose (shutdown) all currently loaded plugins
187 * @param this xine instance
188 */
189 void _x_dispose_plugins (xine_t *this) INTERNAL;
190
191 void _x_free_video_driver (xine_t *xine, vo_driver_t **driver) INTERNAL;
192 void _x_free_audio_driver (xine_t *xine, ao_driver_t **driver) INTERNAL;
193
194 ///@{
195 /**
196 * @defgroup
197 * @brief find and instantiate input and demux plugins
198 */
199 demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const char *last_demux_name, input_plugin_t *input) INTERNAL;
200 input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *filename) INTERNAL;
201 input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream) INTERNAL;
202 ///@}
203
204 ///@{
205 /**
206 * @defgroup
207 * @brief create decoder fifos and threads
208 */
209
210 int _x_video_decoder_init (xine_stream_t *stream) INTERNAL;
211 void _x_video_decoder_shutdown (xine_stream_t *stream) INTERNAL;
212
213 int _x_audio_decoder_init (xine_stream_t *stream) INTERNAL;
214 void _x_audio_decoder_shutdown (xine_stream_t *stream) INTERNAL;
215 ///@}
216
217 /**
218 * @brief Benchmark available memcpy methods
219 */
220 void xine_probe_fast_memcpy(xine_t *xine) INTERNAL;
221
222 /**
223 * @brief Make file descriptors and sockets uninheritable
224 */
225 int _x_set_file_close_on_exec(int fd) INTERNAL;
226
227 int _x_set_socket_close_on_exec(int s) INTERNAL;
228
229
230 #if defined(HAVE_PTHREAD_RWLOCK)
231 # define xine_rwlock_t pthread_rwlock_t
232 # define xine_rwlock_init_default(l) pthread_rwlock_init (l, NULL)
233 # define xine_rwlock_rdlock(l) pthread_rwlock_rdlock (l)
234 # define xine_rwlock_tryrdlock(l) pthread_rwlock_tryrdlock (l)
235 # define xine_rwlock_timedrdlock(l,t) pthread_rwlock_timedrdlock (l, t)
236 # define xine_rwlock_wrlock(l) pthread_rwlock_wrlock (l)
237 # define xine_rwlock_trywrlock(l) pthread_rwlock_trywrlock (l)
238 # define xine_rwlock_timedwrlock(l,t) pthread_rwlock_timedwrlock (l, t)
239 # define xine_rwlock_unlock(l) pthread_rwlock_unlock (l)
240 # define xine_rwlock_destroy(l) pthread_rwlock_destroy (l)
241 #else
242 # define xine_rwlock_t pthread_mutex_t
243 # define xine_rwlock_init_default(l) pthread_mutex_init (l, NULL)
244 # define xine_rwlock_rdlock(l) pthread_mutex_lock (l)
245 # define xine_rwlock_tryrdlock(l) pthread_mutex_trylock (l)
246 # define xine_rwlock_timedrdlock(l,t) pthread_mutex_timedlock (l, t)
247 # define xine_rwlock_wrlock(l) pthread_mutex_lock (l)
248 # define xine_rwlock_trywrlock(l) pthread_mutex_trylock (l)
249 # define xine_rwlock_timedwrlock(l,t) pthread_mutex_timedlock (l, t)
250 # define xine_rwlock_unlock(l) pthread_mutex_unlock (l)
251 # define xine_rwlock_destroy(l) pthread_mutex_destroy (l)
252 #endif
253
254 #ifdef HAVE_POSIX_TIMERS
255 # define xine_gettime(t) clock_gettime (CLOCK_REALTIME, t)
256 #else
xine_gettime(struct timespec * ts)257 static inline int xine_gettime (struct timespec *ts) {
258 struct timeval tv;
259 int r;
260 r = gettimeofday (&tv, NULL);
261 if (!r) {
262 ts->tv_sec = tv.tv_sec;
263 ts->tv_nsec = tv.tv_usec * 1000;
264 }
265 return r;
266 }
267 #endif
268
269 #if (defined(__GNUC__) || defined(__clang__)) && defined(ARCH_X86)
xine_uint_mul_div(uint32_t num,uint32_t mul,uint32_t den)270 static inline uint32_t xine_uint_mul_div (uint32_t num, uint32_t mul, uint32_t den) {
271 register uint32_t eax = num, edx;
272 /* if result > 0xffffffff, return 0xffffffff without math exception. */
273 __asm__ __volatile__ (
274 "mull\t%2\n"
275 "\tmovl\t%3, %2\n"
276 "\tshrl\t%2\n"
277 "\taddl\t%2, %0\n"
278 "\tadcl\t$0, %1\n"
279 "\tcmpl\t%1, %3\n"
280 "\tjbe\t1f\n"
281 "\tdivl\t%3\n"
282 "\tjmp\t2f\n"
283 "1:\n"
284 "\txorl\t%0, %0\n"
285 "\tnotl\t%0\n"
286 "2:\n"
287 : "=a" (eax), "=d" (edx), "=r" (mul), "=g" (den)
288 : "0" (eax), "2" (mul), "3" (den)
289 : "cc"
290 );
291 (void)mul;
292 (void)den;
293 (void)edx;
294 return eax;
295 }
296 #else
xine_uint_mul_div(uint32_t num,uint32_t mul,uint32_t den)297 static inline uint32_t xine_uint_mul_div (uint32_t num, uint32_t mul, uint32_t den) {
298 return ((uint64_t)num * mul + (den >> 1)) / den;
299 }
300 #endif
301
xine_str2int32(const char ** s)302 static inline int32_t xine_str2int32 (const char **s) {
303 const uint8_t *p = (const uint8_t *)*s;
304 uint8_t z;
305 int32_t v;
306 do {
307 z = *p;
308 if (!z) {
309 *s = (const char *)p;
310 return 0;
311 }
312 p++;
313 z ^= '0';
314 } while ((z > 9) && (z != ('-' ^ '0')));
315 if (z == ('-' ^ '0')) {
316 v = 0;
317 while (1) {
318 z = *p++ ^ '0';
319 if (z > 9)
320 break;
321 v = 10 * v - z;
322 }
323 } else {
324 v = 0;
325 do {
326 v = 10 * v + z;
327 z = *p++ ^ '0';
328 } while (z <= 9);
329 }
330 *s = (const char *)(p - 1);
331 return v;
332 }
333
xine_str2uint32(const char ** s)334 static inline uint32_t xine_str2uint32 (const char **s) {
335 const uint8_t *p = (const uint8_t *)*s;
336 uint8_t z;
337 uint32_t v;
338 do {
339 z = *p;
340 if (!z) {
341 *s = (const char *)p;
342 return 0;
343 }
344 p++;
345 z ^= '0';
346 } while (z > 9);
347 v = 0;
348 do {
349 v = 10u * v + z;
350 z = *p++ ^ '0';
351 } while (z <= 9);
352 *s = (const char *)(p - 1);
353 return v;
354 }
355
xine_str2uint64(const char ** s)356 static inline uint64_t xine_str2uint64 (const char **s) {
357 const uint8_t *p = (const uint8_t *)*s;
358 uint8_t z;
359 uint64_t v;
360 #if defined(__WORDSIZE) && (__WORDSIZE == 32)
361 uint32_t u;
362 #endif
363 do {
364 z = *p;
365 if (!z) {
366 *s = (const char *)p;
367 return 0;
368 }
369 p++;
370 z ^= '0';
371 } while (z > 9);
372 #if defined(__WORDSIZE) && (__WORDSIZE == 32)
373 u = 0;
374 do {
375 u = 10u * u + z;
376 z = *p++ ^ '0';
377 if (z > 9) {
378 *s = (const char *)(p - 1);
379 return u;
380 }
381 } while (!(u & 0xf0000000));
382 v = u;
383 #else
384 v = 0;
385 #endif
386 do {
387 v = (v << 3) + (v << 1) + z;
388 z = *p++ ^ '0';
389 } while (z <= 9);
390 *s = (const char *)(p - 1);
391 return v;
392 }
393
394 #define XINE_MAX_INT32_STR 13
xine_int32_2str(char ** s,int32_t v)395 static inline void xine_int32_2str (char **s, int32_t v) {
396 uint8_t b[24], *t = b + 11, *q = (uint8_t *)*s;
397 uint32_t u;
398 if (v < 0) {
399 *q++ = '-';
400 u = -v;
401 } else {
402 u = v;
403 }
404 *t = 0;
405 do {
406 *--t = u % 10u + '0';
407 u /= 10u;
408 } while (u);
409 memcpy (q, t, 12);
410 *s = (char *)(q + (b + 11 - t));
411 }
412
xine_uint32_2str(char ** s,uint32_t v)413 static inline void xine_uint32_2str (char **s, uint32_t v) {
414 uint8_t b[24], *t = b + 11, *q = (uint8_t *)*s;
415 *t = 0;
416 do {
417 *--t = v % 10u + '0';
418 v /= 10u;
419 } while (v);
420 memcpy (q, t, 12);
421 *s = (char *)(q + (b + 11 - t));
422 }
423
424 #define XINE_MAX_INT64_STR 21
xine_uint64_2str(char ** s,uint64_t v)425 static inline void xine_uint64_2str (char **s, uint64_t v) {
426 uint8_t b[44], *t = b + 21, *q = (uint8_t *)*s;
427 *t = 0;
428 do {
429 *--t = v % 10u + '0';
430 v /= 10u;
431 } while (v);
432 memcpy (q, t, 21);
433 *s = (char *)(q + (b + 21 - t));
434 }
435
436 /* A little helper for integers whose size is not obvious, like off_t and time_t. */
437 #define xine_uint2str(s,v) do { \
438 if (sizeof (v) == 8) \
439 xine_uint64_2str (s, v); \
440 else \
441 xine_uint32_2str (s, v); \
442 } while (0)
443
444 #if 1 /* XXX: Is this safe everywhere? */
445 # define PTR_IN_RANGE(_ptr,_start,_size) \
446 ((uintptr_t)((uint8_t *)(_ptr) - (uint8_t *)(_start)) < (uintptr_t)(_size))
447 #else
448 # define PTR_IN_RANGE(_ptr,_start,_size) \
449 ((uint8_t *)(_ptr) >= (uint8_t *)(_start) && ((uint8_t *)(_ptr) < (uint8_t *)(_start) + (_size)))
450 #endif
451
452 typedef struct {
453 xine_t x;
454
455 xine_ticket_t *port_ticket;
456 pthread_mutex_t log_lock;
457
458 xine_log_cb_t log_cb;
459 void *log_cb_user_data;
460
461 int flags;
462 int network_timeout;
463 enum {
464 XINE_IP_PREF_AUTO = 0,
465 XINE_IP_PREF_4,
466 XINE_IP_PREF_4_6,
467 XINE_IP_PREF_6_4
468 } ip_pref;
469
470 uint32_t join_av:1;
471
472 /* lock controlling speed change access.
473 * if we should ever introduce per stream clock and ticket,
474 * move this to xine_stream_private_t below. */
475 #define SPEED_FLAG_IGNORE_CHANGE 1
476 #define SPEED_FLAG_CHANGING 2
477 #define SPEED_FLAG_WANT_LIVE 4
478 #define SPEED_FLAG_WANT_NEW 8
479 uint32_t speed_change_flags;
480 int speed_change_new_live;
481 int speed_change_new_speed;
482 pthread_mutex_t speed_change_lock;
483 pthread_cond_t speed_change_done;
484 /* set when pauseing with port ticket granted, for XINE_PARAM_VO_SINGLE_STEP. */
485 /* special values for set_speed_internal (). now defined in xine/xine_internal.h. */
486 /* # define XINE_LIVE_PAUSE_ON 0x7ffffffd */
487 /* # define XINE_LIVE_PAUSE_OFF 0x7ffffffc */
488 } xine_private_t;
489
490 typedef struct xine_stream_private_st {
491 xine_stream_t s;
492
493 int status;
494
495 uint32_t video_thread_created:1;
496 uint32_t audio_thread_created:1;
497 uint32_t slave_is_subtitle:1; /*< ... and will be automaticaly disposed */
498 uint32_t emergency_brake:1; /*< something went really wrong and this stream must be
499 * stopped. usually due some fatal error on output
500 * layers as they cannot call xine_stop. */
501 uint32_t early_finish_event:1; /*< do not wait fifos get empty before sending event */
502 uint32_t gapless_switch:1; /*< next stream switch will be gapless */
503 uint32_t keep_ao_driver_open:1;
504 uint32_t finished_naturally:1;
505
506 input_class_t *eject_class;
507
508 /* vo_driver_t *video_driver;*/
509 pthread_t video_thread;
510 video_decoder_t *video_decoder_plugin;
511 extra_info_t *video_decoder_extra_info;
512 int video_decoder_streamtype;
513 int video_channel;
514
515 int audio_track_map_entries;
516
517 int audio_decoder_streamtype;
518 pthread_t audio_thread;
519 audio_decoder_t *audio_decoder_plugin;
520 extra_info_t *audio_decoder_extra_info;
521
522 uint32_t audio_type;
523 /* *_user: -2 => off
524 -1 => auto (use *_auto value)
525 >=0 => respect the user's choice
526 */
527 int audio_channel_user;
528 /* int audio_channel_auto; */
529
530 /* spu_decoder_t *spu_decoder_plugin; */
531 /* int spu_decoder_streamtype; */
532 int spu_track_map_entries;
533 /* int spu_channel_user; */
534 /* int spu_channel_auto; */
535 /* int spu_channel_letterbox; */
536 int spu_channel_pan_scan;
537 /* int spu_channel; */
538
539 /* lock for public xine player functions */
540 pthread_mutex_t frontend_lock;
541
542 #define XINE_NUM_SIDE_STREAMS 4
543 /* HACK: protected by info_lock below.
544 * side_streams[0] always points to the master, which is the stream itself if not a side stream.
545 * It is set by init, and does not change until dispose.
546 * In other words: it may safely be read without lock. */
547 struct xine_stream_private_st *side_streams[XINE_NUM_SIDE_STREAMS];
548 /* 1 << side_stream_index (1, 2, 4, 8) */
549 uint32_t id_flag;
550
551 /* stream meta information */
552 /* Grab lock, or use helpers (see info_helper.c). */
553 xine_rwlock_t info_lock;
554 int stream_info[XINE_STREAM_INFO_MAX];
555 /* Broken API: _x_meta_info_get_public () returns const char *, with no go away safety.
556 * For now, we copy info to info_public when a new value is requested :-/ */
557 xine_rwlock_t meta_lock;
558 char *meta_info_public[XINE_STREAM_INFO_MAX];
559 char *meta_info[XINE_STREAM_INFO_MAX];
560
561 /* seeking slowdown */
562 struct {
563 pthread_mutex_t lock;
564 pthread_cond_t reached;
565 /* 3: wait for first frame to decode (stream start).
566 * 2: wait for first frame to display (stream seek).
567 * 1: after 2, first frame is decoded but not yet displayed.
568 * 0: waiting done.
569 */
570 uint32_t flag:2;
571 } first_frame;
572
573 /* wait for headers sent / stream decoding finished */
574 struct {
575 pthread_mutex_t lock;
576 pthread_cond_t changed;
577 int headers_audio;
578 int headers_video;
579 int finisheds_audio;
580 int finisheds_video;
581 int demuxers_running;
582 /* network buffering control. */
583 int nbc_refs;
584 xine_nbc_t *nbc;
585 } counter;
586
587 /* event mechanism */
588 struct {
589 pthread_mutex_t lock;
590 xine_list_t *queues;
591 } event;
592
593 /* demux thread stuff */
594 struct {
595 demux_plugin_t *plugin;
596 pthread_t thread;
597 pthread_mutex_t lock;
598 pthread_mutex_t action_lock;
599 pthread_cond_t resume;
600 /* used in _x_demux_... functions to synchronize order of pairwise A/V buffer operations */
601 pthread_mutex_t pair;
602 /* next 2 protected by action_lock */
603 uint32_t action_pending;
604 uint32_t input_caps;
605 uint32_t thread_created:1;
606 uint32_t thread_running:1;
607 /* filter out duplicate seek discontinuities from side streams */
608 uint32_t max_seek_bufs;
609 /* set of id_flag values */
610 uint32_t start_buffers_sent;
611 } demux;
612
613 #define XINE_NUM_CURR_EXTRA_INFOS 2
614 xine_refs_t current_extra_info_index;
615 extra_info_t current_extra_info[XINE_NUM_CURR_EXTRA_INFOS];
616 int video_seek_count;
617
618 int delay_finish_event; /* delay event in 1/10 sec units. 0=>no delay, -1=>forever */
619
620 int slave_affection; /* what operations need to be propagated down to the slave? */
621
622 int err;
623
624 xine_post_out_t video_source;
625 xine_post_out_t audio_source;
626
627 broadcaster_t *broadcaster;
628
629 xine_refs_t refs;
630
631 struct {
632 pthread_mutex_t lock;
633 xine_keyframes_entry_t *array;
634 int size, used, lastadd;
635 } index;
636
637 uint32_t disable_decoder_flush_at_discontinuity;
638
639 /* _x_find_input_plugin () recursion protection */
640 input_class_t *query_input_plugins[2];
641
642 extra_info_t ei[2];
643 } xine_stream_private_t;
644
645 void xine_current_extra_info_set (xine_stream_private_t *stream, const extra_info_t *info) INTERNAL;
646
647 /* Nasty net_buf_ctrl helper: inform about something outside its regular callbacks. */
648 #define XINE_NBC_EVENT_AUDIO_DRY 1
649 void xine_nbc_event (xine_stream_private_t *stream, uint32_t type) INTERNAL;
650
651 EXTERN_C_STOP
652
653 #endif
654