~ubuntu-branches/ubuntu/trusty/phonon/trusty-updates

« back to all changes in this revision

Viewing changes to xine/net_buf_ctrl.c

  • Committer: Bazaar Package Importer
  • Author(s): Modestas Vainius
  • Date: 2011-03-11 21:39:20 UTC
  • mfrom: (6.1.4 experimental)
  • Revision ID: james.westby@ubuntu.com-20110311213920-pvkmqc1gdpy88uzx
Tags: 4:4.6.0really4.4.4-2
* Drop phonon-backends-dbg from phonon-dbg Recommends/Breaks. No longer
  needed.
* Readd packaging copyright/licensing to debian/copyright.
* Bump libphonon-dev Breaks/Replaces to << 4:4.6.0really4.4.4 for
  libphononexperimental-dev. experimental/avcaptureinterface.h header which
  used to be there up to 4.4.4 (see changelog below).
* Switch debian/rules build engine to dhmk (qt-kde-team/2/*):
  - build-depend on pkg-kde-tools >= 0.11;
  - port debian/rules to dhmk keeping it dh compatible as much as possible.
* Drop unused ${shlibs:Depends} from libphonon-dev and
  libphononexperimental-dev packages.
* Add README.Debian to phonon-backend-null package.
* Remove phonon-backend-null.lintian-overrides: phonon-backend-null is no
  longer and empty package due to README.Debian (see above).
* Release to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2000-2003 the xine project
3
 
 * Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
4
 
 *
5
 
 * This file is copied from xine, a free video player.
6
 
 *
7
 
 * xine is free software; you can redistribute it and/or modify
8
 
 * it under the terms of the GNU General Public License as published by
9
 
 * the Free Software Foundation; either version 2 of the License, or
10
 
 * (at your option) any later version.
11
 
 *
12
 
 * xine is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
20
 
 *
21
 
 * network buffering control
22
 
 */
23
 
 
24
 
 
25
 
#include <stdlib.h>
26
 
#include <unistd.h>
27
 
 
28
 
/********** logging **********/
29
 
#define LOG_MODULE "net_buf_ctrl"
30
 
#define LOG_VERBOSE
31
 
/*
32
 
#define LOG
33
 
*/
34
 
 
35
 
 
36
 
#include <xine/xine_internal.h>
37
 
#include "net_buf_ctrl.h"
38
 
 
39
 
#define DEFAULT_HIGH_WATER_MARK 5000 /* in 1/1000 s */
40
 
 
41
 
#define FULL_FIFO_MARK             5 /* buffers free */
42
 
 
43
 
#define FIFO_PUT                   0
44
 
#define FIFO_GET                   1
45
 
 
46
 
struct nbc_s {
47
 
 
48
 
  xine_stream_t   *stream;
49
 
  void (*set_speed_pause)(void *);
50
 
  void *set_speed_pause_data;
51
 
  void (*set_speed_normal)(void *);
52
 
  void *set_speed_normal_data;
53
 
 
54
 
  int              buffering;
55
 
  int              enabled;
56
 
 
57
 
  int              progress;
58
 
  fifo_buffer_t   *video_fifo;
59
 
  fifo_buffer_t   *audio_fifo;
60
 
  int              video_fifo_fill;
61
 
  int              audio_fifo_fill;
62
 
  int              video_fifo_free;
63
 
  int              audio_fifo_free;
64
 
  int64_t          video_fifo_length;     /* in ms */
65
 
  int64_t          audio_fifo_length;     /* in ms */
66
 
  int64_t          video_fifo_length_int; /* in ms */
67
 
  int64_t          audio_fifo_length_int; /* in ms */
68
 
 
69
 
  int64_t          high_water_mark;
70
 
  /* bitrate */
71
 
  int64_t          video_last_pts;
72
 
  int64_t          audio_last_pts;
73
 
  int64_t          video_first_pts;
74
 
  int64_t          audio_first_pts;
75
 
  int64_t          video_fifo_size;
76
 
  int64_t          audio_fifo_size;
77
 
  int64_t          video_br;
78
 
  int64_t          audio_br;
79
 
 
80
 
  int              video_in_disc;
81
 
  int              audio_in_disc;
82
 
 
83
 
  pthread_mutex_t  mutex;
84
 
};
85
 
 
86
 
static void report_progress (xine_stream_t *stream, int p) {
87
 
 
88
 
  xine_event_t             event;
89
 
  xine_progress_data_t     prg;
90
 
 
91
 
  prg.description = _("Buffering...");
92
 
  prg.percent = (p>100)?100:p;
93
 
 
94
 
  event.type = XINE_EVENT_PROGRESS;
95
 
  event.data = &prg;
96
 
  event.data_length = sizeof (xine_progress_data_t);
97
 
 
98
 
  xine_event_send (stream, &event);
99
 
}
100
 
 
101
 
 
102
 
static void nbc_set_speed_pause (void *data) {
103
 
  xine_stream_t *stream = (xine_stream_t *)data;
104
 
 
105
 
  xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_set_speed_pause\n");
106
 
  _x_set_speed (stream, XINE_SPEED_PAUSE);
107
 
  stream->xine->clock->set_option (stream->xine->clock, CLOCK_SCR_ADJUSTABLE, 0);
108
 
}
109
 
 
110
 
static void nbc_set_speed_normal (void *data) {
111
 
  xine_stream_t *stream = (xine_stream_t *)data;
112
 
 
113
 
  xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_set_speed_normal\n");
114
 
  _x_set_speed (stream, XINE_SPEED_NORMAL);
115
 
  stream->xine->clock->set_option (stream->xine->clock, CLOCK_SCR_ADJUSTABLE, 1);
116
 
}
117
 
 
118
 
/*  Try to compute the length of the fifo in 1/1000 s
119
 
 *  2 methods :
120
 
 *    if the bitrate is known
121
 
 *      use the size of the fifo
122
 
 *    else
123
 
 *      use the the first and the last pts of the fifo
124
 
 */
125
 
static void nbc_compute_fifo_length(nbc_t *this,
126
 
                                    fifo_buffer_t *fifo,
127
 
                                    buf_element_t *buf,
128
 
                                    int action) {
129
 
  int fifo_free, fifo_fill, fifo_div;
130
 
  int64_t video_br, audio_br, diff;
131
 
  int has_video, has_audio;
132
 
 
133
 
  has_video = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO);
134
 
  has_audio = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO);
135
 
  video_br  = _x_stream_info_get(this->stream, XINE_STREAM_INFO_VIDEO_BITRATE);
136
 
  audio_br  = _x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE);
137
 
 
138
 
  fifo_free = fifo->buffer_pool_num_free;
139
 
  fifo_fill = fifo->fifo_size;
140
 
  fifo_div = fifo_fill + fifo_free - 1;
141
 
  if (fifo_div == 0)
142
 
    fifo_div = 1; /* avoid a possible divide-by-zero */
143
 
 
144
 
  if (fifo == this->video_fifo) {
145
 
    this->video_fifo_free = fifo_free;
146
 
    this->video_fifo_fill = (100 * fifo_fill) / fifo_div;
147
 
    this->video_fifo_size = fifo->fifo_data_size;
148
 
    
149
 
    if (buf->pts && (this->video_in_disc == 0)) {
150
 
      if (action == FIFO_PUT) {
151
 
        this->video_last_pts = buf->pts;
152
 
        if (this->video_first_pts == 0) {
153
 
          this->video_first_pts = buf->pts;
154
 
        }
155
 
      } else {
156
 
        /* GET */
157
 
        this->video_first_pts = buf->pts;
158
 
      }
159
 
    }
160
 
    
161
 
    if (video_br) {
162
 
      this->video_br = video_br;
163
 
      this->video_fifo_length_int = (8000 * this->video_fifo_size) / this->video_br;
164
 
    } else {
165
 
      if (buf->pts && (this->video_in_disc == 0)) {
166
 
        this->video_fifo_length_int = (this->video_last_pts - this->video_first_pts) / 90;
167
 
        if (this->video_fifo_length)
168
 
          this->video_br = 8000 * (this->video_fifo_size / this->video_fifo_length);
169
 
        else
170
 
          this->video_br = 0;
171
 
      } else {
172
 
        if (this->video_br)
173
 
          this->video_fifo_length_int = (8000 * this->video_fifo_size) / this->video_br;
174
 
      }
175
 
    }
176
 
 
177
 
  } else {
178
 
    this->audio_fifo_free = fifo_free;
179
 
    this->audio_fifo_fill = (100 * fifo_fill) / fifo_div;
180
 
    this->audio_fifo_size = fifo->fifo_data_size;
181
 
    
182
 
    if (buf->pts && (this->audio_in_disc == 0)) {
183
 
      if (action == FIFO_PUT) {
184
 
        this->audio_last_pts = buf->pts;
185
 
        if (!this->audio_first_pts) {
186
 
          this->audio_first_pts = buf->pts;
187
 
        }
188
 
      } else {
189
 
        /* GET */
190
 
        this->audio_first_pts = buf->pts;
191
 
      }
192
 
    }
193
 
    
194
 
    if (audio_br) {
195
 
      this->audio_br = audio_br;
196
 
      this->audio_fifo_length_int = (8000 * this->audio_fifo_size) / this->audio_br;
197
 
    } else {
198
 
      if (buf->pts && (this->audio_in_disc == 0)) {
199
 
        this->audio_fifo_length_int = (this->audio_last_pts - this->audio_first_pts) / 90;
200
 
        if (this->audio_fifo_length)
201
 
          this->audio_br = 8000 * (this->audio_fifo_size / this->audio_fifo_length);
202
 
        else
203
 
          this->audio_br = 0;
204
 
      } else {
205
 
        if (this->audio_br)
206
 
          this->audio_fifo_length_int = (8000 * this->audio_fifo_size) / this->audio_br;
207
 
      }
208
 
    }
209
 
  }
210
 
  
211
 
  /* decoder buffer compensation */
212
 
  if (has_audio && has_video) {
213
 
    diff = this->video_first_pts - this->audio_first_pts;
214
 
  } else {
215
 
    diff = 0;
216
 
  }
217
 
  if (diff > 0) {
218
 
    this->video_fifo_length = this->video_fifo_length_int + diff / 90;
219
 
    this->audio_fifo_length = this->audio_fifo_length_int;
220
 
  } else {
221
 
    this->video_fifo_length = this->video_fifo_length_int;
222
 
    this->audio_fifo_length = this->audio_fifo_length_int - diff / 90;
223
 
  }
224
 
}
225
 
 
226
 
/* Alloc callback */
227
 
static void nbc_alloc_cb (fifo_buffer_t *fifo, void *this_gen) {
228
 
  nbc_t *this = (nbc_t*)this_gen;
229
 
 
230
 
  lprintf("enter nbc_alloc_cb\n");
231
 
  pthread_mutex_lock(&this->mutex);
232
 
  if (this->enabled && this->buffering) {
233
 
 
234
 
    /* restart playing if one fifo is full (to avoid deadlock) */
235
 
    if (fifo->buffer_pool_num_free <= 1) {
236
 
      this->progress = 100;
237
 
      report_progress (this->stream, 100);
238
 
      this->buffering = 0;
239
 
 
240
 
      xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_alloc_cb: stops buffering\n");
241
 
 
242
 
      this->set_speed_normal(this->set_speed_normal_data);
243
 
    }
244
 
  }
245
 
  pthread_mutex_unlock(&this->mutex);
246
 
  lprintf("exit nbc_alloc_cb\n");
247
 
}
248
 
 
249
 
/* Put callback
250
 
 * the fifo mutex is locked */
251
 
static void nbc_put_cb (fifo_buffer_t *fifo, 
252
 
                        buf_element_t *buf, void *this_gen) {
253
 
  nbc_t *this = (nbc_t*)this_gen;
254
 
  int64_t progress = 0;
255
 
  int64_t video_p = 0;
256
 
  int64_t audio_p = 0;
257
 
  int has_video, has_audio;
258
 
 
259
 
  lprintf("enter nbc_put_cb\n");
260
 
  pthread_mutex_lock(&this->mutex);
261
 
 
262
 
  if ((buf->type & BUF_MAJOR_MASK) != BUF_CONTROL_BASE) {
263
 
 
264
 
    if (this->enabled) {
265
 
      
266
 
      nbc_compute_fifo_length(this, fifo, buf, FIFO_PUT);
267
 
 
268
 
      if (this->buffering) {
269
 
 
270
 
        has_video = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO);
271
 
        has_audio = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO);
272
 
        /* restart playing if high_water_mark is reached by all fifos
273
 
         * do not restart if has_video and has_audio are false to avoid
274
 
         * a yoyo effect at the beginning of the stream when these values
275
 
         * are not yet known.
276
 
         *
277
 
         * be sure that the next buffer_pool_alloc() call will not deadlock,
278
 
         * we need at least 2 buffers (see buffer.c)
279
 
         */
280
 
        if ((((!has_video) || (this->video_fifo_length > this->high_water_mark)) &&
281
 
             ((!has_audio) || (this->audio_fifo_length > this->high_water_mark)) &&
282
 
             (has_video || has_audio))) {
283
 
 
284
 
          this->progress = 100;
285
 
          report_progress (this->stream, 100);
286
 
          this->buffering = 0;
287
 
 
288
 
          xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_put_cb: stops buffering\n");
289
 
 
290
 
          this->set_speed_normal(this->set_speed_normal_data);
291
 
  
292
 
          this->high_water_mark += this->high_water_mark / 2;   
293
 
 
294
 
        } else {
295
 
          /*  compute the buffering progress
296
 
           *    50%: video
297
 
           *    50%: audio */
298
 
          video_p = ((this->video_fifo_length * 50) / this->high_water_mark);
299
 
          if (video_p > 50) video_p = 50;
300
 
          audio_p = ((this->audio_fifo_length * 50) / this->high_water_mark);
301
 
          if (audio_p > 50) audio_p = 50;
302
 
 
303
 
          if ((has_video) && (has_audio)) {
304
 
            progress = video_p + audio_p;
305
 
          } else if (has_video) {
306
 
            progress = 2 * video_p;
307
 
          } else {
308
 
            progress = 2 * audio_p;
309
 
          }
310
 
 
311
 
          /* if the progress can't be computed using the fifo length,
312
 
             use the number of buffers */
313
 
          if (!progress) {
314
 
            video_p = this->video_fifo_fill;
315
 
            audio_p = this->audio_fifo_fill;
316
 
            progress = (video_p > audio_p) ? video_p : audio_p;
317
 
          }
318
 
 
319
 
          if (progress > this->progress) {
320
 
            report_progress (this->stream, progress);
321
 
            this->progress = progress;
322
 
          }
323
 
        }
324
 
      }
325
 
    }
326
 
  } else {
327
 
 
328
 
    switch (buf->type) {
329
 
      case BUF_CONTROL_START:
330
 
        lprintf("BUF_CONTROL_START\n");
331
 
        if (!this->enabled) {
332
 
          /* a new stream starts */
333
 
          xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_put_cb: starts buffering\n");
334
 
          this->enabled           = 1;
335
 
          this->buffering         = 1;
336
 
          this->video_first_pts   = 0;
337
 
          this->video_last_pts    = 0;
338
 
          this->audio_first_pts   = 0;
339
 
          this->audio_last_pts    = 0;
340
 
          this->video_fifo_length = 0;
341
 
          this->audio_fifo_length = 0;
342
 
          this->set_speed_pause(this->set_speed_pause_data);
343
 
          this->progress = 0;
344
 
          report_progress (this->stream, progress);
345
 
        }
346
 
        break;
347
 
      case BUF_CONTROL_NOP:
348
 
        if (!(buf->decoder_flags & BUF_FLAG_END_USER) &&
349
 
            !(buf->decoder_flags & BUF_FLAG_END_STREAM)) {
350
 
          break;
351
 
        }
352
 
        /* fall through */
353
 
      case BUF_CONTROL_END:
354
 
      case BUF_CONTROL_QUIT:
355
 
        lprintf("BUF_CONTROL_END\n");
356
 
        if (this->enabled) {
357
 
          /* end of stream :
358
 
           *   - disable the nbc
359
 
           *   - unpause the engine if buffering
360
 
           */
361
 
          this->enabled = 0;
362
 
 
363
 
          lprintf("DISABLE netbuf\n");
364
 
 
365
 
          if (this->buffering) {
366
 
            this->buffering = 0;
367
 
            this->progress = 100;
368
 
            report_progress (this->stream, this->progress);
369
 
 
370
 
            xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_put_cb: stops buffering\n");
371
 
 
372
 
            this->set_speed_normal(this->set_speed_normal_data);
373
 
          }
374
 
        }
375
 
        break;
376
 
 
377
 
      case BUF_CONTROL_NEWPTS:
378
 
        /* discontinuity management */
379
 
        if (fifo == this->video_fifo) {
380
 
          this->video_in_disc++;
381
 
          xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
382
 
                  "\nnet_buf_ctrl: nbc_put_cb video disc %d\n", this->video_in_disc);
383
 
        } else {
384
 
          this->audio_in_disc++;
385
 
          xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
386
 
                  "\nnet_buf_ctrl: nbc_put_cb audio disc %d\n", this->audio_in_disc);
387
 
        }
388
 
        break;
389
 
    }
390
 
 
391
 
    if (fifo == this->video_fifo) {
392
 
      this->video_fifo_free = fifo->buffer_pool_num_free;
393
 
      this->video_fifo_size = fifo->fifo_data_size;
394
 
    } else {
395
 
      this->audio_fifo_free = fifo->buffer_pool_num_free;
396
 
      this->audio_fifo_size = fifo->fifo_data_size;
397
 
    }
398
 
  }
399
 
  pthread_mutex_unlock(&this->mutex);
400
 
  lprintf("exit nbc_put_cb\n");
401
 
}
402
 
 
403
 
/* Get callback
404
 
 * the fifo mutex is locked */
405
 
static void nbc_get_cb (fifo_buffer_t *fifo,
406
 
                        buf_element_t *buf, void *this_gen) {
407
 
  nbc_t *this = (nbc_t*)this_gen;
408
 
 
409
 
  lprintf("enter nbc_get_cb\n");
410
 
  pthread_mutex_lock(&this->mutex);
411
 
 
412
 
  if ((buf->type & BUF_MAJOR_MASK) != BUF_CONTROL_BASE) {
413
 
 
414
 
    if (this->enabled) {
415
 
 
416
 
      nbc_compute_fifo_length(this, fifo, buf, FIFO_GET);
417
 
      
418
 
      if (!this->buffering) {
419
 
        /* start buffering if one fifo is empty
420
 
         */
421
 
        int has_video = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO);
422
 
        int has_audio = _x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO);
423
 
        if (((this->video_fifo_length == 0) && has_video) ||
424
 
            ((this->audio_fifo_length == 0) && has_audio)) {
425
 
          /* do not pause if a fifo is full to avoid yoyo (play-pause-play-pause) */
426
 
          if ((this->video_fifo_free > FULL_FIFO_MARK) &&
427
 
              (this->audio_fifo_free > FULL_FIFO_MARK)) {
428
 
            this->buffering = 1;
429
 
            this->progress  = 0;
430
 
            report_progress (this->stream, 0);
431
 
 
432
 
            xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, 
433
 
                    "\nnet_buf_ctrl: nbc_get_cb: starts buffering, vid: %d, aud: %d\n",
434
 
                    this->video_fifo_fill, this->audio_fifo_fill);
435
 
            this->set_speed_pause(this->set_speed_pause_data);
436
 
          }
437
 
        }
438
 
      } else {
439
 
        this->set_speed_pause(this->set_speed_pause_data);
440
 
      }
441
 
 
442
 
    }
443
 
  } else {
444
 
    /* discontinuity management */
445
 
    if (buf->type == BUF_CONTROL_NEWPTS) {
446
 
      if (fifo == this->video_fifo) {
447
 
        this->video_in_disc--;
448
 
        xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
449
 
                "\nnet_buf_ctrl: nbc_get_cb video disc %d\n", this->video_in_disc);
450
 
      } else {
451
 
        this->audio_in_disc--;
452
 
        xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
453
 
                "\nnet_buf_ctrl: nbc_get_cb audio disc %d\n", this->audio_in_disc);
454
 
      }
455
 
    }
456
 
 
457
 
    if (fifo == this->video_fifo) {
458
 
      this->video_fifo_free = fifo->buffer_pool_num_free;
459
 
      this->video_fifo_size = fifo->fifo_data_size;
460
 
    } else {
461
 
      this->audio_fifo_free = fifo->buffer_pool_num_free;
462
 
      this->audio_fifo_size = fifo->fifo_data_size;
463
 
    }
464
 
  }
465
 
 
466
 
  pthread_mutex_unlock(&this->mutex);
467
 
  lprintf("exit nbc_get_cb\n");
468
 
}
469
 
 
470
 
void nbc_set_pause_cb (nbc_t *this, void (*cb)(void *), void *data)
471
 
{
472
 
    this->set_speed_pause = cb;
473
 
    this->set_speed_pause_data = data;
474
 
}
475
 
 
476
 
void nbc_set_normal_cb (nbc_t *this, void (*cb)(void *), void *data)
477
 
{
478
 
    this->set_speed_normal = cb;
479
 
    this->set_speed_normal_data = data;
480
 
}
481
 
 
482
 
nbc_t *nbc_init (xine_stream_t *stream) {
483
 
  
484
 
  nbc_t *this = calloc(1, sizeof (nbc_t));
485
 
  fifo_buffer_t *video_fifo = stream->video_fifo;
486
 
  fifo_buffer_t *audio_fifo = stream->audio_fifo;
487
 
  double video_fifo_factor, audio_fifo_factor;
488
 
  cfg_entry_t *entry;
489
 
 
490
 
  lprintf("nbc_init\n");
491
 
  pthread_mutex_init (&this->mutex, NULL);
492
 
 
493
 
  this->stream              = stream;
494
 
  this->set_speed_pause     = nbc_set_speed_pause;
495
 
  this->set_speed_pause_data = stream;
496
 
  this->set_speed_normal    = nbc_set_speed_normal;
497
 
  this->set_speed_normal_data = stream;
498
 
  this->video_fifo          = video_fifo;
499
 
  this->audio_fifo          = audio_fifo;
500
 
  
501
 
  /* when the FIFO sizes are increased compared to the default configuration,
502
 
   * apply a factor to the high water mark */
503
 
  entry = stream->xine->config->lookup_entry(stream->xine->config, "engine.buffers.video_num_buffers");
504
 
  /* No entry when no video output */
505
 
  if (entry)
506
 
    video_fifo_factor = (double)video_fifo->buffer_pool_capacity / (double)entry->num_default;
507
 
  else
508
 
    video_fifo_factor = 1.0;
509
 
  entry = stream->xine->config->lookup_entry(stream->xine->config, "engine.buffers.audio_num_buffers");
510
 
  /* When there's no audio output, there's no entry */
511
 
  if (entry)
512
 
    audio_fifo_factor = (double)audio_fifo->buffer_pool_capacity / (double)entry->num_default;
513
 
  else
514
 
    audio_fifo_factor = 1.0;
515
 
  /* use the smaller factor */
516
 
  if (video_fifo_factor < audio_fifo_factor)
517
 
    this->high_water_mark = (double)DEFAULT_HIGH_WATER_MARK * video_fifo_factor;
518
 
  else
519
 
    this->high_water_mark = (double)DEFAULT_HIGH_WATER_MARK * audio_fifo_factor;
520
 
 
521
 
  video_fifo->register_alloc_cb(video_fifo, nbc_alloc_cb, this);
522
 
  video_fifo->register_put_cb(video_fifo, nbc_put_cb, this);
523
 
  video_fifo->register_get_cb(video_fifo, nbc_get_cb, this);
524
 
 
525
 
  audio_fifo->register_alloc_cb(audio_fifo, nbc_alloc_cb, this);
526
 
  audio_fifo->register_put_cb(audio_fifo, nbc_put_cb, this);
527
 
  audio_fifo->register_get_cb(audio_fifo, nbc_get_cb, this);
528
 
 
529
 
  return this;
530
 
}
531
 
 
532
 
void nbc_close (nbc_t *this) {
533
 
  fifo_buffer_t *video_fifo = this->stream->video_fifo;
534
 
  fifo_buffer_t *audio_fifo = this->stream->audio_fifo;
535
 
  xine_t        *xine       = this->stream->xine;
536
 
 
537
 
  xprintf(xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_close\n");
538
 
 
539
 
  /* unregister all fifo callbacks */
540
 
  /* do not lock the mutex to avoid deadlocks if a decoder calls fifo->get() */
541
 
  video_fifo->unregister_alloc_cb(video_fifo, nbc_alloc_cb);
542
 
  video_fifo->unregister_put_cb(video_fifo, nbc_put_cb);
543
 
  video_fifo->unregister_get_cb(video_fifo, nbc_get_cb);
544
 
 
545
 
  audio_fifo->unregister_alloc_cb(audio_fifo, nbc_alloc_cb);
546
 
  audio_fifo->unregister_put_cb(audio_fifo, nbc_put_cb);
547
 
  audio_fifo->unregister_get_cb(audio_fifo, nbc_get_cb);
548
 
 
549
 
  /* now we are sure that nobody will call a callback */
550
 
  this->stream->xine->clock->set_option (this->stream->xine->clock, CLOCK_SCR_ADJUSTABLE, 1);
551
 
 
552
 
  pthread_mutex_destroy(&this->mutex);
553
 
  free (this);
554
 
  xprintf(xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_close: done\n");
555
 
}