diff options
Diffstat (limited to 'src/xine-engine')
37 files changed, 839 insertions, 493 deletions
diff --git a/src/xine-engine/alphablend.c b/src/xine-engine/alphablend.c index a7ab33cf8..a9b015209 100644 --- a/src/xine-engine/alphablend.c +++ b/src/xine-engine/alphablend.c @@ -23,6 +23,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* #define LOG_BLEND_YUV #define LOG_BLEND_RGB16 @@ -1110,12 +1114,12 @@ static uint8_t *(*blend_yuv_grow_extra_data(alphablend_t *extra_data, int osd_wi uint8_t *data[ 3 ][ 2 ]; } *header = (struct header_s *)extra_data->buffer; - int needed_buffer_size = sizeof (*header) + osd_width * sizeof (uint8_t[ 3 ][ 2 ]); + size_t needed_buffer_size = sizeof (*header) + osd_width * sizeof (uint8_t[ 3 ][ 2 ]); if (extra_data->buffer_size < needed_buffer_size) { free(extra_data->buffer); - header = xine_xmalloc(needed_buffer_size); + header = calloc(1, needed_buffer_size); if (!header) { extra_data->buffer_size = 0; return 0; @@ -1552,12 +1556,12 @@ static uint8_t *(*blend_yuy2_grow_extra_data(alphablend_t *extra_data, int osd_w uint8_t *data[ 3 ]; } *header = (struct header_s *)extra_data->buffer; - int needed_buffer_size = sizeof (*header) + osd_width * sizeof (uint8_t[ 3 ]); + size_t needed_buffer_size = sizeof (*header) + osd_width * sizeof (uint8_t[ 3 ]); if (extra_data->buffer_size < needed_buffer_size) { free(extra_data->buffer); - header = xine_xmalloc(needed_buffer_size); + header = calloc(1, needed_buffer_size); if (!header) { extra_data->buffer_size = 0; return 0; diff --git a/src/xine-engine/alphablend.h b/src/xine-engine/alphablend.h index 3c9a693d9..7aa63b306 100644 --- a/src/xine-engine/alphablend.h +++ b/src/xine-engine/alphablend.h @@ -39,22 +39,7 @@ typedef struct { void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine) XINE_PROTECTED; void _x_alphablend_free(alphablend_t *extra_data) XINE_PROTECTED; -/* _MSC_VER port changes */ -#undef ATTRIBUTE_PACKED -#undef PRAGMA_PACK_BEGIN -#undef PRAGMA_PACK_END - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) || defined(__ICC) -#define ATTRIBUTE_PACKED __attribute__ ((packed)) -#define PRAGMA_PACK 0 -#endif - -#if !defined(ATTRIBUTE_PACKED) -#define ATTRIBUTE_PACKED -#define PRAGMA_PACK 1 -#endif - -#if PRAGMA_PACK +#if !SUPPORT_ATTRIBUTE_PACKED #pragma pack(8) #endif @@ -63,10 +48,10 @@ typedef struct { /* CLUT == Color LookUp Table */ uint8_t cr; uint8_t y; uint8_t foo; -} ATTRIBUTE_PACKED clut_t; +} XINE_PACKED clut_t; -#if PRAGMA_PACK +#if !SUPPORT_ATTRIBUTE_PACKED #pragma pack() #endif diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 5476262d9..855dee372 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.c @@ -89,16 +89,18 @@ static void *audio_decoder_loop (void *stream_gen) { if (stream->audio_decoder_plugin) { lprintf ("close old decoder\n"); - + + stream->keep_ao_driver_open = !!(buf->decoder_flags & BUF_FLAG_GAPLESS_SW); _x_free_audio_decoder (stream, stream->audio_decoder_plugin); stream->audio_decoder_plugin = NULL; stream->audio_track_map_entries = 0; stream->audio_type = 0; + stream->keep_ao_driver_open = 0; } running_ticket->release(running_ticket, 0); - if( !stream->gapless_switch ) + if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) ) stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSTART, 0); buftype_unknown = 0; diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 7fe92d9fe..a6f83dc9d 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -215,6 +215,7 @@ typedef struct { int num_driver_actions; /* number of threads, that wish to call * functions needing driver_lock */ pthread_mutex_t driver_action_lock; /* protects num_driver_actions */ + pthread_cond_t driver_action_cond; /* informs about num_driver_actions-- */ metronom_clock_t *clock; xine_t *xine; @@ -243,6 +244,7 @@ typedef struct { audio_fifo_t *free_fifo; audio_fifo_t *out_fifo; int64_t last_audio_vpts; + pthread_mutex_t current_speed_lock; uint32_t current_speed; /* the current playback speed */ /* FIXME: replace all this->clock->speed with this->current_speed. we should make * sure nobody will change speed without going through xine.c:set_speed_internal */ @@ -287,13 +289,14 @@ struct audio_fifo_s { int num_buffers; }; +static int ao_get_property (xine_audio_port_t *this_gen, int property); static int ao_set_property (xine_audio_port_t *this_gen, int property, int value); -static audio_fifo_t *fifo_new (xine_t *xine) { +static audio_fifo_t *XINE_MALLOC fifo_new (xine_t *xine) { audio_fifo_t *fifo; - fifo = (audio_fifo_t *) xine_xmalloc (sizeof (audio_fifo_t)); + fifo = (audio_fifo_t *) calloc(1, sizeof(audio_fifo_t)); if (!fifo) return NULL; @@ -1039,6 +1042,7 @@ static void *ao_loop (void *this_gen) { * we must process/free buffers otherwise the entire engine will stop. */ + pthread_mutex_lock(&this->current_speed_lock); if ( this->audio_loop_running && (this->clock->speed == XINE_SPEED_PAUSE || (this->clock->speed != XINE_FINE_SPEED_NORMAL && @@ -1054,6 +1058,7 @@ static void *ao_loop (void *this_gen) { _x_refcounter_dec(in_buf->stream->refcounter); fifo_append (this->free_fifo, in_buf); in_buf = NULL; + pthread_mutex_unlock(&this->current_speed_lock); continue; } @@ -1064,6 +1069,7 @@ static void *ao_loop (void *this_gen) { } lprintf ("loop:pause: I feel sleepy (%d buffers).\n", this->out_fifo->num_buffers); + pthread_mutex_unlock(&this->current_speed_lock); xine_usec_sleep (10000); lprintf ("loop:pause: I wake up.\n"); continue; @@ -1273,12 +1279,20 @@ static void *ao_loop (void *this_gen) { fifo_append (this->free_fifo, in_buf); in_buf = NULL; } + pthread_mutex_unlock(&this->current_speed_lock); /* Give other threads a chance to use functions which require this->driver_lock to * be available. This is needed when using NPTL on Linux (and probably PThreads * on Solaris as well). */ - if (this->num_driver_actions > 0) - sched_yield(); + if (this->num_driver_actions > 0) { + /* calling sched_yield() is not sufficient on multicore systems */ + /* sched_yield(); */ + /* instead wait for the other thread to acquire this->driver_lock */ + pthread_mutex_lock(&this->driver_action_lock); + if (this->num_driver_actions > 0) + pthread_cond_wait(&this->driver_action_cond, &this->driver_action_lock); + pthread_mutex_unlock(&this->driver_action_lock); + } } if (in_buf) { @@ -1469,6 +1483,8 @@ static inline void dec_num_driver_actions(aos_t *this) { pthread_mutex_lock(&this->driver_action_lock); this->num_driver_actions--; + /* indicate the change to ao_loop() */ + pthread_cond_broadcast(&this->driver_action_cond); pthread_mutex_unlock(&this->driver_action_lock); } @@ -1608,17 +1624,21 @@ static void ao_close(xine_audio_port_t *this_gen, xine_stream_t *stream) { pthread_mutex_unlock(&this->streams_lock); /* close driver if no streams left */ - if (!ite && !this->grab_only && !stream->gapless_switch) { + if (!ite && !this->grab_only && !stream->keep_ao_driver_open) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_out: no streams left, closing driver\n"); if (this->audio_loop_running) { + /* make sure there are no more buffers on queue */ if (this->clock->speed == XINE_SPEED_PAUSE || (this->clock->speed != XINE_FINE_SPEED_NORMAL && !this->slow_fast_audio)) { - /* discard buffers, otherwise we'll wait forever */ + int discard = ao_get_property(this_gen, AO_PROP_DISCARD_BUFFERS); + /* discard buffers while waiting, otherwise we'll wait forever */ ao_set_property(this_gen, AO_PROP_DISCARD_BUFFERS, 1); + fifo_wait_empty(this->out_fifo); + ao_set_property(this_gen, AO_PROP_DISCARD_BUFFERS, discard); } - /* make sure there are no more buffers on queue */ - fifo_wait_empty(this->out_fifo); + else + fifo_wait_empty(this->out_fifo); } pthread_mutex_lock( &this->driver_lock ); @@ -1667,6 +1687,7 @@ static void ao_exit(xine_audio_port_t *this_gen) { } pthread_mutex_destroy(&this->driver_lock); + pthread_cond_destroy(&this->driver_action_cond); pthread_mutex_destroy(&this->driver_action_lock); pthread_mutex_destroy(&this->streams_lock); xine_list_delete(this->streams); @@ -1679,6 +1700,7 @@ static void ao_exit(xine_audio_port_t *this_gen) { free (this->frame_buf[1]); free (this->zero_space); + pthread_mutex_destroy(&this->current_speed_lock); pthread_mutex_destroy(&this->flush_audio_driver_lock); pthread_cond_destroy(&this->flush_audio_driver_reached); @@ -1905,8 +1927,15 @@ static int ao_set_property (xine_audio_port_t *this_gen, int property, int value if (value != XINE_FINE_SPEED_NORMAL && value != XINE_SPEED_PAUSE && !this->slow_fast_audio ) this->ao.control(&this->ao, AO_CTRL_FLUSH_BUFFERS, NULL); - this->ao.control(&this->ao, - (value == XINE_SPEED_PAUSE) ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME, NULL); + if( value == XINE_SPEED_PAUSE ) { + /* current_speed_lock is here to make sure the ao_loop will pause in a safe place. + * that is, we cannot pause writing to device, filling gaps etc. */ + pthread_mutex_lock(&this->current_speed_lock); + this->ao.control(&this->ao, AO_CTRL_PLAY_PAUSE, NULL); + pthread_mutex_unlock(&this->current_speed_lock); + } else { + this->ao.control(&this->ao, AO_CTRL_PLAY_RESUME, NULL); + } this->current_speed = value; if( this->slow_fast_audio ) ao_update_resample_factor(this); @@ -2046,11 +2075,12 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, static const char* resample_modes[] = {"auto", "off", "on", NULL}; static const char* av_sync_methods[] = {"metronom feedback", "resample", NULL}; - this = xine_xmalloc (sizeof (aos_t)) ; + this = calloc(1, sizeof(aos_t)) ; this->driver = driver; this->xine = xine; this->clock = xine->clock; + this->current_speed = xine->clock->speed; this->streams = xine_list_new(); /* warning: driver_lock is a recursive mutex. it must NOT be @@ -2062,6 +2092,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, pthread_mutex_init( &this->streams_lock, NULL ); pthread_mutex_init( &this->driver_lock, &attr ); pthread_mutex_init( &this->driver_action_lock, NULL ); + pthread_cond_init( &this->driver_action_cond, NULL ); this->ao.open = ao_open; this->ao.get_buffer = ao_get_buffer; @@ -2080,8 +2111,9 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, this->grab_only = grab_only; this->flush_audio_driver = 0; this->discard_buffers = 0; - this->zero_space = xine_xmalloc (ZERO_BUF_SIZE * 4 * 6); /* MAX as 32bit, 6 channels. */ + this->zero_space = calloc (1, ZERO_BUF_SIZE * 4 * 6); /* MAX as 32bit, 6 channels. */ + pthread_mutex_init( &this->current_speed_lock, NULL ); pthread_mutex_init( &this->flush_audio_driver_lock, NULL ); pthread_cond_init( &this->flush_audio_driver_reached, NULL ); @@ -2191,8 +2223,8 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, audio_buffer_t *buf; - buf = (audio_buffer_t *) xine_xmalloc (sizeof (audio_buffer_t)); - buf->mem = xine_xmalloc (AUDIO_BUF_SIZE); + buf = (audio_buffer_t *) calloc(1, sizeof(audio_buffer_t)); + buf->mem = calloc (1, AUDIO_BUF_SIZE); buf->mem_size = AUDIO_BUF_SIZE; buf->extra_info = malloc(sizeof(extra_info_t)); @@ -2206,8 +2238,8 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, audio_buffer_t *buf; - buf = (audio_buffer_t *) xine_xmalloc (sizeof (audio_buffer_t)); - buf->mem = xine_xmalloc (4*AUDIO_BUF_SIZE); + buf = (audio_buffer_t *) calloc(1, sizeof(audio_buffer_t)); + buf->mem = calloc(4, AUDIO_BUF_SIZE); buf->mem_size = 4*AUDIO_BUF_SIZE; buf->extra_info = malloc(sizeof(extra_info_t)); diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h index c4581ec24..5f4420363 100644 --- a/src/xine-engine/audio_out.h +++ b/src/xine-engine/audio_out.h @@ -259,7 +259,7 @@ struct audio_driver_class_s { * this initiates the audio_out sync routines * found in ./src/xine-engine/audio_out.c */ -xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, int grab_only) XINE_PROTECTED; +xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, int grab_only) XINE_MALLOC XINE_PROTECTED; /* * audio output modes + capabilities diff --git a/src/xine-engine/broadcaster.c b/src/xine-engine/broadcaster.c index 1d2f01366..81711de49 100644 --- a/src/xine-engine/broadcaster.c +++ b/src/xine-engine/broadcaster.c @@ -32,6 +32,10 @@ * 'xine -V none -A none' */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -323,7 +327,7 @@ broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) signal( SIGPIPE, SIG_IGN ); - this = xine_xmalloc(sizeof(broadcaster_t)); + this = calloc(1, sizeof(broadcaster_t)); this->port = port; this->stream = stream; this->msock = msock; diff --git a/src/xine-engine/broadcaster.h b/src/xine-engine/broadcaster.h index 093fb4af0..b59d33349 100644 --- a/src/xine-engine/broadcaster.h +++ b/src/xine-engine/broadcaster.h @@ -27,13 +27,9 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - typedef struct broadcaster_s broadcaster_t; -broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) XINE_PROTECTED; +broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) XINE_MALLOC XINE_PROTECTED; void _x_close_broadcaster(broadcaster_t *this) XINE_PROTECTED; int _x_get_broadcaster_port(broadcaster_t *this) XINE_PROTECTED; diff --git a/src/xine-engine/buffer.c b/src/xine-engine/buffer.c index 93ad75ba0..417fee745 100644 --- a/src/xine-engine/buffer.c +++ b/src/xine-engine/buffer.c @@ -500,7 +500,7 @@ fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) { int alignment = 2048; unsigned char *multi_buffer = NULL; - this = xine_xmalloc (sizeof (fifo_buffer_t)); + this = calloc(1, sizeof(fifo_buffer_t)); this->first = NULL; this->last = NULL; @@ -551,7 +551,7 @@ fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) { for (i = 0; i<num_buffers; i++) { buf_element_t *buf; - buf = xine_xmalloc (sizeof (buf_element_t)); + buf = calloc(1, sizeof(buf_element_t)); buf->mem = multi_buffer; multi_buffer += buf_size; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index 3a3f06e9b..6928ebd96 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -35,10 +35,7 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - +#include <string.h> #include <stdio.h> #include <pthread.h> #include <sys/types.h> @@ -191,6 +188,7 @@ extern "C" { #define BUF_VIDEO_THEORA_RAW 0x02640000 #define BUF_VIDEO_VC1 0x02650000 #define BUF_VIDEO_VMNC 0x02660000 +#define BUF_VIDEO_SNOW 0x02670000 /* audio buffer types: (please keep in sync with buffer_types.c) */ @@ -258,6 +256,9 @@ extern "C" { #define BUF_AUDIO_SMACKER 0x033B0000 #define BUF_AUDIO_FLVADPCM 0x033C0000 #define BUF_AUDIO_WAVPACK 0x033D0000 +#define BUF_AUDIO_MP3ADU 0x033E0000 +#define BUF_AUDIO_AMR_NB 0x033F0000 +#define BUF_AUDIO_AMR_WB 0x03400000 /* spu buffer types: */ @@ -373,13 +374,16 @@ struct buf_element_s { * decoder_info[2] carries denominator for display aspect ratio */ #define BUF_FLAG_ASPECT 0x0800 +/* represent the state of gapless_switch at the time buf was enqueued */ +#define BUF_FLAG_GAPLESS_SW 0x1000 + /* Amount of audio padding added by encoder (mp3, aac). These empty * audio frames are causing a gap when switching between mp3 files. * decoder_info[1] carries amount of audio frames padded at the * beginning of the buffer * decoder_info[2] carries amount of audio frames padded at the end of * the buffer */ -#define BUF_FLAG_AUDIO_PADDING 0x1000 +#define BUF_FLAG_AUDIO_PADDING 0x2000 /* Special buffer types: * Sometimes there is a need to relay special information from a demuxer @@ -613,8 +617,8 @@ struct fifo_buffer_s * allocate num_buffers of buf_size bytes each */ -fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_PROTECTED; -fifo_buffer_t *_x_dummy_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_PROTECTED; +fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_MALLOC XINE_PROTECTED; +fifo_buffer_t *_x_dummy_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_MALLOC XINE_PROTECTED; /* return BUF_VIDEO_xxx given the fourcc @@ -624,16 +628,16 @@ fifo_buffer_t *_x_dummy_fifo_buffer_new (int num_buffers, uint32_t buf_size) XIN uint32_t _x_fourcc_to_buf_video( uint32_t fourcc_int ) XINE_PROTECTED; /* return codec name given BUF_VIDEO_xxx */ -char * _x_buf_video_name( uint32_t buf_type ) XINE_PROTECTED; +const char * _x_buf_video_name( uint32_t buf_type ) XINE_PROTECTED; /* return BUF_AUDIO_xxx given the formattag */ uint32_t _x_formattag_to_buf_audio( uint32_t formattag ) XINE_PROTECTED; /* return codec name given BUF_AUDIO_xxx */ -char * _x_buf_audio_name( uint32_t buf_type ) XINE_PROTECTED; +const char * _x_buf_audio_name( uint32_t buf_type ) XINE_PROTECTED; -#ifndef ATTRIBUTE_PACKED +#ifndef SUPPORT_ATTRIBUTE_PACKED /* no attribute packed? let's try with pragma pack as a last resort */ #pragma pack(2) #endif @@ -642,7 +646,7 @@ char * _x_buf_audio_name( uint32_t buf_type ) XINE_PROTECTED; * - will always use machine endian format, so demuxers reading * stuff from win32 formats must use the function below. */ -typedef struct __attribute__((__packed__)) { +typedef struct XINE_PACKED { int32_t biSize; int32_t biWidth; int32_t biHeight; @@ -659,7 +663,7 @@ typedef struct __attribute__((__packed__)) { /* this is xine version of WAVEFORMATEX * (the same comments from xine_bmiheader) */ -typedef struct __attribute__((__packed__)) { +typedef struct XINE_PACKED { int16_t wFormatTag; int16_t nChannels; int32_t nSamplesPerSec; @@ -668,7 +672,7 @@ typedef struct __attribute__((__packed__)) { int16_t wBitsPerSample; int16_t cbSize; } xine_waveformatex; -#ifndef ATTRIBUTE_PACKED +#ifndef SUPPORT_ATTRIBUTE_PACKED #pragma pack() #endif @@ -678,6 +682,10 @@ void _x_bmiheader_le2me( xine_bmiheader *bih ) XINE_PROTECTED; /* convert xine_waveformatex struct from little endian */ void _x_waveformatex_le2me( xine_waveformatex *wavex ) XINE_PROTECTED; +static __inline int _x_is_fourcc(void *ptr, void *tag) { + return memcmp(ptr, tag, 4) == 0; +} + #ifdef __cplusplus } #endif diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c index 7242738e1..b7571d1d7 100644 --- a/src/xine-engine/buffer_types.c +++ b/src/xine-engine/buffer_types.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2005 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -659,6 +659,8 @@ static const video_db_t video_db[] = { ME_FOURCC('a','v','c','1'), ME_FOURCC('h','2','6','4'), ME_FOURCC('H','2','6','4'), + ME_FOURCC('x','2','6','4'), + ME_FOURCC('X','2','6','4'), 0 }, BUF_VIDEO_H264, @@ -779,6 +781,14 @@ static const video_db_t video_db[] = { BUF_VIDEO_VMNC, "VMware Screen Codec" }, +{ + { + ME_FOURCC('S','N','O','W'), + 0 + }, + BUF_VIDEO_SNOW, + "Snow" +}, { { 0 }, 0, "last entry" } }; @@ -806,6 +816,14 @@ static const audio_db_t audio_db[] = { }, { { + ME_FOURCC('a', 'd', 'u', 0x55), + 0 + }, + BUF_AUDIO_MP3ADU, + "MPEG layer-3 adu" +}, +{ + { ME_FOURCC('t','w','o','s'), ME_FOURCC('i','n','2','4'), 0 @@ -1132,11 +1150,32 @@ static const audio_db_t audio_db[] = { }, { { - 0 + ME_FOURCC('W', 'V', 'P', 'K'), }, BUF_AUDIO_WAVPACK, "Wavpack" }, +{ + { + ME_FOURCC('s', 'a', 'm', 'r'), + }, + BUF_AUDIO_AMR_NB, + "AMR narrow band" +}, +{ + { + ME_FOURCC('s', 'a', 'w', 'b'), + }, + BUF_AUDIO_AMR_WB, + "AMR wide band" +}, +{ + { + ME_FOURCC('T', 'T', 'A', '1'), + }, + BUF_AUDIO_TTA, + "True Audio Lossless" +}, { { 0 }, 0, "last entry" } }; @@ -1161,7 +1200,7 @@ static uint32_t cached_buf_type=0; return 0; } -char * _x_buf_video_name( uint32_t buf_type ) { +const char * _x_buf_video_name( uint32_t buf_type ) { int i; buf_type &= 0xffff0000; @@ -1195,7 +1234,7 @@ static uint32_t cached_buf_type=0; return 0; } -char * _x_buf_audio_name( uint32_t buf_type ) { +const char * _x_buf_audio_name( uint32_t buf_type ) { int i; buf_type &= 0xffff0000; diff --git a/src/xine-engine/configfile.c b/src/xine-engine/configfile.c index 2dc89f0af..81acab348 100644 --- a/src/xine-engine/configfile.c +++ b/src/xine-engine/configfile.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -319,11 +319,11 @@ static void config_insert(config_values_t *this, cfg_entry_t *new_entry) { this->first = new_entry; } -static cfg_entry_t *config_add (config_values_t *this, const char *key, int exp_level) { +static cfg_entry_t *XINE_MALLOC config_add (config_values_t *this, const char *key, int exp_level) { cfg_entry_t *entry; - entry = (cfg_entry_t *) xine_xmalloc (sizeof (cfg_entry_t)); + entry = calloc (1, sizeof (cfg_entry_t)); entry->config = this; entry->key = strdup(key); entry->type = XINE_CONFIG_TYPE_UNKNOWN; @@ -356,22 +356,22 @@ static const char *config_xlate_internal (const char *key, const xine_config_ent return NULL; } -static const char *config_translate_key (const char *key) { +static const char *config_translate_key (const char *key, char **tmp) { /* Returns translated key or, if no translation found, NULL. * Translated key may be in a static buffer allocated within this function. * NOT re-entrant; assumes that config_lock is held. */ unsigned trans; - static char *newkey = NULL; + const char *newkey = NULL; /* first, special-case the decoder entries (so that new ones can be added * without requiring modification of the translation table) */ + *tmp = NULL; if (!strncmp (key, "decoder.", 8) && !strcmp (key + (trans = strlen (key)) - 9, "_priority")) { - newkey = realloc (newkey, trans + 27 - 17); /* diff. in string lengths */ - sprintf (newkey, "engine.decoder_priorities.%.*s", trans - 17, key + 8); - return newkey; + asprintf (tmp, "engine.decoder_priorities.%.*s", trans - 17, key + 8); + return *tmp; } /* search the translation table... */ @@ -386,6 +386,7 @@ static void config_lookup_entry_int (config_values_t *this, const char *key, cfg_entry_t **entry, cfg_entry_t **prev) { int trans; + char *tmp = NULL; /* try twice at most (second time with translation from old key name) */ for (trans = 2; trans; --trans) { @@ -397,14 +398,18 @@ static void config_lookup_entry_int (config_values_t *this, const char *key, *entry = (*entry)->next; } - if (*entry) + if (*entry) { + free(tmp); return; + } /* we did not find a match, maybe this is an old config entry name * trying to translate */ - key = config_translate_key(key); - if (!key) + key = config_translate_key(key, &tmp); + if (!key) { + free(tmp); return; + } } } @@ -748,7 +753,7 @@ static int config_register_enum (config_values_t *this, entry->type = XINE_CONFIG_TYPE_ENUM; if (entry->unknown_value) - entry->num_value = config_parse_enum (entry->unknown_value, values); + entry->num_value = config_parse_enum (entry->unknown_value, (const char **)values); else entry->num_value = def_value; @@ -756,14 +761,14 @@ static int config_register_enum (config_values_t *this, entry->num_default = def_value; /* allocate and copy the enum values */ - value_src = values; + value_src = (const char **)values; value_count = 0; while (*value_src) { value_src++; value_count++; } entry->enum_values = malloc (sizeof(char*) * (value_count + 1)); - value_src = values; + value_src = (const char **)values; value_dest = entry->enum_values; while (*value_src) { *value_dest = strdup(*value_src); @@ -862,7 +867,7 @@ static void config_update_string (config_values_t *this, /* if an enum is updated with a string, we convert the string to * its index and use update number */ if (entry->type == XINE_CONFIG_TYPE_ENUM) { - config_update_num(this, key, config_parse_enum(value, entry->enum_values)); + config_update_num(this, key, config_parse_enum(value, (const char **)entry->enum_values)); return; } @@ -944,15 +949,17 @@ void xine_config_load (xine_t *xine, const char *filename) { if (!(entry = config_lookup_entry(this, line))) { const char *key = line; + char *tmp = NULL; pthread_mutex_lock(&this->config_lock); if (this->current_version < CONFIG_FILE_VERSION) { /* old config file -> let's see if we have to rename this one */ - key = config_translate_key(key); + key = config_translate_key(key, &tmp); if (!key) key = line; /* no translation? fall back on untranslated key */ } entry = config_add (this, key, 50); entry->unknown_value = strdup(value); + free(tmp); pthread_mutex_unlock(&this->config_lock); } else { switch (entry->type) { @@ -1005,7 +1012,7 @@ void xine_config_save (xine_t *xine, const char *filename) { char *buf = NULL; size_t rlen; - buf = (char *) xine_xmalloc(config_stat.st_size + 1); + buf = (char *) malloc(config_stat.st_size + 1); if((rlen = fread(buf, 1, config_stat.st_size, f_config)) && ((off_t)rlen == config_stat.st_size)) { (void) fwrite(buf, 1, rlen, f_backup); } @@ -1204,7 +1211,7 @@ config_values_t *_x_config_init (void) { config_values_t *this; pthread_mutexattr_t attr; - if (!(this = xine_xmalloc(sizeof(config_values_t)))) { + if (!(this = calloc(1, sizeof(config_values_t)))) { printf ("configfile: could not allocate config object\n"); _x_abort(); diff --git a/src/xine-engine/configfile.h b/src/xine-engine/configfile.h index e21b08db0..e1dca7b18 100644 --- a/src/xine-engine/configfile.h +++ b/src/xine-engine/configfile.h @@ -200,7 +200,7 @@ struct config_values_s { /* * allocate and init a new xine config object */ -config_values_t *_x_config_init (void) XINE_PROTECTED; +config_values_t *_x_config_init (void) XINE_MALLOC XINE_PROTECTED; /* * interpret stream_setup part of mrls for config value changes diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c index f33397256..698b44988 100644 --- a/src/xine-engine/demux.c +++ b/src/xine-engine/demux.c @@ -21,6 +21,9 @@ * hide some xine engine details from demuxers and reduce code duplication */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include <stdio.h> #include <string.h> @@ -47,11 +50,6 @@ #include <winsock.h> #endif -#ifdef MIN -#undef MIN -#endif -#define MIN(a,b) ( (a) < (b) ) ? (a) : (b) - /* * Flush audio and video buffers. It is called from demuxers on * seek/stop, and may be useful when user input changes a stream and @@ -122,6 +120,16 @@ void _x_demux_flush_engine (xine_stream_t *stream) { } +static struct timespec _x_compute_interval(unsigned int millisecs) { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + uint64_t ttimer = (uint64_t)ts.tv_sec*1000 + ts.tv_nsec/1000000 + millisecs; + ts.tv_sec = ttimer/1000; + ts.tv_nsec = (ttimer%1000)*1000000; + return ts; +} + + void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags ) { buf_element_t *buf; @@ -143,6 +151,29 @@ void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags pthread_mutex_unlock(&stream->demux_mutex); } +/* avoid ao_loop being stuck in a pthread_cond_wait, waiting for data; + * return 1 if the stream is stopped + * (better fix wanted!) + */ +static int demux_unstick_ao_loop (xine_stream_t *stream) +{ +/* if (!stream->audio_thread_created) + return 0; +*/ + int status = xine_get_status (stream); + if (status != XINE_STATUS_QUIT && status != XINE_STATUS_STOP && stream->demux_plugin->get_status(stream->demux_plugin) != DEMUX_FINISHED) + return 0; +#if 0 + /* right, stream is stopped... */ + audio_buffer_t *buf = stream->audio_out->get_buffer (stream->audio_out); + buf->num_frames = 0; + buf->stream = NULL; + stream->audio_out->put_buffer (stream->audio_out, buf, stream); +#endif + lprintf("stuck\n"); + return 1; +} + /* sync with decoder fifos, making sure everything gets processed */ void _x_demux_control_headers_done (xine_stream_t *stream) { @@ -180,24 +211,31 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { stream->audio_fifo->put (stream->audio_fifo, buf_audio); pthread_mutex_unlock(&stream->demux_mutex); + unsigned int max_iterations = 0; while ((stream->header_count_audio < header_count_audio) || (stream->header_count_video < header_count_video)) { - struct timeval tv; - struct timespec ts; lprintf ("waiting for headers. v:%d %d a:%d %d\n", stream->header_count_video, header_count_video, stream->header_count_audio, header_count_audio); + + struct timespec ts = _x_compute_interval(1000); + int ret_wait; - gettimeofday(&tv, NULL); - ts.tv_sec = tv.tv_sec + 1; - ts.tv_nsec = tv.tv_usec * 1000; /* use timedwait to workaround buggy pthread broadcast implementations */ - pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + + if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) { + xine_log(stream->xine, + XINE_LOG_MSG,_("Stuck in _x_demux_control_headers_done(). Taking the emergency exit\n")); + stream->emergency_brake = 1; + break; + } } stream->demux_action_pending = 0; + pthread_cond_signal(&stream->demux_resume); lprintf ("headers processed.\n"); @@ -207,15 +245,18 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { void _x_demux_control_start( xine_stream_t *stream ) { buf_element_t *buf; + uint32_t flags = (stream->gapless_switch) ? BUF_FLAG_GAPLESS_SW : 0; pthread_mutex_lock(&stream->demux_mutex); buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_START; + buf->decoder_flags = flags; stream->video_fifo->put (stream->video_fifo, buf); buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_START; + buf->decoder_flags = flags; stream->audio_fifo->put (stream->audio_fifo, buf); pthread_mutex_unlock(&stream->demux_mutex); @@ -284,12 +325,14 @@ static void *demux_loop (void *stream_gen) { /* someone may want to interrupt us */ if( stream->demux_action_pending ) { - pthread_mutex_unlock( &stream->demux_lock ); - - lprintf ("sched_yield\n"); + struct timeval tv; + struct timespec ts; - sched_yield(); - pthread_mutex_lock( &stream->demux_lock ); + gettimeofday(&tv, NULL); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = (tv.tv_usec + 100000) * 1000; + + pthread_cond_timedwait (&stream->demux_resume, &stream->demux_lock, &ts); } } @@ -345,10 +388,21 @@ static void *demux_loop (void *stream_gen) { pthread_mutex_unlock( &stream->demux_lock ); pthread_mutex_lock (&stream->counter_lock); + struct timespec ts; + unsigned int max_iterations = 0; + int ret_wait; while ((stream->finished_count_audio < finished_count_audio) || (stream->finished_count_video < finished_count_video)) { lprintf ("waiting for finisheds.\n"); - pthread_cond_wait (&stream->counter_changed, &stream->counter_lock); + ts = _x_compute_interval(1000); + ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + + if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) { + xine_log(stream->xine, + XINE_LOG_MSG,_("Stuck in demux_loop(). Taking the emergency exit\n")); + stream->emergency_brake = 1; + break; + } } pthread_mutex_unlock (&stream->counter_lock); @@ -365,6 +419,7 @@ int _x_demux_start_thread (xine_stream_t *stream) { stream->demux_action_pending = 1; pthread_mutex_lock( &stream->demux_lock ); stream->demux_action_pending = 0; + pthread_cond_signal(&stream->demux_resume); if( !stream->demux_thread_running ) { @@ -396,6 +451,7 @@ int _x_demux_stop_thread (xine_stream_t *stream) { pthread_mutex_lock( &stream->demux_lock ); stream->demux_thread_running = 0; stream->demux_action_pending = 0; + pthread_cond_signal(&stream->demux_resume); /* At that point, the demuxer has sent the last audio/video buffer, * so it's a safe place to flush the engine. @@ -435,7 +491,7 @@ int _x_demux_read_header( input_plugin_t *input, unsigned char *buffer, off_t si read_size = input->read(input, buffer, size); input->seek(input, 0, SEEK_SET); } else if (input->get_capabilities(input) & INPUT_CAP_PREVIEW) { - buf = xine_xmalloc(MAX_PREVIEW_SIZE); + buf = malloc(MAX_PREVIEW_SIZE); read_size = input->get_optional_data(input, buf, INPUT_OPTIONAL_DATA_PREVIEW); read_size = MIN (read_size, size); memcpy(buffer, buf, read_size); @@ -652,7 +708,7 @@ void _x_demux_send_mrl_reference (xine_stream_t *stream, int alternative, xine_mrl_reference_data_ext_t *e; xine_mrl_reference_data_t *b; } data; - int mrl_len = strlen (mrl); + const size_t mrl_len = strlen (mrl); if (!title) title = ""; diff --git a/src/xine-engine/info_helper.c b/src/xine-engine/info_helper.c index 1ac4ed982..6ce9bcd38 100644 --- a/src/xine-engine/info_helper.c +++ b/src/xine-engine/info_helper.c @@ -131,7 +131,7 @@ uint32_t _x_stream_info_get_public(xine_stream_t *stream, int info) { * at the end of the string */ static void meta_info_chomp(char *str) { - int i, len; + ssize_t i, len; len = strlen(str); if (!len) @@ -251,7 +251,15 @@ static void meta_info_set_unlocked_encoding(xine_stream_t *stream, int info, con size_t inbytesleft, outbytesleft; inbuf = (ICONV_CONST char *)value; - inbytesleft = strlen(value); + if (!strncmp (enc, "UTF-16", 6) || !strncmp (enc, "UCS-2", 5)) + { + /* strlen() won't work with UTF-16* or UCS-2* */ + inbytesleft = 0; + while (value[inbytesleft] || value[inbytesleft + 1]) + inbytesleft += 2; + } /* ... do we need to handle UCS-4? Probably not. */ + else + inbytesleft = strlen(value); outbytesleft = 4 * inbytesleft; /* estimative (max) */ outbuf = utf8_value = malloc(outbytesleft+1); @@ -340,11 +348,10 @@ void _x_meta_info_set_utf8(xine_stream_t *stream, int info, const char *str) { void _x_meta_info_n_set(xine_stream_t *stream, int info, const char *buf, int len) { pthread_mutex_lock(&stream->meta_mutex); if(meta_valid(info) && len) { - char *str = xine_xmalloc(len + 1); + char *str = strndup(buf, len); - snprintf(str, len + 1 , "%s", buf); - meta_info_set_unlocked(stream, info, (const char *) &str[0]); - free(str); + meta_info_set_unlocked(stream, info, str); + free(str); } pthread_mutex_unlock(&stream->meta_mutex); } @@ -359,7 +366,7 @@ void _x_meta_info_set_multi(xine_stream_t *stream, int info, ...) { va_list ap; char *args[1025]; char *buf; - int n, len; + size_t n, len; len = n = 0; @@ -376,7 +383,7 @@ void _x_meta_info_set_multi(xine_stream_t *stream, int info, ...) { if(len) { char *p, *meta; - p = meta = (char *) xine_xmalloc(len + 1); + p = meta = (char *) malloc(len + 1); n = 0; while(args[n]) { diff --git a/src/xine-engine/input_cache.c b/src/xine-engine/input_cache.c index 30b1ba4aa..4eb524af6 100644 --- a/src/xine-engine/input_cache.c +++ b/src/xine-engine/input_cache.c @@ -356,7 +356,7 @@ input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahe lprintf("mrl: %s\n", main_plugin->get_mrl(main_plugin)); - this = (cache_input_plugin_t *)xine_xmalloc(sizeof(cache_input_plugin_t)); + this = calloc(1, sizeof(cache_input_plugin_t)); if (!this) return NULL; @@ -386,7 +386,7 @@ input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahe this->buf_size = DEFAULT_BUFFER_SIZE; } - this->buf = (char *)xine_xmalloc(this->buf_size); + this->buf = calloc(1, this->buf_size); if (!this->buf) { free (this); return NULL; diff --git a/src/xine-engine/input_rip.c b/src/xine-engine/input_rip.c index 0c185aa1b..8db7eaaf5 100644 --- a/src/xine-engine/input_rip.c +++ b/src/xine-engine/input_rip.c @@ -517,10 +517,9 @@ static void rip_plugin_dispose(input_plugin_t *this_gen) { * returns non-zero, if there was enough space */ static int dir_file_concat(char *target, size_t maxlen, const char *dir, const char *name) { - size_t len_dir, len_name, pos_name = 0; - - len_name = strlen(name); - len_dir = strlen(dir); + size_t len_name = strlen(name); + size_t len_dir = strlen(dir); + size_t pos_name = 0; /* remove slashes */ if (dir[len_dir - 1] == '/') len_dir--; @@ -585,7 +584,7 @@ input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *f return NULL; } - this = (rip_input_plugin_t *)xine_xmalloc(sizeof(rip_input_plugin_t)); + this = calloc(1, sizeof(rip_input_plugin_t)); this->main_input_plugin = main_plugin; this->stream = stream; this->curpos = 0; diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 71cb19d3b..5128644da 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2006 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -313,7 +313,6 @@ static void _insert_node (xine_t *this, const input_info_t *input_old; uint32_t *types; char key[80]; - char desc[100]; int i; _x_assert(list); @@ -325,8 +324,8 @@ static void _insert_node (xine_t *this, return; } - entry = xine_xmalloc(sizeof(plugin_node_t)); - entry->info = xine_xmalloc(sizeof(plugin_info_t)); + entry = calloc(1, sizeof(plugin_node_t)); + entry->info = calloc(1, sizeof(plugin_info_t)); *(entry->info) = *info; entry->info->id = strdup(info->id); entry->info->init = info->init; @@ -339,7 +338,7 @@ static void _insert_node (xine_t *this, case PLUGIN_VIDEO_OUT: vo_old = info->special_info; - vo_new = xine_xmalloc(sizeof(vo_info_t)); + vo_new = calloc(1, sizeof(vo_info_t)); entry->priority = vo_new->priority = vo_old->priority; vo_new->visual_type = vo_old->visual_type; entry->info->special_info = vo_new; @@ -347,7 +346,7 @@ static void _insert_node (xine_t *this, case PLUGIN_AUDIO_OUT: ao_old = info->special_info; - ao_new = xine_xmalloc(sizeof(ao_info_t)); + ao_new = calloc(1, sizeof(ao_info_t)); entry->priority = ao_new->priority = ao_old->priority; entry->info->special_info = ao_new; break; @@ -356,7 +355,7 @@ static void _insert_node (xine_t *this, case PLUGIN_VIDEO_DECODER: case PLUGIN_SPU_DECODER: decoder_old = info->special_info; - decoder_new = xine_xmalloc(sizeof(decoder_info_t)); + decoder_new = calloc(1, sizeof(decoder_info_t)); if (decoder_old == NULL) { if (file) xprintf (this, XINE_VERBOSITY_DEBUG, @@ -368,22 +367,21 @@ static void _insert_node (xine_t *this, info->id); _x_abort(); } - for (i=0; decoder_old->supported_types[i] != 0; ++i); - types = xine_xmalloc((i+1)*sizeof(uint32_t)); - for (i=0; decoder_old->supported_types[i] != 0; ++i){ - types[i] = decoder_old->supported_types[i]; + { + size_t supported_types_size; + for (supported_types_size=0; decoder_old->supported_types[supported_types_size] != 0; ++supported_types_size); + types = calloc((supported_types_size+1), sizeof(uint32_t)); + memcpy(types, decoder_old->supported_types, supported_types_size*sizeof(uint32_t)); + decoder_new->supported_types = types; } - decoder_new->supported_types = types; entry->priority = decoder_new->priority = decoder_old->priority; snprintf(key, sizeof(key), "engine.decoder_priorities.%s", info->id); - snprintf(desc, sizeof(desc), _("priority for %s decoder"), info->id); /* write the description on the heap because the config system * does not strdup() it, so we have to provide a different pointer * for each decoder */ for (i = 0; catalog->prio_desc[i]; i++); - catalog->prio_desc[i] = malloc(strlen(desc) + 1); - strcpy(catalog->prio_desc[i], desc); + asprintf(&catalog->prio_desc[i], _("priority for %s decoder"), info->id); this->config->register_num (this->config, key, 0, @@ -402,14 +400,14 @@ static void _insert_node (xine_t *this, case PLUGIN_POST: post_old = info->special_info; - post_new = xine_xmalloc(sizeof(post_info_t)); + post_new = calloc(1, sizeof(post_info_t)); post_new->type = post_old->type; entry->info->special_info = post_new; break; case PLUGIN_DEMUX: demux_old = info->special_info; - demux_new = xine_xmalloc(sizeof(demuxer_info_t)); + demux_new = calloc(1, sizeof(demuxer_info_t)); if (demux_old) { entry->priority = demux_new->priority = demux_old->priority; @@ -426,7 +424,7 @@ static void _insert_node (xine_t *this, case PLUGIN_INPUT: input_old = info->special_info; - input_new = xine_xmalloc(sizeof(input_info_t)); + input_new = calloc(1, sizeof(input_info_t)); if (input_old) { entry->priority = input_new->priority = input_old->priority; @@ -463,12 +461,12 @@ static int _plugin_node_comparator(void *a, void *b) { } } -static plugin_catalog_t *_new_catalog(void){ +static plugin_catalog_t *XINE_MALLOC _new_catalog(void){ plugin_catalog_t *catalog; int i; - catalog = xine_xmalloc(sizeof(plugin_catalog_t)); + catalog = calloc(1, sizeof(plugin_catalog_t)); for (i = 0; i < PLUGIN_TYPE_MAX; i++) { catalog->plugin_lists[i] = xine_sarray_new(0, _plugin_node_comparator); @@ -487,7 +485,7 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin while ( info && info->type != PLUGIN_NONE ) { - if (file) + if (file && file->filename) xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: plugin %s found\n"), file->filename); else @@ -556,25 +554,20 @@ static void collect_plugins(xine_t *this, char *path){ dir = opendir(path); if (dir) { struct dirent *pEntry; - size_t path_len, str_size; - char *str = NULL; - path_len = strlen(path); - str_size = path_len * 2 + 2; /* +2 for '/' and '\0' */ - str = malloc(str_size); - xine_fast_memcpy(str, path, path_len); - str[path_len] = '/'; - str[path_len + 1] = '\0'; + size_t path_len = strlen(path); + size_t str_size = path_len * 2 + 2; /* +2 for '/' and '\0' */ + char *str = malloc(str_size); + sprintf(str, "%s/", path); while ((pEntry = readdir (dir)) != NULL) { - size_t new_str_size, d_len; void *lib = NULL; plugin_info_t *info = NULL; struct stat statbuffer; - d_len = strlen(pEntry->d_name); - new_str_size = path_len + d_len + 2; + size_t d_len = strlen(pEntry->d_name); + size_t new_str_size = path_len + d_len + 2; if (str_size < new_str_size) { str_size = new_str_size + new_str_size / 2; str = realloc(str, str_size); @@ -599,7 +592,7 @@ static void collect_plugins(xine_t *this, char *path){ #if defined(__hpux) if(!strstr(str, ".sl") #elif defined(__CYGWIN__) || defined(WIN32) - if(!strstr(str, ".dll") + if(!strstr(str, ".dll") || strstr(str, ".dll.a") #else if(!strstr(str, ".so") #endif @@ -941,11 +934,11 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { if( node ) { xine_sarray_add (plugins, node); } - node = xine_xmalloc(sizeof(plugin_node_t)); - file = xine_xmalloc(sizeof(plugin_file_t)); + node = calloc(1, sizeof(plugin_node_t)); + file = calloc(1, sizeof(plugin_file_t)); node->file = file; file->filename = strdup(line+1); - node->info = xine_xmalloc(2*sizeof(plugin_info_t)); + node->info = calloc(2, sizeof(plugin_info_t)); node->info[1].type = PLUGIN_NONE; decoder_info = NULL; vo_info = NULL; @@ -981,34 +974,34 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { case PLUGIN_VIDEO_OUT: node->info->special_info = vo_info = - xine_xmalloc(sizeof(vo_info_t)); + calloc(1, sizeof(vo_info_t)); break; case PLUGIN_AUDIO_OUT: node->info->special_info = ao_info = - xine_xmalloc(sizeof(ao_info_t)); + calloc(1, sizeof(ao_info_t)); break; case PLUGIN_DEMUX: node->info->special_info = demuxer_info = - xine_xmalloc(sizeof(demuxer_info_t)); + calloc(1, sizeof(demuxer_info_t)); break; case PLUGIN_INPUT: node->info->special_info = input_info = - xine_xmalloc(sizeof(input_info_t)); + calloc(1, sizeof(input_info_t)); break; case PLUGIN_AUDIO_DECODER: case PLUGIN_VIDEO_DECODER: case PLUGIN_SPU_DECODER: node->info->special_info = decoder_info = - xine_xmalloc(sizeof(decoder_info_t)); + calloc(1, sizeof(decoder_info_t)); break; case PLUGIN_POST: node->info->special_info = post_info = - xine_xmalloc(sizeof(post_info_t)); + calloc(1, sizeof(post_info_t)); break; } @@ -1029,7 +1022,7 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { for( s = value, i = 0; s && sscanf(s," %lu",&lu) > 0; i++ ) { s = strchr(s+1, ' '); } - decoder_info->supported_types = xine_xmalloc((i+1)*sizeof(uint32_t)); + decoder_info->supported_types = calloc((i+1), sizeof(uint32_t)); for( s = value, i = 0; s && sscanf(s," %lu",&lu) > 0; i++ ) { decoder_info->supported_types[i] = lu; s = strchr(s+1, ' '); @@ -1069,22 +1062,21 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { static void save_catalog (xine_t *this) { FILE *fp; - char *cachefile, *dirfile; + char *cachefile, *cachefile_new, *dirfile; const char *relname = CACHE_CATALOG_FILE; const char *dirname = CACHE_CATALOG_DIR; + + const char *const homedir = xine_get_homedir(); - cachefile = (char *) xine_xmalloc(strlen(xine_get_homedir()) + - strlen(relname) + 2); - sprintf(cachefile, "%s/%s", xine_get_homedir(), relname); + asprintf(&cachefile, "%s/%s", homedir, relname); + asprintf(&cachefile_new, "%s.new", cachefile); /* make sure homedir (~/.xine) exists */ - dirfile = (char *) xine_xmalloc(strlen(xine_get_homedir()) + - strlen(dirname) + 2); - sprintf(dirfile, "%s/%s", xine_get_homedir(), dirname); + asprintf(&dirfile, "%s/%s", homedir, dirname); mkdir (dirfile, 0755); free (dirfile); - if( (fp = fopen(cachefile,"w")) != NULL ) { + if( (fp = fopen(cachefile_new,"w")) != NULL ) { int i; fprintf(fp, "# this file is automatically created by xine, do not edit.\n\n"); @@ -1093,9 +1085,29 @@ static void save_catalog (xine_t *this) { for (i = 0; i < PLUGIN_TYPE_MAX; i++) { save_plugin_list (fp, this->plugin_catalog->plugin_lists[i]); } - fclose(fp); + if (fclose(fp)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to save catalogue cache: %s\n"), err); + goto do_unlink; + } + else if (rename (cachefile_new, cachefile)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to replace catalogue cache: %s\n"), err); + do_unlink: + if (unlink (cachefile_new) && errno != ENOENT) + { + err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to remove new catalogue cache: %s\n"), err); + } + } } free(cachefile); + free(cachefile_new); } /* @@ -1107,9 +1119,7 @@ static void load_cached_catalog (xine_t *this) { char *cachefile; const char *relname = CACHE_CATALOG_FILE; - cachefile = (char *) xine_xmalloc(strlen(xine_get_homedir()) + - strlen(relname) + 2); - sprintf(cachefile, "%s/%s", xine_get_homedir(), relname); + asprintf(&cachefile, "%s/%s", xine_get_homedir(), relname); if( (fp = fopen(cachefile,"r")) != NULL ) { load_plugin_list (fp, this->plugin_catalog->cache_list); @@ -1119,14 +1129,24 @@ static void load_cached_catalog (xine_t *this) { } +/* helper function for _x_scan_plugins */ +static void push_if_dir (xine_list_t *plugindirs, void *path) +{ + struct stat st; + if (!stat (path, &st) && S_ISDIR (st.st_mode)) + xine_list_push_back (plugindirs, path); + else + free (path); +} + /* * initialize catalog, load all plugins into new catalog */ void _x_scan_plugins (xine_t *this) { - - char *homedir, *plugindir, *pluginpath; - int i,j; - int lenpluginpath; + + char *homedir, *pluginpath; + xine_list_t *plugindirs = xine_list_new (); + xine_list_iterator_t iter; lprintf("_x_scan_plugins()\n"); @@ -1140,41 +1160,45 @@ void _x_scan_plugins (xine_t *this) { this->plugin_catalog = _new_catalog(); load_cached_catalog (this); - if ((pluginpath = getenv("XINE_PLUGIN_PATH")) != NULL) { - pluginpath = strdup(pluginpath); + if ((pluginpath = getenv("XINE_PLUGIN_PATH")) != NULL && *pluginpath) { + char *p = pluginpath; + while (p && p[0]) + { + size_t len; + char *dir, *q; + + q = p; + p = strchr (p, XINE_PATH_SEPARATOR_CHAR); + if (p) { + p++; + len = p - q; + } else + len = strlen(q); + if (q[0] == '~' && q[1] == '/') + asprintf (&dir, "%s%.*s", homedir, (int)(len - 1), q + 1); + else + dir = strndup (q, len); + push_if_dir (plugindirs, dir); /* store or free it */ + } } else { - const char *str1, *str2; - int len; - - str1 = "~/.xine/plugins"; - str2 = XINE_PLUGINDIR; - len = strlen(str1) + strlen(str2) + 2; - pluginpath = xine_xmalloc(len); - snprintf(pluginpath, len, "%s" XINE_PATH_SEPARATOR_STRING "%s", str1, str2); - } - plugindir = xine_xmalloc(strlen(pluginpath)+strlen(homedir)+2); - j=0; - lenpluginpath = strlen(pluginpath); - for (i=0; i <= lenpluginpath; ++i){ - switch (pluginpath[i]){ - case XINE_PATH_SEPARATOR_CHAR: - case '\0': - plugindir[j] = '\0'; - collect_plugins(this, plugindir); - j = 0; - break; - case '~': - if (j == 0){ - strcpy(plugindir, homedir); - j = strlen(plugindir); - break; - } - default: - plugindir[j++] = pluginpath[i]; + char *dir; + int i; + asprintf (&dir, "%s/.xine/plugins", homedir); + push_if_dir (plugindirs, dir); + for (i = 0; i <= XINE_LT_AGE; ++i) + { + asprintf (&dir, "%s.%d", XINE_PLUGINROOT, XINE_LT_AGE - i); + push_if_dir (plugindirs, dir); } } - free(plugindir); - free(pluginpath); + for (iter = xine_list_front (plugindirs); iter; + iter = xine_list_next (plugindirs, iter)) + { + char *dir = xine_list_get_value (plugindirs, iter); + collect_plugins(this, dir); + free (dir); + } + xine_list_delete (plugindirs); free(homedir); save_catalog (this); @@ -1229,6 +1253,26 @@ void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) { } } +static int probe_mime_type (xine_t *self, plugin_node_t *node, const char *mime_type) +{ + /* catalog->lock is expected to be locked */ + if (node->plugin_class || _load_plugin_class(self, node, NULL)) + { + const unsigned int mime_type_len = strlen (mime_type); + demux_class_t *cls = (demux_class_t *)node->plugin_class; + const char *mime = cls->get_mimetypes (cls); + while (mime) + { + while (*mime == ';' || isspace (*mime)) + ++mime; + if (!strncasecmp (mime, mime_type, mime_type_len) && + (!mime[mime_type_len] || mime[mime_type_len] == ':' || mime[mime_type_len] == ';')) + return 1; + mime = strchr (mime, ';'); + } + } + return 0; +} static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int method2, input_plugin_t *input) { @@ -1251,8 +1295,6 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth while (methods[i] != -1 && !plugin) { int list_id, list_size; - stream->content_detection_method = methods[i]; - pthread_mutex_lock (&catalog->lock); list_size = xine_sarray_size(catalog->plugin_lists[PLUGIN_DEMUX - 1]); @@ -1264,6 +1306,25 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugins: probing demux '%s'\n", node->info->id); if (node->plugin_class || _load_plugin_class(stream->xine, node, NULL)) { + const char *mime_type; + + /* If detecting by MRL, try the MIME type first (but not text/plain)... */ + stream->content_detection_method = METHOD_EXPLICIT; + if (methods[i] == METHOD_BY_EXTENSION && + stream->input_plugin->get_optional_data && + stream->input_plugin->get_optional_data (stream->input_plugin, NULL, INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && + stream->input_plugin->get_optional_data (stream->input_plugin, &mime_type, INPUT_OPTIONAL_DATA_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && + mime_type && strcasecmp (mime_type, "text/plain") && + probe_mime_type (stream->xine, node, mime_type) && + (plugin = ((demux_class_t *)node->plugin_class)->open_plugin (node->plugin_class, stream, input))) + { + inc_node_ref(node); + plugin->node = node; + break; + } + + /* ... then try the extension */ + stream->content_detection_method = methods[i]; if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) { inc_node_ref(node); plugin->node = node; @@ -1659,6 +1720,36 @@ const char *const *xine_list_video_output_plugins (xine_t *xine) { return catalog->ids; } +const char *const *xine_list_video_output_plugins_typed(xine_t *xine, uint64_t typemask) +{ + plugin_catalog_t *catalog = xine->plugin_catalog; + plugin_node_t *node; + int list_id, list_size, i; + + pthread_mutex_lock (&catalog->lock); + + list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1]); + + for (list_id = i = 0; list_id < list_size; list_id++) + { + node = xine_sarray_get (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1], list_id); + if (typemask & (1ULL << ((vo_info_t *)node->info->special_info)->visual_type)) + { + const char *id = node->info->id; + int j = i; + while (--j >= 0) + if (!strcmp (catalog->ids[j], id)) + goto ignore; /* already listed */ + catalog->ids[i++] = id; + } + ignore: ; + } + catalog->ids[i] = NULL; + + pthread_mutex_unlock (&catalog->lock); + return catalog->ids; +} + static ao_driver_t *_load_audio_driver (xine_t *this, plugin_node_t *node, void *data) { @@ -2384,6 +2475,31 @@ void xine_post_dispose(xine_t *xine, xine_post_t *post_gen) { * their disposal if they are still in use => post.c handles the counting for us */ } +/** + * @brief Concantenates an array of strings into a single + * string separated with a given string. + * + * @param strings Array of strings to concatenate. + * @param count Number of elements in the @p strings array. + * @param joining String to use to join the various strings together. + * @param final_length The pre-calculated final length of the string. + */ +static char *_x_concatenate_with_string(char const **strings, size_t count, char *joining, size_t final_length) { + size_t i; + char *const result = malloc(final_length+1); /* Better be safe */ + char *str = result; + + for(i = 0; i < count; i++, strings++) { + if ( *strings ) { + int offset = snprintf(str, final_length, "%s%s", *strings, joining); + str += offset; + final_length -= offset; + } + } + + return result; +} + /* get a list of file extensions for file types supported by xine * the list is separated by spaces * @@ -2391,66 +2507,35 @@ void xine_post_dispose(xine_t *xine, xine_post_t *post_gen) { char *xine_get_file_extensions (xine_t *self) { plugin_catalog_t *catalog = self->plugin_catalog; - int len, pos; - plugin_node_t *node; - char *str; - int list_id, list_size; + int list_id; pthread_mutex_lock (&catalog->lock); - /* calc length of output */ - - len = 0; - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); - for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *exts; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; - - if((exts = cls->get_extensions(cls)) && *exts) - len += strlen(exts) + 1; - } - } - - /* create output */ - str = malloc (len); /* '\0' space is already counted in the previous loop */ - pos = 0; + /* calc length of output string and create an array of strings to + concatenate */ + size_t len = 0; + const int list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); + const char **extensions = calloc(list_size, sizeof(char*)); - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *e; - int l; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); + plugin_node_t *const node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; - - if((e = cls->get_extensions (cls)) && *e) { - l = strlen(e); - memcpy (&str[pos], e, l); - - pos += l; - - /* Don't add ' ' char at the end of str */ - if((pos + 1) < len) { - str[pos] = ' '; - pos++; - } - } + demux_class_t *const cls = (demux_class_t *)node->plugin_class; + if( (extensions[list_id] = cls->get_extensions(cls)) != NULL ) + len += strlen(extensions[list_id]) +1; } } - str[pos] = 0; + /* create output string */ + char *const result = _x_concatenate_with_string(extensions, list_size, " ", len); + free(extensions); + /* Drop the last whitespace */ + result[len-1] = '\0'; + pthread_mutex_unlock (&catalog->lock); - return str; + return result; } /* get a list of mime types supported by xine @@ -2459,65 +2544,34 @@ char *xine_get_file_extensions (xine_t *self) { char *xine_get_mime_types (xine_t *self) { plugin_catalog_t *catalog = self->plugin_catalog; - int len, pos; - plugin_node_t *node; - char *str; - int list_id, list_size; + int list_id; pthread_mutex_lock (&catalog->lock); /* calc length of output */ - len = 0; - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); + /* calc length of output string and create an array of strings to + concatenate */ + size_t len = 0; + const int list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); + const char **mimetypes = calloc(list_size, sizeof(char*)); for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *s; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); + plugin_node_t *const node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; - - s = cls->get_mimetypes (cls); - if (s) - len += strlen(s); + demux_class_t *const cls = (demux_class_t *)node->plugin_class; + if( (mimetypes[list_id] = cls->get_mimetypes(cls)) != NULL ) + len += strlen(mimetypes[list_id]); } } - /* create output */ - - str = malloc (len+1); - pos = 0; - - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); - - for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *s; - int l; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { + /* create output string */ + char *const result = _x_concatenate_with_string(mimetypes, list_size, "", len); + free(mimetypes); - cls = (demux_class_t *)node->plugin_class; - - s = cls->get_mimetypes (cls); - if (s) { - l = strlen(s); - memcpy (&str[pos], s, l); - - pos += l; - } - } - } - - str[pos] = 0; - pthread_mutex_unlock (&catalog->lock); - return str; + return result; } @@ -2530,47 +2584,24 @@ char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type) { plugin_catalog_t *catalog = self->plugin_catalog; plugin_node_t *node; char *id = NULL; - char *mime_arg, *mime_demux; - char *s; - const char *mt; int list_id, list_size; - /* create a copy and convert to lower case */ - mime_arg = strdup(mime_type); - for(s=mime_arg; *s; s++) - *s = tolower(*s); - pthread_mutex_lock (&catalog->lock); list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); for (list_id = 0; (list_id < list_size) && !id; list_id++) { - demux_class_t *cls; node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; - - mt = cls->get_mimetypes (cls); - if (mt) { - mime_demux = strdup(mt); - - for(s=mime_demux; *s; s++) - *s = tolower(*s); - - if( strstr(mime_demux, mime_arg) ) - id = strdup(node->info->id); - - free(mime_demux); - } + if (probe_mime_type (self, node, mime_type)) + { + free (id); + id = strdup(node->info->id); } } pthread_mutex_unlock (&catalog->lock); - free(mime_arg); - return id; } diff --git a/src/xine-engine/lrb.c b/src/xine-engine/lrb.c index 6da846a7c..6f8ac8479 100644 --- a/src/xine-engine/lrb.c +++ b/src/xine-engine/lrb.c @@ -30,7 +30,7 @@ lrb_t *lrb_new (int max_num_entries, lrb_t *this; - this = xine_xmalloc (sizeof (lrb_t)); + this = calloc(1, sizeof(lrb_t)); this->max_num_entries = max_num_entries; this->cur_num_entries = 0; diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 73f36d541..eb9abb84a 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -172,11 +172,10 @@ static void unixscr_exit (scr_plugin_t *scr) { free(this); } -static scr_plugin_t* unixscr_init () { +static scr_plugin_t *XINE_MALLOC unixscr_init () { unixscr_t *this; - this = (unixscr_t *) xine_xmalloc(sizeof(unixscr_t)); - memset(this, 0, sizeof(*this)); + this = calloc(1, sizeof(unixscr_t)); this->scr.interface_version = 3; this->scr.get_priority = unixscr_get_priority; @@ -890,7 +889,7 @@ static void metronom_clock_exit (metronom_clock_t *this) { metronom_t * _x_metronom_init (int have_video, int have_audio, xine_t *xine) { - metronom_t *this = xine_xmalloc (sizeof (metronom_t)); + metronom_t *this = calloc(1, sizeof (metronom_t)); this->set_audio_rate = metronom_set_audio_rate; this->got_video_frame = metronom_got_video_frame; @@ -943,7 +942,7 @@ metronom_t * _x_metronom_init (int have_video, int have_audio, xine_t *xine) { metronom_clock_t *_x_metronom_clock_init(xine_t *xine) { - metronom_clock_t *this = (metronom_clock_t *) xine_xmalloc(sizeof(metronom_clock_t)); + metronom_clock_t *this = calloc(1, sizeof(metronom_clock_t)); int err; this->set_option = metronom_clock_set_option; diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h index 20e31117c..c7a594d89 100644 --- a/src/xine-engine/metronom.h +++ b/src/xine-engine/metronom.h @@ -223,7 +223,7 @@ struct metronom_s { #define METRONOM_VPTS_OFFSET 6 #define METRONOM_PREBUFFER 7 -metronom_t *_x_metronom_init (int have_video, int have_audio, xine_t *xine) XINE_PROTECTED; +metronom_t *_x_metronom_init (int have_video, int have_audio, xine_t *xine) XINE_MALLOC XINE_PROTECTED; /* FIXME: reorder this structure on the next cleanup to remove the dummies */ struct metronom_clock_s { @@ -319,7 +319,7 @@ struct metronom_clock_s { #endif }; -metronom_clock_t *_x_metronom_clock_init(xine_t *xine) XINE_PROTECTED; +metronom_clock_t *_x_metronom_clock_init(xine_t *xine) XINE_MALLOC XINE_PROTECTED; /* * clock options diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index ef888e7a4..af8286831 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -83,17 +83,6 @@ # define UCS2_ENCODING "UCS-2LE" #endif -#ifdef MAX -#undef MAX -#endif -#define MAX(a,b) ( (a) > (b) ) ? (a) : (b) - -#ifdef MIN -#undef MIN -#endif -#define MIN(a,b) ( (a) < (b) ) ? (a) : (b) - - #if (FREETYPE_MAJOR > 2) || \ (FREETYPE_MAJOR == 2 && FREETYPE_MINOR > 1) || \ (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 3) @@ -132,6 +121,20 @@ struct osd_ft2context_s { FT_Face face; int size; }; + +static void osd_free_ft2 (osd_object_t *osd) +{ + if( osd->ft2 ) { + if ( osd->ft2->face ) + FT_Done_Face (osd->ft2->face); + if ( osd->ft2->library ) + FT_Done_FreeType(osd->ft2->library); + free( osd->ft2 ); + osd->ft2 = NULL; + } +} +#else +static inline void osd_free_ft2 (osd_object_t *osd __attr_unused) {} #endif /* @@ -143,20 +146,20 @@ struct osd_ft2context_s { * for the sake of simplicity) */ -static osd_object_t *osd_new_object (osd_renderer_t *this, int width, int height) { +static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width, int height) { osd_object_t *osd; pthread_mutex_lock (&this->osd_mutex); - osd = xine_xmalloc( sizeof(osd_object_t) ); + osd = calloc(1, sizeof(osd_object_t)); osd->renderer = this; osd->next = this->osds; this->osds = osd; osd->width = width; osd->height = height; - osd->area = xine_xmalloc( width * height ); + osd->area = calloc(width, height); osd->x1 = width; osd->y1 = height; @@ -670,7 +673,7 @@ static int osd_renderer_load_font(osd_renderer_t *this, char *filename) { /* fixme: check for all read errors... */ if( (fp = gzopen(filename,"rb")) != NULL ) { - font = xine_xmalloc( sizeof(osd_font_t) ); + font = calloc(1, sizeof(osd_font_t)); gzread(fp, font->name, sizeof(font->name) ); font->version = gzread_i16(fp); @@ -818,7 +821,7 @@ static int osd_renderer_unload_font(osd_renderer_t *this, char *fontname ) { #ifdef HAVE_FT2 static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int size ) { if (!osd->ft2) { - osd->ft2 = xine_xmalloc(sizeof(osd_ft2context_t)); + osd->ft2 = calloc(1, sizeof(osd_ft2context_t)); if(FT_Init_FreeType( &osd->ft2->library )) { xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, _("osd: cannot initialize ft2 library\n")); @@ -827,6 +830,11 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int return 0; } } + + if (osd->ft2->face) { + FT_Done_Face (osd->ft2->face); + osd->ft2->face = NULL; + } #ifdef HAVE_FONTCONFIG do { @@ -885,16 +893,14 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int _("osd: error loading font %s with ft2\n"), fontname); } - free(osd->ft2); - osd->ft2 = NULL; + osd_free_ft2 (osd); return 0; end: if (FT_Set_Pixel_Sizes(osd->ft2->face, 0, size)) { xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, _("osd: error setting font size (no scalable font?)\n")); - free(osd->ft2); - osd->ft2 = NULL; + osd_free_ft2 (osd); return 0; } @@ -1410,10 +1416,9 @@ static void osd_preload_fonts (osd_renderer_t *this, char *path) { if( p ) { osd_font_t *font; - char *pathname; *p++ = '\0'; - font = xine_xmalloc( sizeof(osd_font_t) ); + font = calloc(1, sizeof(osd_font_t) ); strncpy(font->name, s, sizeof(font->name)); font->size = atoi(p); @@ -1421,9 +1426,7 @@ static void osd_preload_fonts (osd_renderer_t *this, char *path) { lprintf("font '%s' size %d is preloaded\n", font->name, font->size); - pathname = (char *) xine_xmalloc(strlen(path) + strlen(entry->d_name) + 2); - sprintf (pathname, "%s/%s", path, entry->d_name); - font->filename = pathname; + asprintf (&font->filename, "%s/%s", path, entry->d_name); font->next = this->fonts; this->fonts = font; @@ -1472,15 +1475,7 @@ static void osd_free_object (osd_object_t *osd_to_close) { if ( osd == osd_to_close ) { free( osd->area ); -#ifdef HAVE_FT2 - if( osd->ft2 ) { - if ( osd->ft2->library ) - FT_Done_FreeType(osd->ft2->library); - - free( osd->ft2 ); - } -#endif - + osd_free_ft2 (osd); osd_free_encoding(osd); if( last ) @@ -1579,9 +1574,9 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { osd_renderer_t *this; char str[1024]; - this = xine_xmalloc(sizeof(osd_renderer_t)); + this = calloc(1, sizeof(osd_renderer_t)); this->stream = stream; - this->event.object.overlay = xine_xmalloc( sizeof(vo_overlay_t) ); + this->event.object.overlay = calloc(1, sizeof(vo_overlay_t)); pthread_mutex_init (&this->osd_mutex, NULL); diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h index 38b5d1fdd..70193a2ea 100644 --- a/src/xine-engine/osd.h +++ b/src/xine-engine/osd.h @@ -226,7 +226,7 @@ struct osd_renderer_s { /* * initialize the osd rendering engine */ -osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ); +osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) XINE_MALLOC; /* diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c index 5d8d67037..aa182d627 100644 --- a/src/xine-engine/post.c +++ b/src/xine-engine/post.c @@ -30,13 +30,10 @@ void _x_post_init(post_plugin_t *post, int num_audio_inputs, int num_video_inputs) { - int audio_inputs_size = (num_audio_inputs + 1) * sizeof(xine_audio_port_t *); - int video_inputs_size = (num_video_inputs + 1) * sizeof(xine_video_port_t *); - post->input = xine_list_new(); post->output = xine_list_new(); - post->xine_post.audio_input = (xine_audio_port_t **)xine_xmalloc(audio_inputs_size); - post->xine_post.video_input = (xine_video_port_t **)xine_xmalloc(video_inputs_size); + post->xine_post.audio_input = calloc(num_audio_inputs + 1, sizeof(xine_audio_port_t *)); + post->xine_post.video_input = calloc(num_video_inputs + 1, sizeof(xine_video_port_t *)); } @@ -207,7 +204,7 @@ static int post_video_rewire(xine_post_out_t *output_gen, void *data) { post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_port_t *original, post_in_t **input, post_out_t **output) { - post_video_port_t *port = (post_video_port_t *)xine_xmalloc(sizeof(post_video_port_t)); + post_video_port_t *port = calloc(1, sizeof(post_video_port_t)); if (!port) return NULL; @@ -235,7 +232,7 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ pthread_mutex_init(&port->free_frames_lock, NULL); if (input) { - *input = (post_in_t *)xine_xmalloc(sizeof(post_in_t)); + *input = calloc(1, sizeof(post_in_t)); if (!*input) return port; (*input)->xine_in.name = "video in"; (*input)->xine_in.type = XINE_POST_DATA_VIDEO; @@ -245,7 +242,7 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ } if (output) { - *output = (post_out_t *)xine_xmalloc(sizeof(post_out_t)); + *output = calloc(1, sizeof(post_out_t)); if (!*output) return port; (*output)->xine_out.name = "video out"; (*output)->xine_out.type = XINE_POST_DATA_VIDEO; @@ -353,7 +350,7 @@ vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t * new_frame = port->free_frame_slots; port->free_frame_slots = new_frame->next; } else { - new_frame = (vo_frame_t *)xine_xmalloc(sizeof(vo_frame_t)); + new_frame = calloc(1, sizeof(vo_frame_t)); } pthread_mutex_unlock(&port->free_frames_lock); @@ -716,7 +713,7 @@ static int post_audio_rewire(xine_post_out_t *output_gen, void *data) { post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_port_t *original, post_in_t **input, post_out_t **output) { - post_audio_port_t *port = (post_audio_port_t *)xine_xmalloc(sizeof(post_audio_port_t)); + post_audio_port_t *port = calloc(1, sizeof(post_audio_port_t)); if (!port) return NULL; @@ -739,7 +736,7 @@ post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_ pthread_mutex_init(&port->usage_lock, NULL); if (input) { - *input = (post_in_t *)xine_xmalloc(sizeof(post_in_t)); + *input = calloc(1, sizeof(post_in_t)); if (!*input) return port; (*input)->xine_in.name = "audio in"; (*input)->xine_in.type = XINE_POST_DATA_AUDIO; @@ -749,7 +746,7 @@ post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_ } if (output) { - *output = (post_out_t *)xine_xmalloc(sizeof(post_out_t)); + *output = calloc(1, sizeof(post_out_t)); if (!*output) return port; (*output)->xine_out.name = "audio out"; (*output)->xine_out.type = XINE_POST_DATA_AUDIO; diff --git a/src/xine-engine/refcounter.c b/src/xine-engine/refcounter.c index 539abf3ed..384bdf5ed 100644 --- a/src/xine-engine/refcounter.c +++ b/src/xine-engine/refcounter.c @@ -17,6 +17,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "refcounter" #define LOG_VERBOSE /* @@ -30,7 +35,7 @@ refcounter_t* _x_new_refcounter(void *object, void (*destructor)(void *)) { refcounter_t *new_refcounter; - new_refcounter = (refcounter_t *) xine_xmalloc (sizeof (refcounter_t)); + new_refcounter = (refcounter_t *) calloc(1, sizeof(refcounter_t)); new_refcounter->count = 1; new_refcounter->object = object; new_refcounter->destructor = destructor; diff --git a/src/xine-engine/refcounter.h b/src/xine-engine/refcounter.h index 87abd6321..b3ddd71fc 100644 --- a/src/xine-engine/refcounter.h +++ b/src/xine-engine/refcounter.h @@ -20,10 +20,6 @@ #ifndef HAVE_REFCOUNTER_H #define HAVE_REFCOUNTER_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <pthread.h> typedef struct { @@ -35,7 +31,7 @@ typedef struct { typedef void (*refcounter_destructor)(void*); -refcounter_t* _x_new_refcounter(void *object, refcounter_destructor destructor) XINE_PROTECTED; +refcounter_t* _x_new_refcounter(void *object, refcounter_destructor destructor) XINE_MALLOC XINE_PROTECTED; int _x_refcounter_inc(refcounter_t *refcounter) XINE_PROTECTED; diff --git a/src/xine-engine/scratch.c b/src/xine-engine/scratch.c index 38b606b84..696e99ffb 100644 --- a/src/xine-engine/scratch.c +++ b/src/xine-engine/scratch.c @@ -50,12 +50,11 @@ static void __attribute__((__format__(__printf__, 2, 0))) localtime_r (&t, &tm); if ( ! this->lines[this->cur] ) - this->lines[this->cur] = xine_xmalloc(SCRATCH_LINE_LEN_MAX+1); + this->lines[this->cur] = malloc(SCRATCH_LINE_LEN_MAX+1); if ( ! this->lines[this->cur] ) return; - strftime (this->lines[this->cur], SCRATCH_LINE_LEN_MAX, "%X: ", &tm); - l = strlen (this->lines[this->cur]); + l = strftime (this->lines[this->cur], SCRATCH_LINE_LEN_MAX, "%X: ", &tm); vsnprintf (this->lines[this->cur] + l, SCRATCH_LINE_LEN_MAX - l, format, argp); lprintf ("printing format %s to line %d\n", format, this->cur); @@ -105,15 +104,11 @@ static void scratch_dispose (scratch_buffer_t *this) { scratch_buffer_t *_x_new_scratch_buffer (int num_lines) { scratch_buffer_t *this; - int i; - this = xine_xmalloc (sizeof (scratch_buffer_t)); + this = calloc(1, sizeof(scratch_buffer_t)); - this->lines = xine_xmalloc (sizeof (char *) * (num_lines + 1)); - this->ordered = xine_xmalloc (sizeof (char *) * (num_lines + 1)); - - for (i = 0; i <= num_lines; i++) - this->lines[i] = this->ordered[i] = NULL; + this->lines = calloc ((num_lines + 1), sizeof(char*)); + this->ordered = calloc ((num_lines + 1), sizeof(char*)); this->scratch_printf = scratch_printf; this->get_content = scratch_get_content; diff --git a/src/xine-engine/scratch.h b/src/xine-engine/scratch.h index c0e591d31..1029276e3 100644 --- a/src/xine-engine/scratch.h +++ b/src/xine-engine/scratch.h @@ -51,6 +51,6 @@ struct scratch_buffer_s { pthread_mutex_t lock; }; -scratch_buffer_t *_x_new_scratch_buffer (int num_lines) XINE_PROTECTED; +scratch_buffer_t *_x_new_scratch_buffer (int num_lines) XINE_MALLOC XINE_PROTECTED; #endif diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index c88e01714..d3c9e0d34 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.c @@ -160,7 +160,7 @@ static void *video_decoder_loop (void *stream_gen) { running_ticket->release(running_ticket, 0); - if( !stream->gapless_switch ) + if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) ) stream->metronom->handle_video_discontinuity (stream->metronom, DISC_STREAMSTART, 0); diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index a8464ac40..be062cc5d 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -139,11 +139,11 @@ typedef struct { * frame queue (fifo) util functions */ -static img_buf_fifo_t *vo_new_img_buf_queue () { +static img_buf_fifo_t *XINE_MALLOC vo_new_img_buf_queue () { img_buf_fifo_t *queue; - queue = (img_buf_fifo_t *) xine_xmalloc (sizeof (img_buf_fifo_t)); + queue = (img_buf_fifo_t *) calloc(1, sizeof(img_buf_fifo_t)); if( queue ) { queue->first = NULL; queue->last = NULL; @@ -1771,7 +1771,7 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon int num_frame_buffers; - this = xine_xmalloc (sizeof (vos_t)) ; + this = calloc(1, sizeof(vos_t)) ; this->xine = xine; this->clock = xine->clock; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 4d9c80565..9a2ba06c6 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -36,10 +36,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <pthread.h> #ifdef XINE_COMPILE @@ -448,7 +444,7 @@ struct video_overlay_manager_s { * build a video_out_port from * a given video driver */ -xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabonly) XINE_PROTECTED; +xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabonly) XINE_MALLOC XINE_PROTECTED; #ifdef __cplusplus } diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c index c189fa56b..b88f10c11 100644 --- a/src/xine-engine/video_overlay.c +++ b/src/xine-engine/video_overlay.c @@ -18,6 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <unistd.h> #include <string.h> @@ -199,7 +203,7 @@ static void video_overlay_reset (video_overlay_t *this) { pthread_mutex_lock (&this->events_mutex); for (i=0; i < MAX_EVENTS; i++) { if (this->events[i].event == NULL) { - this->events[i].event = xine_xmalloc (sizeof(video_overlay_event_t)); + this->events[i].event = calloc(1, sizeof(video_overlay_event_t)); #ifdef LOG_DEBUG printf ("video_overlay: MALLOC2: this->events[%d].event %p, len=%d\n", i, @@ -293,7 +297,7 @@ static int32_t video_overlay_add_event(video_overlay_manager_t *this_gen, void event->object.overlay->hili_trans[i] = OVL_MAX_OPACITY; } - this->events[new_event].event->object.overlay = xine_xmalloc (sizeof(vo_overlay_t)); + this->events[new_event].event->object.overlay = calloc(1, sizeof(vo_overlay_t)); xine_fast_memcpy(this->events[new_event].event->object.overlay, event->object.overlay, sizeof(vo_overlay_t)); @@ -587,7 +591,7 @@ video_overlay_manager_t *_x_video_overlay_new_manager (xine_t *xine) { video_overlay_t *this; - this = (video_overlay_t *) xine_xmalloc (sizeof (video_overlay_t)); + this = (video_overlay_t *) calloc(1, sizeof(video_overlay_t)); this->xine = xine; this->video_overlay.init = video_overlay_init; diff --git a/src/xine-engine/video_overlay.h b/src/xine-engine/video_overlay.h index d580a1e83..01f3a2a3a 100644 --- a/src/xine-engine/video_overlay.h +++ b/src/xine-engine/video_overlay.h @@ -98,6 +98,6 @@ typedef struct video_overlay_event_s { video_overlay_object_t object; /* The image data. */ } video_overlay_event_t; -video_overlay_manager_t *_x_video_overlay_new_manager(xine_t *) XINE_PROTECTED; +video_overlay_manager_t *_x_video_overlay_new_manager(xine_t *) XINE_MALLOC XINE_PROTECTED; #endif diff --git a/src/xine-engine/vo_scale.c b/src/xine-engine/vo_scale.c index ff30c47a6..8d84c32da 100644 --- a/src/xine-engine/vo_scale.c +++ b/src/xine-engine/vo_scale.c @@ -22,6 +22,10 @@ * Takes into account aspect ratio correction and zooming. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> #include <math.h> diff --git a/src/xine-engine/vo_scale.h b/src/xine-engine/vo_scale.h index 829405162..eb2607024 100644 --- a/src/xine-engine/vo_scale.h +++ b/src/xine-engine/vo_scale.h @@ -29,10 +29,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #ifdef XINE_COMPILE # include "configfile.h" #else diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index eae13bec9..aebbffb39 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -36,6 +36,7 @@ #include <stdarg.h> #include <stdio.h> #include <ctype.h> +#include <unistd.h> #if defined (__linux__) || defined (__GLIBC__) #include <endian.h> #elif defined (__FreeBSD__) @@ -132,7 +133,7 @@ static int acquire_allowed_to_block(xine_ticket_t *this) { unsigned new_size; for(entry = 0; entry < this->holder_thread_count; ++entry) { - if(this->holder_threads[entry].holder == own_id) { + if(pthread_equal(this->holder_threads[entry].holder, own_id)) { /* This thread may already hold this ticket */ this->holder_threads[entry].count++; return (this->holder_threads[entry].count == 1); @@ -203,7 +204,7 @@ static int release_allowed_to_block(xine_ticket_t *this) { unsigned entry; for(entry = 0; entry < this->holder_thread_count; ++entry) { - if(this->holder_threads[entry].holder == own_id) { + if(pthread_equal(this->holder_threads[entry].holder, own_id)) { this->holder_threads[entry].count--; return this->holder_threads[entry].count == 0; } @@ -303,10 +304,10 @@ static void ticket_dispose(xine_ticket_t *this) { free(this); } -static xine_ticket_t *ticket_init(void) { +static xine_ticket_t *XINE_MALLOC ticket_init(void) { xine_ticket_t *port_ticket; - port_ticket = (xine_ticket_t *) xine_xmalloc(sizeof(xine_ticket_t)); + port_ticket = calloc(1, sizeof(xine_ticket_t)); port_ticket->acquire_nonblocking = ticket_acquire_nonblocking; port_ticket->acquire = ticket_acquire; @@ -329,17 +330,20 @@ static xine_ticket_t *ticket_init(void) { static void set_speed_internal (xine_stream_t *stream, int speed) { xine_t *xine = stream->xine; + int old_speed = xine->clock->speed; - if (xine->clock->speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) + if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) /* get all decoder and post threads in a state where they agree to be blocked */ xine->port_ticket->revoke(xine->port_ticket, 0); - if (xine->clock->speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE) + if (old_speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE) /* all decoder and post threads may continue now */ xine->port_ticket->issue(xine->port_ticket, 0); - stream->xine->clock->set_fine_speed (stream->xine->clock, speed); - + if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) + /* set master clock so audio_out loop can pause in a safe place */ + stream->xine->clock->set_fine_speed (stream->xine->clock, speed); + /* see coment on audio_out loop about audio_paused */ if( stream->audio_out ) { xine->port_ticket->acquire(xine->port_ticket, 1); @@ -349,6 +353,10 @@ static void set_speed_internal (xine_stream_t *stream, int speed) { xine->port_ticket->release(xine->port_ticket, 1); } + + if (old_speed == XINE_SPEED_PAUSE || speed != XINE_SPEED_PAUSE) + /* master clock is set after resuming the audio device (audio_out loop may continue) */ + stream->xine->clock->set_fine_speed (stream->xine->clock, speed); } @@ -418,6 +426,7 @@ void xine_stop (xine_stream_t *stream) { static void close_internal (xine_stream_t *stream) { int i ; + int gapless_switch = stream->gapless_switch; if( stream->slave ) { xine_close( stream->slave ); @@ -428,7 +437,7 @@ static void close_internal (xine_stream_t *stream) { } } - if( !stream->gapless_switch ) { + if( !gapless_switch ) { /* make sure that other threads cannot change the speed, especially pauseing the stream */ pthread_mutex_lock(&stream->speed_change_lock); stream->ignore_speed_change = 1; @@ -444,7 +453,7 @@ static void close_internal (xine_stream_t *stream) { stop_internal( stream ); - if( !stream->gapless_switch ) { + if( !gapless_switch ) { if (stream->video_out) stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); if (stream->audio_out) @@ -552,7 +561,7 @@ static int stream_rewire_video(xine_post_out_t *output, void *data) return 1; } -void xine_dispose_internal (xine_stream_t *stream); +static void xine_dispose_internal (xine_stream_t *stream); xine_stream_t *xine_stream_new (xine_t *this, xine_audio_port_t *ao, xine_video_port_t *vo) { @@ -569,7 +578,7 @@ xine_stream_t *xine_stream_new (xine_t *this, pthread_mutex_lock (&this->streams_lock); - stream = (xine_stream_t *) xine_xmalloc (sizeof (xine_stream_t)) ; + stream = (xine_stream_t *) calloc (1, sizeof (xine_stream_t)) ; stream->current_extra_info = malloc( sizeof( extra_info_t ) ); stream->audio_decoder_extra_info = malloc( sizeof( extra_info_t ) ); stream->video_decoder_extra_info = malloc( sizeof( extra_info_t ) ); @@ -595,6 +604,7 @@ xine_stream_t *xine_stream_new (xine_t *this, stream->early_finish_event = 0; stream->delay_finish_event = 0; stream->gapless_switch = 0; + stream->keep_ao_driver_open = 0; stream->video_out = vo; if (vo) @@ -628,6 +638,7 @@ xine_stream_t *xine_stream_new (xine_t *this, pthread_mutex_init (&stream->meta_mutex, NULL); pthread_mutex_init (&stream->demux_lock, NULL); pthread_mutex_init (&stream->demux_mutex, NULL); + pthread_cond_init (&stream->demux_resume, NULL); pthread_mutex_init (&stream->event_queues_lock, NULL); pthread_mutex_init (&stream->counter_lock, NULL); pthread_cond_init (&stream->counter_changed, NULL); @@ -733,7 +744,7 @@ xine_stream_t *xine_stream_new (xine_t *this, } void _x_mrl_unescape(char *mrl) { - int i, len = strlen(mrl); + size_t i, len = strlen(mrl); for (i = 0; i < len; i++) { if ((mrl[i]=='%') && (i<(len-2))) { @@ -780,9 +791,23 @@ void _x_flush_events_queues (xine_stream_t *stream) { pthread_mutex_unlock (&stream->event_queues_lock); } -/*static*/ int open_internal (xine_stream_t *stream, const char *mrl) { +static inline int _x_path_looks_like_mrl (const char *path) +{ + if ((*path & 0xDF) < 'A' || (*path & 0xDF) > 'Z') + return 0; + + for (++path; *path; ++path) + if ((*path != '-' && *path < '0') || (*path > '9' && *path < 'A') || + (*path > 'Z' && *path < 'a') || *path > 'z') + break; + + return path[0] == ':' && path[1] == '/'; +} + +static int open_internal (xine_stream_t *stream, const char *mrl) { const char *stream_setup = NULL; + const char *mrl_proto = NULL; int no_cache = 0; if (!mrl) { @@ -806,16 +831,31 @@ void _x_flush_events_queues (xine_stream_t *stream) { /* * look for a stream_setup in MRL and try finding an input plugin */ + stream_setup = strchr (mrl, '#'); if (isalpha (*mrl)) { - stream_setup = mrl + 1; - while (isalnum (*stream_setup) || *stream_setup == '+' || *stream_setup == '-' || *stream_setup == '.') - ++stream_setup; - if (stream_setup[0] == ':' && stream_setup[1] == '/') - stream_setup = strchr (mrl, '#'); - else - stream_setup = NULL; + mrl_proto = mrl + 1; + while (isalnum (*mrl_proto) || *mrl_proto == '+' || *mrl_proto == '-' || *mrl_proto == '.') + ++mrl_proto; + if (!mrl_proto[0] || mrl_proto[0] != ':' || mrl_proto[1] != '/') + mrl_proto = NULL; + } + + /* for raw filenames we must try every '#' checking if it is part of the filename */ + if( !mrl_proto && stream_setup) { + struct stat stat_buf; + int res; + + while( stream_setup ) { + char *raw_filename = strndup (mrl, stream_setup - mrl); + + res = stat(raw_filename, &stat_buf); + free(raw_filename); + if( !res ) + break; + stream_setup = strchr(stream_setup + 1, '#'); + } } { @@ -824,8 +864,10 @@ void _x_flush_events_queues (xine_stream_t *stream) { /* * find an input plugin */ - - if ((stream->input_plugin = _x_find_input_plugin (stream, input_source))) { + stream->input_plugin = _x_find_input_plugin (stream, input_source); + free(input_source); + + if ( stream->input_plugin ) { int res; xine_log (stream->xine, XINE_LOG_MSG, _("xine: found input plugin : %s\n"), @@ -840,7 +882,6 @@ void _x_flush_events_queues (xine_stream_t *stream) { case 1: /* Open successfull */ break; case -1: /* Open unsuccessfull, but correct plugin */ - free(input_source); stream->err = XINE_ERROR_INPUT_FAILED; _x_flush_events_queues (stream); return 0; @@ -851,8 +892,6 @@ void _x_flush_events_queues (xine_stream_t *stream) { stream->err = XINE_ERROR_INPUT_FAILED; } } - - free(input_source); } if (!stream->input_plugin) { @@ -917,6 +956,7 @@ void _x_flush_events_queues (xine_stream_t *stream) { memcpy(filename, tmp, strlen(tmp)); filename[strlen(tmp)] = '\0'; } + _x_mrl_unescape(filename); xine_log(stream->xine, XINE_LOG_MSG, _("xine: join rip input plugin\n")); input_saver = _x_rip_plugin_get_instance (stream, filename); @@ -1091,7 +1131,9 @@ void _x_flush_events_queues (xine_stream_t *stream) { memcpy(subtitle_mrl, tmp, strlen(tmp)); subtitle_mrl[strlen(tmp)] = '\0'; } - _x_mrl_unescape(subtitle_mrl); + /* unescape for xine_open() if the MRL looks like a raw pathname */ + if (!_x_path_looks_like_mrl(subtitle_mrl)) + _x_mrl_unescape(subtitle_mrl); stream->slave = xine_stream_new (stream->xine, NULL, stream->video_out ); stream->slave_affection = XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP; if( xine_open( stream->slave, subtitle_mrl ) ) { @@ -1152,6 +1194,27 @@ void _x_flush_events_queues (xine_stream_t *stream) { /* enable buffered input plugin (request optimizer) */ stream->input_plugin = _x_cache_plugin_get_instance(stream, 0); + /* Let the plugin request a specific demuxer (if the user hasn't). + * This overrides find-by-content & find-by-extension. + */ + if (!stream->demux_plugin) + { + char *default_demux = NULL; + stream->input_plugin->get_optional_data (stream->input_plugin, &default_demux, INPUT_OPTIONAL_DATA_DEMUXER); + if (default_demux) + { + stream->demux_plugin = _x_find_demux_plugin_by_name (stream, default_demux, stream->input_plugin); + if (stream->demux_plugin) + { + lprintf ("demux and input plugin found\n"); + _x_meta_info_set_utf8 (stream, XINE_META_INFO_SYSTEMLAYER, + stream->demux_plugin->demux_class->get_identifier (stream->demux_plugin->demux_class)); + } + else + xine_log (stream->xine, XINE_LOG_MSG, _("xine: couldn't load plugin-specified demux %s for >%s<\n"), default_demux, mrl); + } + } + if (!stream->demux_plugin) { /* @@ -1290,6 +1353,7 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) pthread_mutex_lock( &stream->demux_lock ); /* demux_lock taken. now demuxer is suspended */ stream->demux_action_pending = 0; + pthread_cond_signal(&stream->demux_resume); /* set normal speed again (now that demuxer/input pair is suspended) * some input plugin may have changed speed by itself, we must ensure @@ -1403,7 +1467,7 @@ int xine_eject (xine_stream_t *stream) { return status; } -void xine_dispose_internal (xine_stream_t *stream) { +static void xine_dispose_internal (xine_stream_t *stream) { xine_list_iterator_t *ite; @@ -1416,6 +1480,7 @@ void xine_dispose_internal (xine_stream_t *stream) { pthread_mutex_destroy (&stream->current_extra_info_lock); pthread_cond_destroy (&stream->counter_changed); pthread_mutex_destroy (&stream->demux_mutex); + pthread_cond_destroy (&stream->demux_resume); pthread_mutex_destroy (&stream->demux_lock); pthread_mutex_destroy (&stream->first_frame_lock); pthread_cond_destroy (&stream->first_frame_reached); @@ -1510,7 +1575,7 @@ xine_t *xine_new (void) { int i_err; #endif - this = xine_xmalloc (sizeof (xine_t)); + this = calloc(1, sizeof (xine_t)); if (!this) _x_abort(); @@ -1599,8 +1664,7 @@ static void config_save_cb (void *this_gen, xine_cfg_entry_t *entry) { xine_t *this = (xine_t *)this_gen; char *homedir_trail_slash; - homedir_trail_slash = (char *)malloc(strlen(xine_get_homedir()) + 2); - sprintf(homedir_trail_slash, "%s/", xine_get_homedir()); + asprintf(&homedir_trail_slash, "%s/", xine_get_homedir()); if (entry->str_value[0] && (entry->str_value[0] != '/' || strstr(entry->str_value, "/.") || strcmp(entry->str_value, xine_get_homedir()) == 0 || @@ -1627,6 +1691,12 @@ void xine_init (xine_t *this) { static const char *demux_strategies[] = {"default", "reverse", "content", "extension", NULL}; + /* + * locks + */ + pthread_mutex_init (&this->streams_lock, NULL); + pthread_mutex_init (&this->log_lock, NULL); + /* initialize color conversion tables and functions */ init_yuv_conversion(); @@ -1708,12 +1778,6 @@ void xine_init (xine_t *this) { this->streams = xine_list_new(); /* - * locks - */ - pthread_mutex_init (&this->streams_lock, NULL); - pthread_mutex_init (&this->log_lock, NULL); - - /* * start metronom clock */ @@ -1899,50 +1963,98 @@ int xine_get_pos_length (xine_stream_t *stream, int *pos_stream, return 1; } -int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, - int *ratio_code, int *format, - uint8_t *img) { +static int _x_get_current_frame_data (xine_stream_t *stream, + xine_current_frame_data_t *data, + int flags, int img_size_unknown) { vo_frame_t *frame; + size_t required_size; stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); frame = stream->video_out->get_last_frame (stream->video_out); stream->xine->port_ticket->release(stream->xine->port_ticket, 0); - if (!frame) + if (!frame) { + data->img_size = 0; return 0; + } - *width = frame->width; - *height = frame->height; + data->width = frame->width; + data->height = frame->height; + data->crop_left = frame->crop_left; + data->crop_right = frame->crop_right; + data->crop_top = frame->crop_top; + data->crop_bottom = frame->crop_bottom; - *ratio_code = 10000.0 * frame->ratio; + data->ratio_code = 10000.0 * frame->ratio; /* make ratio_code backward compatible */ #define RATIO_LIKE(a, b) ((b) - 1 <= (a) && (a) <= 1 + (b)) - if (RATIO_LIKE(*ratio_code, 10000)) - *ratio_code = XINE_VO_ASPECT_SQUARE; - else if (RATIO_LIKE(*ratio_code, 13333)) - *ratio_code = XINE_VO_ASPECT_4_3; - else if (RATIO_LIKE(*ratio_code, 17778)) - *ratio_code = XINE_VO_ASPECT_ANAMORPHIC; - else if (RATIO_LIKE(*ratio_code, 21100)) - *ratio_code = XINE_VO_ASPECT_DVB; - - *format = frame->format; - - if (img){ + if (RATIO_LIKE(data->ratio_code, 10000)) + data->ratio_code = XINE_VO_ASPECT_SQUARE; + else if (RATIO_LIKE(data->ratio_code, 13333)) + data->ratio_code = XINE_VO_ASPECT_4_3; + else if (RATIO_LIKE(data->ratio_code, 17778)) + data->ratio_code = XINE_VO_ASPECT_ANAMORPHIC; + else if (RATIO_LIKE(data->ratio_code, 21100)) + data->ratio_code = XINE_VO_ASPECT_DVB; + + data->format = frame->format; + data->interlaced = frame->progressive_frame ? 0 : (2 - frame->top_field_first); + + switch (frame->format) { + + case XINE_IMGFMT_YV12: + required_size = frame->width * frame->height + + ((frame->width + 1) / 2) * ((frame->height + 1) / 2) + + ((frame->width + 1) / 2) * ((frame->height + 1) / 2); + break; + + case XINE_IMGFMT_YUY2: + required_size = frame->width * frame->height + + ((frame->width + 1) / 2) * frame->height + + ((frame->width + 1) / 2) * frame->height; + break; + + default: + if (data->img || (flags & XINE_FRAME_DATA_ALLOCATE_IMG)) { + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, + "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); + _x_abort (); + } + + required_size = 0; + } + + if (flags & XINE_FRAME_DATA_ALLOCATE_IMG) { + /* return allocated buffer size */ + data->img_size = required_size; + /* allocate img or fail */ + if (!(data->img = calloc(1, required_size))) + return 0; + } else { + /* fail if supplied buffer is to small */ + if (data->img && !img_size_unknown && data->img_size < required_size) { + data->img_size = required_size; + return 0; + } + /* return used buffer size */ + data->img_size = required_size; + } + + if (data->img) { switch (frame->format) { case XINE_IMGFMT_YV12: yv12_to_yv12( /* Y */ frame->base[0], frame->pitches[0], - img, frame->width, + data->img, frame->width, /* U */ frame->base[1], frame->pitches[1], - img+frame->width*frame->height, frame->width/2, + data->img+frame->width*frame->height, frame->width/2, /* V */ frame->base[2], frame->pitches[2], - img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2, + data->img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2, /* width x height */ frame->width, frame->height); break; @@ -1952,7 +2064,7 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, /* src */ frame->base[0], frame->pitches[0], /* dst */ - img, frame->width*2, + data->img, frame->width*2, /* width x height */ frame->width, frame->height); break; @@ -1966,6 +2078,69 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, return 1; } +int xine_get_current_frame_data (xine_stream_t *stream, + xine_current_frame_data_t *data, + int flags) { + + return _x_get_current_frame_data(stream, data, flags, 0); +} + +int xine_get_current_frame_alloc (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t **img, int *img_size) { + + int result; + xine_current_frame_data_t data; + + memset(&data, 0, sizeof (data)); + + result = _x_get_current_frame_data(stream, &data, img ? XINE_FRAME_DATA_ALLOCATE_IMG : 0, 0); + if (width) *width = data.width; + if (height) *height = data.height; + if (ratio_code) *ratio_code = data.ratio_code; + if (format) *format = data.format; + if (img_size) *img_size = data.img_size; + if (img) *img = data.img; + return result; +} + +int xine_get_current_frame_s (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t *img, int *img_size) { + int result; + xine_current_frame_data_t data; + + memset(&data, 0, sizeof (data)); + data.img = img; + if (img_size) + data.img_size = *img_size; + + result = _x_get_current_frame_data(stream, &data, 0, 0); + if (width) *width = data.width; + if (height) *height = data.height; + if (ratio_code) *ratio_code = data.ratio_code; + if (format) *format = data.format; + if (img_size) *img_size = data.img_size; + return result; +} + +int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t *img) { + int result; + xine_current_frame_data_t data; + + memset(&data, 0, sizeof (data)); + data.img = img; + + result = _x_get_current_frame_data(stream, &data, 0, 1); + if (width) *width = data.width; + if (height) *height = data.height; + if (ratio_code) *ratio_code = data.ratio_code; + if (format) *format = data.format; + return result; +} + int xine_get_video_frame (xine_stream_t *stream, int timestamp, /* msec */ int *width, int *height, @@ -2084,7 +2259,10 @@ void xine_log (xine_t *this, int buf, const char *format, ...) { vsnprintf(buffer, SCRATCH_LINE_LEN_MAX, format, argp); printf("%s", buffer); va_end (argp); - } + } + + if (this->log_cb) + this->log_cb (this->log_cb_user_data, buf); } void xine_vlog(xine_t *this, int buf, const char *format, @@ -2093,6 +2271,9 @@ void xine_vlog(xine_t *this, int buf, const char *format, check_log_alloc (this, buf); this->log_buffers[buf]->scratch_printf(this->log_buffers[buf], format, args); + + if (this->log_cb) + this->log_cb (this->log_cb_user_data, buf); } char *const *xine_get_log (xine_t *this, int buf) { @@ -2107,12 +2288,10 @@ char *const *xine_get_log (xine_t *this, int buf) { } void xine_register_log_cb (xine_t *this, xine_log_cb_t cb, void *user_data) { - - printf ("xine: xine_register_log_cb: not implemented yet.\n"); - _x_abort(); + this->log_cb = cb; + this->log_cb_user_data = user_data; } - int xine_get_error (xine_stream_t *stream) { return stream->err; } diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 50d8796e8..0438aedfa 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -527,6 +527,9 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { case XINE_PARAM_GAPLESS_SWITCH: stream->gapless_switch = !!value; + if( stream->gapless_switch && !stream->early_finish_event ) { + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "frontend possibly buggy: gapless_switch without early_finish_event\n"); + } break; default: @@ -739,6 +742,8 @@ uint32_t xine_get_stream_info (xine_stream_t *stream, int info) { case XINE_STREAM_INFO_IGNORE_AUDIO: case XINE_STREAM_INFO_IGNORE_SPU: case XINE_STREAM_INFO_VIDEO_HAS_STILL: + case XINE_STREAM_INFO_SKIPPED_FRAMES: + case XINE_STREAM_INFO_DISCARDED_FRAMES: case XINE_STREAM_INFO_VIDEO_AFD: case XINE_STREAM_INFO_DVD_TITLE_NUMBER: case XINE_STREAM_INFO_DVD_TITLE_COUNT: @@ -945,7 +950,7 @@ int _x_message(xine_stream_t *stream, int type, ...) { xine_ui_message_data_t *data; xine_event_t event; const char *explanation; - int size; + size_t size; int n; va_list ap; char *s, *params; @@ -990,7 +995,7 @@ int _x_message(xine_stream_t *stream, int type, ...) { args[n] = NULL; size += sizeof(xine_ui_message_data_t) + 1; - data = xine_xmalloc( size ); + data = calloc(1, size ); strcpy(data->compatibility.str, "Upgrade your frontend to see the error messages"); data->type = type; diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index 9b69f16f1..945157fc2 100644 --- a/src/xine-engine/xine_internal.h +++ b/src/xine-engine/xine_internal.h @@ -117,6 +117,9 @@ struct xine_s { #ifdef XINE_ENGINE_INTERNAL xine_ticket_t *port_ticket; pthread_mutex_t log_lock; + + xine_log_cb_t log_cb; + void *log_cb_user_data; #endif }; @@ -333,6 +336,7 @@ struct xine_stream_s { int demux_thread_running; pthread_mutex_t demux_lock; int demux_action_pending; + pthread_cond_t demux_resume; pthread_mutex_t demux_mutex; /* used in _x_demux_... functions to synchronize order of pairwise A/V buffer operations */ extra_info_t *current_extra_info; @@ -357,6 +361,7 @@ struct xine_stream_s { int early_finish_event; /* do not wait fifos get empty before sending event */ int gapless_switch; /* next stream switch will be gapless */ int delay_finish_event; /* delay event in 1/10 sec units. 0=>no delay, -1=>forever */ + int keep_ao_driver_open; #endif }; @@ -388,8 +393,8 @@ input_plugin_t *_x_find_input_plugin (xine_stream_t *stream, const char *mrl) XI demux_plugin_t *_x_find_demux_plugin (xine_stream_t *stream, input_plugin_t *input) XINE_PROTECTED; demux_plugin_t *_x_find_demux_plugin_by_name (xine_stream_t *stream, const char *name, input_plugin_t *input) XINE_PROTECTED; demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const char *last_demux_name, input_plugin_t *input) XINE_PROTECTED; -input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *filename) XINE_PROTECTED; -input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahead_size) XINE_PROTECTED; +input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *filename) XINE_MALLOC XINE_PROTECTED; +input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahead_size) XINE_MALLOC XINE_PROTECTED; void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) XINE_PROTECTED; void _x_free_demux_plugin (xine_stream_t *stream, demux_plugin_t *demux) XINE_PROTECTED; |