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