You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1227 lines
47 KiB
1227 lines
47 KiB
13 years ago
|
diff --git a/modules/access/rtp/rtp.c b/modules/access/rtp/rtp.c
|
||
|
index e1cd6b1..03f882f 100755
|
||
|
--- a/modules/access/rtp/rtp.c
|
||
|
+++ b/modules/access/rtp/rtp.c
|
||
|
@@ -39,6 +39,8 @@
|
||
|
#include "rtp.h"
|
||
|
#ifdef HAVE_SRTP
|
||
|
# include <srtp.h>
|
||
|
+# include <gcrypt.h>
|
||
|
+# include <vlc_gcrypt.h>
|
||
|
#endif
|
||
|
|
||
|
#define RTP_CACHING_TEXT N_("RTP de-jitter buffer length (msec)")
|
||
|
@@ -276,6 +278,7 @@ static int Open (vlc_object_t *obj)
|
||
|
char *key = var_CreateGetNonEmptyString (demux, "srtp-key");
|
||
|
if (key)
|
||
|
{
|
||
|
+ vlc_gcrypt_init ();
|
||
|
p_sys->srtp = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 10,
|
||
|
SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
|
||
|
if (p_sys->srtp == NULL)
|
||
|
diff --git a/modules/access/v4l2.c b/modules/access/v4l2.c
|
||
|
index d29aec6..d0e14db 100644
|
||
|
--- a/modules/access/v4l2.c
|
||
|
+++ b/modules/access/v4l2.c
|
||
|
@@ -792,7 +792,7 @@ static void ParseMRL( demux_sys_t *p_sys, char *psz_path, vlc_object_t *p_obj )
|
||
|
}
|
||
|
|
||
|
if( i == ARRAY_SIZE(psz_standards_list_text) )
|
||
|
- p_sys->i_selected_standard_id = i_standards_list[strtol( psz_parser, &psz_parser, 0 )];
|
||
|
+ p_sys->i_selected_standard_id = strtol( psz_parser, &psz_parser, 0 );
|
||
|
}
|
||
|
else if( !strncmp( psz_parser, "chroma=", strlen( "chroma=" ) ) )
|
||
|
{
|
||
|
diff --git a/modules/audio_output/auhal.c b/modules/audio_output/auhal.c
|
||
|
index ab45f0c..6985781 100644
|
||
|
--- a/modules/audio_output/auhal.c
|
||
|
+++ b/modules/audio_output/auhal.c
|
||
|
@@ -632,7 +632,7 @@ static int OpenSPDIF( aout_instance_t * p_aout )
|
||
|
|
||
|
/* Set mixable to false if we are allowed to */
|
||
|
AudioObjectPropertyAddress audioDeviceSupportsMixingAddress = { kAudioDevicePropertySupportsMixing , kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
|
||
|
- b_writeable = AudioObjectHasProperty( p_sys->i_selected_dev, &audioDeviceSupportsMixingAddress );
|
||
|
+ err = AudioObjectIsPropertySettable( p_sys->i_selected_dev, &audioDeviceSupportsMixingAddress, &b_writeable );
|
||
|
err = AudioObjectGetPropertyDataSize( p_sys->i_selected_dev, &audioDeviceSupportsMixingAddress, 0, NULL, &i_param_size );
|
||
|
err = AudioObjectGetPropertyData( p_sys->i_selected_dev, &audioDeviceSupportsMixingAddress, 0, NULL, &i_param_size, &b_mix );
|
||
|
|
||
|
@@ -676,7 +676,7 @@ static int OpenSPDIF( aout_instance_t * p_aout )
|
||
|
for( int i = 0; i < i_streams && p_sys->i_stream_index < 0 ; i++ )
|
||
|
{
|
||
|
/* Find a stream with a cac3 stream */
|
||
|
- AudioStreamBasicDescription *p_format_list = NULL;
|
||
|
+ AudioStreamRangedDescription *p_format_list = NULL;
|
||
|
int i_formats = 0;
|
||
|
bool b_digital = false;
|
||
|
|
||
|
@@ -688,8 +688,8 @@ static int OpenSPDIF( aout_instance_t * p_aout )
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
- i_formats = i_param_size / sizeof( AudioStreamBasicDescription );
|
||
|
- p_format_list = (AudioStreamBasicDescription *)malloc( i_param_size );
|
||
|
+ i_formats = i_param_size / sizeof( AudioStreamRangedDescription );
|
||
|
+ p_format_list = (AudioStreamRangedDescription *)malloc( i_param_size );
|
||
|
if( p_format_list == NULL )
|
||
|
continue;
|
||
|
|
||
|
@@ -704,8 +704,8 @@ static int OpenSPDIF( aout_instance_t * p_aout )
|
||
|
/* Check if one of the supported formats is a digital format */
|
||
|
for( int j = 0; j < i_formats; j++ )
|
||
|
{
|
||
|
- if( p_format_list[j].mFormatID == 'IAC3' ||
|
||
|
- p_format_list[j].mFormatID == kAudioFormat60958AC3 )
|
||
|
+ if( p_format_list[j].mFormat.mFormatID == 'IAC3' ||
|
||
|
+ p_format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 )
|
||
|
{
|
||
|
b_digital = true;
|
||
|
break;
|
||
|
@@ -737,21 +737,21 @@ static int OpenSPDIF( aout_instance_t * p_aout )
|
||
|
|
||
|
for( int j = 0; j < i_formats; j++ )
|
||
|
{
|
||
|
- if( p_format_list[j].mFormatID == 'IAC3' ||
|
||
|
- p_format_list[j].mFormatID == kAudioFormat60958AC3 )
|
||
|
+ if( p_format_list[j].mFormat.mFormatID == 'IAC3' ||
|
||
|
+ p_format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 )
|
||
|
{
|
||
|
- if( p_format_list[j].mSampleRate == p_aout->output.output.i_rate )
|
||
|
+ if( p_format_list[j].mFormat.mSampleRate == p_aout->output.output.i_rate )
|
||
|
{
|
||
|
i_requested_rate_format = j;
|
||
|
break;
|
||
|
}
|
||
|
- else if( p_format_list[j].mSampleRate == p_sys->sfmt_revert.mSampleRate )
|
||
|
+ else if( p_format_list[j].mFormat.mSampleRate == p_sys->sfmt_revert.mSampleRate )
|
||
|
{
|
||
|
i_current_rate_format = j;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
- if( i_backup_rate_format < 0 || p_format_list[j].mSampleRate > p_format_list[i_backup_rate_format].mSampleRate )
|
||
|
+ if( i_backup_rate_format < 0 || p_format_list[j].mFormat.mSampleRate > p_format_list[i_backup_rate_format].mFormat.mSampleRate )
|
||
|
i_backup_rate_format = j;
|
||
|
}
|
||
|
}
|
||
|
@@ -759,10 +759,10 @@ static int OpenSPDIF( aout_instance_t * p_aout )
|
||
|
}
|
||
|
|
||
|
if( i_requested_rate_format >= 0 ) /* We prefer to output at the samplerate of the original audio */
|
||
|
- p_sys->stream_format = p_format_list[i_requested_rate_format];
|
||
|
+ p_sys->stream_format = p_format_list[i_requested_rate_format].mFormat;
|
||
|
else if( i_current_rate_format >= 0 ) /* If not possible, we will try to use the current samplerate of the device */
|
||
|
- p_sys->stream_format = p_format_list[i_current_rate_format];
|
||
|
- else p_sys->stream_format = p_format_list[i_backup_rate_format]; /* And if we have to, any digital format will be just fine (highest rate possible) */
|
||
|
+ p_sys->stream_format = p_format_list[i_current_rate_format].mFormat;
|
||
|
+ else p_sys->stream_format = p_format_list[i_backup_rate_format].mFormat; /* And if we have to, any digital format will be just fine (highest rate possible) */
|
||
|
}
|
||
|
free( p_format_list );
|
||
|
}
|
||
|
@@ -866,7 +866,7 @@ static void Close( vlc_object_t * p_this )
|
||
|
Boolean b_writeable;
|
||
|
/* Revert mixable to true if we are allowed to */
|
||
|
AudioObjectPropertyAddress audioDeviceSupportsMixingAddress = { kAudioDevicePropertySupportsMixing , kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
|
||
|
- b_writeable = AudioObjectHasProperty( p_sys->i_selected_dev, &audioDeviceSupportsMixingAddress );
|
||
|
+ err = AudioObjectIsPropertySettable( p_sys->i_selected_dev, &audioDeviceSupportsMixingAddress, &b_writeable );
|
||
|
err = AudioObjectGetPropertyData( p_sys->i_selected_dev, &audioDeviceSupportsMixingAddress, 0, NULL, &i_param_size, &b_mix );
|
||
|
|
||
|
if( !err && b_writeable )
|
||
|
@@ -1082,7 +1082,7 @@ static int AudioDeviceSupportsDigital( aout_instance_t *p_aout, AudioDeviceID i_
|
||
|
bool b_return = false;
|
||
|
|
||
|
/* Retrieve all the output streams */
|
||
|
- AudioObjectPropertyAddress streamsAddress = { kAudioDevicePropertyStreams, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
|
||
|
+ AudioObjectPropertyAddress streamsAddress = { kAudioDevicePropertyStreams, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
|
||
|
err = AudioObjectGetPropertyDataSize( i_dev_id, &streamsAddress, 0, NULL, &i_param_size );
|
||
|
if( err != noErr )
|
||
|
{
|
||
|
diff --git a/modules/audio_output/pulse.c b/modules/audio_output/pulse.c
|
||
|
index 64de04d..a377f66 100644
|
||
|
--- a/modules/audio_output/pulse.c
|
||
|
+++ b/modules/audio_output/pulse.c
|
||
|
@@ -58,7 +58,9 @@ struct aout_sys_t
|
||
|
pa_stream *stream; /**< PulseAudio playback stream object */
|
||
|
pa_context *context; /**< PulseAudio connection context */
|
||
|
pa_threaded_mainloop *mainloop; /**< PulseAudio event loop */
|
||
|
- //uint32_t byterate; /**< bytes per second */
|
||
|
+ mtime_t pts; /**< Play time of buffer write offset */
|
||
|
+ mtime_t desync; /**< Measured desynchronization */
|
||
|
+ unsigned rate; /**< Current stream sample rate */
|
||
|
};
|
||
|
|
||
|
/* Context helpers */
|
||
|
@@ -93,6 +95,164 @@ static void error(aout_instance_t *aout, const char *msg, pa_context *context)
|
||
|
msg_Err(aout, "%s: %s", msg, pa_strerror(pa_context_errno(context)));
|
||
|
}
|
||
|
|
||
|
+/* Latency management and lip synchronization */
|
||
|
+static mtime_t vlc_pa_get_latency(aout_instance_t *aout,
|
||
|
+ pa_context *ctx, pa_stream *s)
|
||
|
+{
|
||
|
+ pa_usec_t latency;
|
||
|
+ int negative;
|
||
|
+
|
||
|
+ if (pa_stream_get_latency(s, &latency, &negative)) {
|
||
|
+ if (pa_context_errno (ctx) != PA_ERR_NODATA)
|
||
|
+ error(aout, "unknown latency", ctx);
|
||
|
+ return VLC_TS_INVALID;
|
||
|
+ }
|
||
|
+ return negative ? -latency : +latency;
|
||
|
+}
|
||
|
+
|
||
|
+static void stream_reset_sync(pa_stream *s, aout_instance_t *aout)
|
||
|
+{
|
||
|
+ aout_sys_t *sys = aout->output.p_sys;
|
||
|
+ const unsigned rate = aout->output.output.i_rate;
|
||
|
+
|
||
|
+ sys->pts = VLC_TS_INVALID;
|
||
|
+ sys->desync = 0;
|
||
|
+ pa_operation *op = pa_stream_update_sample_rate(s, rate, NULL, NULL);
|
||
|
+ if (unlikely(op == NULL))
|
||
|
+ return;
|
||
|
+ pa_operation_unref(op);
|
||
|
+ sys->rate = rate;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * Starts or resumes the playback stream.
|
||
|
+ * Tries start playing back audio samples at the most accurate time
|
||
|
+ * in order to minimize desync and resampling during early playback.
|
||
|
+ * @note PulseAudio lock required.
|
||
|
+ */
|
||
|
+static void stream_resync(aout_instance_t *aout, pa_stream *s)
|
||
|
+{
|
||
|
+ aout_sys_t *sys = aout->output.p_sys;
|
||
|
+ pa_operation *op;
|
||
|
+ mtime_t delta;
|
||
|
+
|
||
|
+ assert (pa_stream_is_corked(s) > 0);
|
||
|
+ assert (sys->pts != VLC_TS_INVALID);
|
||
|
+
|
||
|
+ delta = vlc_pa_get_latency(aout, sys->context, s);
|
||
|
+ if (unlikely(delta == VLC_TS_INVALID))
|
||
|
+ delta = 0; /* screwed */
|
||
|
+
|
||
|
+ delta = (sys->pts - mdate()) - delta;
|
||
|
+
|
||
|
+ /* TODO: adjust prebuf instead of padding? */
|
||
|
+ if (delta > 0) {
|
||
|
+ size_t nb = (delta * sys->rate) / CLOCK_FREQ;
|
||
|
+ size_t size = aout->output.output.i_bytes_per_frame;
|
||
|
+ float *zeroes = calloc (nb, size);
|
||
|
+
|
||
|
+ msg_Dbg(aout, "starting with %zu zeroes (%"PRId64" us)", nb,
|
||
|
+ delta);
|
||
|
+#if 0 /* Fault injector: add delay */
|
||
|
+ pa_stream_write(s, zeroes, nb * size, NULL, 0, PA_SEEK_RELATIVE);
|
||
|
+ pa_stream_write(s, zeroes, nb * size, NULL, 0, PA_SEEK_RELATIVE);
|
||
|
+#endif
|
||
|
+ if (likely(zeroes != NULL))
|
||
|
+ if (pa_stream_write(s, zeroes, nb * size, free, 0,
|
||
|
+ PA_SEEK_RELATIVE) < 0)
|
||
|
+ free(zeroes);
|
||
|
+ } else
|
||
|
+ msg_Warn(aout, "starting late (%"PRId64" us)", delta);
|
||
|
+
|
||
|
+ op = pa_stream_cork(s, 0, NULL, NULL);
|
||
|
+ if (op != NULL)
|
||
|
+ pa_operation_unref(op);
|
||
|
+ op = pa_stream_trigger(s, NULL, NULL);
|
||
|
+ if (op != NULL)
|
||
|
+ pa_operation_unref(op);
|
||
|
+}
|
||
|
+
|
||
|
+/* Values from EBU R37 */
|
||
|
+#define AOUT_EARLY_TOLERANCE 40000
|
||
|
+#define AOUT_LATE_TOLERANCE 60000
|
||
|
+
|
||
|
+static void stream_latency_cb(pa_stream *s, void *userdata)
|
||
|
+{
|
||
|
+ aout_instance_t *aout = userdata;
|
||
|
+ aout_sys_t *sys = aout->output.p_sys;
|
||
|
+ mtime_t delta, change;
|
||
|
+
|
||
|
+ if (pa_stream_is_corked(s))
|
||
|
+ return;
|
||
|
+ if (sys->pts == VLC_TS_INVALID)
|
||
|
+ {
|
||
|
+ msg_Dbg(aout, "missing latency from input");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Compute lip desynchronization */
|
||
|
+ delta = vlc_pa_get_latency(aout, sys->context, s);
|
||
|
+ if (delta == VLC_TS_INVALID)
|
||
|
+ return;
|
||
|
+
|
||
|
+ delta = (sys->pts - mdate()) - delta;
|
||
|
+ change = delta - sys->desync;
|
||
|
+ sys->desync = delta;
|
||
|
+ //msg_Dbg(aout, "desync: %+"PRId64" us (variation: %+"PRId64" us)",
|
||
|
+ // delta, change);
|
||
|
+
|
||
|
+ const unsigned inrate = aout->output.output.i_rate;
|
||
|
+ unsigned outrate = sys->rate;
|
||
|
+ bool sync = false;
|
||
|
+
|
||
|
+ if (delta < -AOUT_LATE_TOLERANCE)
|
||
|
+ msg_Warn(aout, "too late by %"PRId64" us", -delta);
|
||
|
+ else if (delta > +AOUT_EARLY_TOLERANCE)
|
||
|
+ msg_Warn(aout, "too early by %"PRId64" us", delta);
|
||
|
+ else if (outrate == inrate)
|
||
|
+ return; /* In sync, do not add unnecessary disturbance! */
|
||
|
+ else
|
||
|
+ sync = true;
|
||
|
+
|
||
|
+ /* Compute playback sample rate */
|
||
|
+ /* This is empirical (especially the shift values).
|
||
|
+ * Feel free to define something smarter. */
|
||
|
+ int adj = sync ? (outrate - inrate)
|
||
|
+ : outrate * ((delta >> 4) + change) / (CLOCK_FREQ << 2);
|
||
|
+ /* This avoids too quick rate variation. It sounds really bad and
|
||
|
+ * causes unstability (e.g. oscillation around the correct rate). */
|
||
|
+ int limit = inrate >> 10;
|
||
|
+ /* However, to improve stability and try to converge, closing to the
|
||
|
+ * nominal rate is favored over drifting from it. */
|
||
|
+ if ((adj > 0) == (sys->rate > inrate))
|
||
|
+ limit *= 2;
|
||
|
+ if (adj > +limit)
|
||
|
+ adj = +limit;
|
||
|
+ if (adj < -limit)
|
||
|
+ adj = -limit;
|
||
|
+ outrate -= adj;
|
||
|
+
|
||
|
+ /* This keeps the effective rate within specified range
|
||
|
+ * (+/-AOUT_MAX_RESAMPLING% - see <vlc_aout.h>) of the nominal rate. */
|
||
|
+ limit = inrate * AOUT_MAX_RESAMPLING / 100;
|
||
|
+ if (outrate > inrate + limit)
|
||
|
+ outrate = inrate + limit;
|
||
|
+ if (outrate < inrate - limit)
|
||
|
+ outrate = inrate - limit;
|
||
|
+
|
||
|
+ /* Apply adjusted sample rate */
|
||
|
+ if (outrate == sys->rate)
|
||
|
+ return;
|
||
|
+ pa_operation *op = pa_stream_update_sample_rate(s, outrate, NULL, NULL);
|
||
|
+ if (unlikely(op == NULL)) {
|
||
|
+ error(aout, "cannot change sample rate", sys->context);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ pa_operation_unref(op);
|
||
|
+ msg_Dbg(aout, "changed sample rate to %u Hz",outrate);
|
||
|
+ sys->rate = outrate;
|
||
|
+}
|
||
|
+
|
||
|
/* Stream helpers */
|
||
|
static void stream_state_cb(pa_stream *s, void *userdata)
|
||
|
{
|
||
|
@@ -106,6 +266,7 @@ static void stream_state_cb(pa_stream *s, void *userdata)
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
+ (void) userdata;
|
||
|
}
|
||
|
|
||
|
static void stream_moved_cb(pa_stream *s, void *userdata)
|
||
|
@@ -138,15 +299,19 @@ static void stream_suspended_cb(pa_stream *s, void *userdata)
|
||
|
aout_instance_t *aout = userdata;
|
||
|
|
||
|
msg_Dbg(aout, "suspended");
|
||
|
- (void) s;
|
||
|
+ stream_reset_sync(s, aout);
|
||
|
}
|
||
|
|
||
|
static void stream_underflow_cb(pa_stream *s, void *userdata)
|
||
|
{
|
||
|
aout_instance_t *aout = userdata;
|
||
|
+ pa_operation *op;
|
||
|
|
||
|
- msg_Dbg(aout, "underflow");
|
||
|
- (void) s;
|
||
|
+ msg_Warn(aout, "underflow");
|
||
|
+ op = pa_stream_cork(s, 1, NULL, NULL);
|
||
|
+ if (op != NULL)
|
||
|
+ pa_operation_unref(op);
|
||
|
+ stream_reset_sync(s, aout);
|
||
|
}
|
||
|
|
||
|
static int stream_wait(pa_threaded_mainloop *mainloop, pa_stream *stream)
|
||
|
@@ -193,6 +358,17 @@ static void Play(aout_instance_t *aout)
|
||
|
aout_sys_t *sys = aout->output.p_sys;
|
||
|
pa_stream *s = sys->stream;
|
||
|
|
||
|
+ /* This function is called exactly once per block in the output FIFO. */
|
||
|
+ block_t *block = aout_FifoPop(aout, &aout->output.fifo);
|
||
|
+ assert (block != NULL);
|
||
|
+
|
||
|
+ const void *ptr = data_convert(&block);
|
||
|
+ if (unlikely(ptr == NULL))
|
||
|
+ return;
|
||
|
+
|
||
|
+ size_t len = block->i_buffer;
|
||
|
+ mtime_t pts = block->i_pts + block->i_length;
|
||
|
+
|
||
|
/* Note: The core already holds the output FIFO lock at this point.
|
||
|
* Therefore we must not under any circumstances (try to) acquire the
|
||
|
* output FIFO lock while the PulseAudio threaded main loop lock is held
|
||
|
@@ -200,71 +376,26 @@ static void Play(aout_instance_t *aout)
|
||
|
* will take place, and sooner or later a deadlock. */
|
||
|
pa_threaded_mainloop_lock(sys->mainloop);
|
||
|
|
||
|
- if (pa_stream_is_corked(sys->stream) > 0) {
|
||
|
- pa_operation *op = pa_stream_cork(s, 0, NULL, NULL);
|
||
|
- if (op != NULL)
|
||
|
- pa_operation_unref(op);
|
||
|
- msg_Dbg(aout, "uncorking");
|
||
|
- }
|
||
|
-
|
||
|
-#if 0
|
||
|
- /* This function should be called by the LibVLC core a header of time,
|
||
|
- * but not more than AOUT_MAX_PREPARE. The PulseAudio latency should be
|
||
|
- * shorter than that (though it might not be the case with some evil piece
|
||
|
- * of audio output hardware). So we may need to trigger playback early,
|
||
|
- * (that is to say, short cut the PulseAudio prebuffering). Otherwise,
|
||
|
- * audio and video may be out of synchronization. */
|
||
|
- pa_usec_t latency;
|
||
|
- int negative;
|
||
|
- if (pa_stream_get_latency(s, &latency, &negative) < 0) {
|
||
|
- /* Especially at start of stream, latency may not be known (yet). */
|
||
|
- if (pa_context_errno(sys->context) != PA_ERR_NODATA)
|
||
|
- error(aout, "cannot determine latency", sys->context);
|
||
|
- } else {
|
||
|
- mtime_t gap = aout_FifoFirstDate(aout, &aout->output.fifo) - mdate()
|
||
|
- - latency;
|
||
|
+ sys->pts = pts;
|
||
|
+ if (pa_stream_is_corked(s) > 0)
|
||
|
+ stream_resync(aout, s);
|
||
|
|
||
|
- if (gap > AOUT_PTS_TOLERANCE)
|
||
|
- msg_Dbg(aout, "buffer too early (%"PRId64" us)", gap);
|
||
|
- else if (gap < -AOUT_PTS_TOLERANCE)
|
||
|
- msg_Err(aout, "buffer too late (%"PRId64" us)", -gap);
|
||
|
- }
|
||
|
-#endif
|
||
|
#if 0 /* Fault injector to test underrun recovery */
|
||
|
- static unsigned u = 0;
|
||
|
- if ((++u % 500) == 0) {
|
||
|
+ static volatile unsigned u = 0;
|
||
|
+ if ((++u % 1000) == 0) {
|
||
|
msg_Err(aout, "fault injection");
|
||
|
- msleep(CLOCK_FREQ*2);
|
||
|
+ pa_operation_unref(pa_stream_flush(s, NULL, NULL));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
- /* This function is called exactly once per block in the output FIFO, so
|
||
|
- * this for-loop is not necessary.
|
||
|
- * If this function is changed to not always dequeue blocks, be sure to
|
||
|
- * limit the queue size to a reasonable limit to avoid huge leaks. */
|
||
|
- for (;;) {
|
||
|
- block_t *block = aout_FifoPop(aout, &aout->output.fifo);
|
||
|
- if (block == NULL)
|
||
|
- break;
|
||
|
-
|
||
|
- const void *ptr = data_convert(&block);
|
||
|
- if (unlikely(ptr == NULL))
|
||
|
- break;
|
||
|
-
|
||
|
- size_t len = block->i_buffer;
|
||
|
- //mtime_t pts = block->i_pts, duration = block->i_length;
|
||
|
-
|
||
|
- if (pa_stream_write(s, ptr, len, data_free, 0, PA_SEEK_RELATIVE) < 0)
|
||
|
- {
|
||
|
- error(aout, "cannot write", sys->context);
|
||
|
- block_Release(block);
|
||
|
- }
|
||
|
+ if (pa_stream_write(s, ptr, len, data_free, 0, PA_SEEK_RELATIVE) < 0) {
|
||
|
+ error(aout, "cannot write", sys->context);
|
||
|
+ block_Release(block);
|
||
|
}
|
||
|
|
||
|
pa_threaded_mainloop_unlock(sys->mainloop);
|
||
|
}
|
||
|
|
||
|
-
|
||
|
/*****************************************************************************
|
||
|
* Open: open the audio device
|
||
|
*****************************************************************************/
|
||
|
@@ -377,21 +508,27 @@ static int Open(vlc_object_t *obj)
|
||
|
msg_Err(aout, "unsupported channel map");
|
||
|
return VLC_EGENERIC;
|
||
|
} else {
|
||
|
- const char *name = pa_channel_map_to_pretty_name(&map);
|
||
|
+ const char *name = pa_channel_map_to_name(&map);
|
||
|
msg_Dbg(aout, "using %s channel map", (name != NULL) ? name : "?");
|
||
|
}
|
||
|
|
||
|
- const pa_stream_flags_t flags = PA_STREAM_INTERPOLATE_TIMING
|
||
|
+ /* Stream parameters */
|
||
|
+ const pa_stream_flags_t flags = PA_STREAM_START_CORKED
|
||
|
+ //| PA_STREAM_INTERPOLATE_TIMING
|
||
|
| PA_STREAM_AUTO_TIMING_UPDATE
|
||
|
- | PA_STREAM_ADJUST_LATENCY
|
||
|
- | PA_STREAM_START_CORKED;
|
||
|
+ | PA_STREAM_VARIABLE_RATE;
|
||
|
|
||
|
const uint32_t byterate = pa_bytes_per_second(&ss);
|
||
|
struct pa_buffer_attr attr;
|
||
|
- /* no point in larger buffers on PA side than VLC */
|
||
|
attr.maxlength = -1;
|
||
|
- attr.tlength = byterate * AOUT_MAX_ADVANCE_TIME / CLOCK_FREQ;
|
||
|
- attr.prebuf = byterate * AOUT_MAX_PREPARE_TIME / CLOCK_FREQ;
|
||
|
+ /* PulseAudio assumes that tlength bytes are available in the buffer. Thus
|
||
|
+ * we need to be conservative and set the minimum value that the VLC
|
||
|
+ * audio decoder thread warrants. Otherwise, PulseAudio buffers will
|
||
|
+ * underrun on hardware with large buffers. VLC keeps at least
|
||
|
+ * AOUT_MIN_PREPARE and at most AOUT_MAX_PREPARE worth of audio buffers.
|
||
|
+ * TODO? tlength could be adaptively increased to reduce wakeups. */
|
||
|
+ attr.tlength = byterate * AOUT_MIN_PREPARE_TIME / CLOCK_FREQ;
|
||
|
+ attr.prebuf = 0; /* trigger manually */
|
||
|
attr.minreq = -1;
|
||
|
attr.fragsize = 0; /* not used for output */
|
||
|
|
||
|
@@ -427,6 +564,9 @@ static int Open(vlc_object_t *obj)
|
||
|
if (unlikely(ctx == NULL))
|
||
|
goto fail;
|
||
|
sys->context = ctx;
|
||
|
+ sys->pts = VLC_TS_INVALID;
|
||
|
+ sys->desync = 0;
|
||
|
+ sys->rate = ss.rate;
|
||
|
|
||
|
pa_context_set_state_callback(ctx, context_state_cb, mainloop);
|
||
|
if (pa_context_connect(ctx, NULL, 0, NULL) < 0
|
||
|
@@ -443,6 +583,7 @@ static int Open(vlc_object_t *obj)
|
||
|
}
|
||
|
sys->stream = s;
|
||
|
pa_stream_set_state_callback(s, stream_state_cb, mainloop);
|
||
|
+ pa_stream_set_latency_update_callback(s, stream_latency_cb, aout);
|
||
|
pa_stream_set_moved_callback(s, stream_moved_cb, aout);
|
||
|
pa_stream_set_overflow_callback(s, stream_overflow_cb, aout);
|
||
|
pa_stream_set_started_callback(s, stream_started_cb, aout);
|
||
|
@@ -487,19 +628,24 @@ static void Close (vlc_object_t *obj)
|
||
|
|
||
|
pa_threaded_mainloop_lock(mainloop);
|
||
|
if (s != NULL) {
|
||
|
- pa_operation *op;
|
||
|
-
|
||
|
- op = pa_stream_flush(s, NULL, NULL);
|
||
|
- if (op != NULL)
|
||
|
- pa_operation_unref(op);
|
||
|
- op = pa_stream_drain(s, NULL, NULL);
|
||
|
- if (op != NULL)
|
||
|
- pa_operation_unref(op);
|
||
|
pa_stream_disconnect(s);
|
||
|
+
|
||
|
+ /* Clear all callbacks */
|
||
|
+ pa_stream_set_state_callback(s, NULL, NULL);
|
||
|
+ pa_stream_set_latency_update_callback(s, NULL, aout);
|
||
|
+ pa_stream_set_moved_callback(s, NULL, aout);
|
||
|
+ pa_stream_set_overflow_callback(s, NULL, aout);
|
||
|
+ pa_stream_set_started_callback(s, NULL, aout);
|
||
|
+ pa_stream_set_suspended_callback(s, NULL, aout);
|
||
|
+ pa_stream_set_underflow_callback(s, NULL, aout);
|
||
|
+
|
||
|
pa_stream_unref(s);
|
||
|
}
|
||
|
- if (ctx != NULL)
|
||
|
+ if (ctx != NULL) {
|
||
|
+ pa_context_disconnect(ctx);
|
||
|
+ pa_context_set_state_callback (ctx, NULL, NULL);
|
||
|
pa_context_unref(ctx);
|
||
|
+ }
|
||
|
pa_threaded_mainloop_unlock(mainloop);
|
||
|
pa_threaded_mainloop_free(mainloop);
|
||
|
free(sys);
|
||
|
diff --git a/modules/codec/vorbis.c b/modules/codec/vorbis.c
|
||
|
index 8ef775f..d8a0cd5 100644
|
||
|
--- a/modules/codec/vorbis.c
|
||
|
+++ b/modules/codec/vorbis.c
|
||
|
@@ -570,6 +570,10 @@ static void ParseVorbisComments( decoder_t *p_dec )
|
||
|
*psz_value = '\0';
|
||
|
psz_value++;
|
||
|
|
||
|
+ /* Don't add empty values */
|
||
|
+ if( *psz_value == '\0' )
|
||
|
+ break;
|
||
|
+
|
||
|
if( !p_dec->p_description )
|
||
|
p_dec->p_description = vlc_meta_New();
|
||
|
if( p_dec->p_description )
|
||
|
diff --git a/modules/control/signals.c b/modules/control/signals.c
|
||
|
index a1e4215..b183718 100644
|
||
|
--- a/modules/control/signals.c
|
||
|
+++ b/modules/control/signals.c
|
||
|
@@ -130,16 +130,16 @@ static void *SigThread (void *data)
|
||
|
sigaction (signum, NULL, &act);
|
||
|
if ((act.sa_flags & SA_SIGINFO) || (act.sa_handler != SIG_DFL))
|
||
|
{
|
||
|
- msg_Err (obj, "signal %d overridden (%p)", signum,
|
||
|
- act.sa_handler);
|
||
|
+ msg_Warn (obj, "signal %d overridden (%p)", signum,
|
||
|
+ act.sa_handler);
|
||
|
#ifdef __GLIBC__
|
||
|
Dl_info info;
|
||
|
|
||
|
if (dladdr (act.sa_handler, &info))
|
||
|
- msg_Err (obj, " %s(%s)[%p]",
|
||
|
- info.dli_fname ? info.dli_fname : "?",
|
||
|
- info.dli_sname ? info.dli_sname : "?",
|
||
|
- info.dli_saddr);
|
||
|
+ msg_Warn (obj, " %s(%s)[%p]",
|
||
|
+ info.dli_fname ? info.dli_fname : "?",
|
||
|
+ info.dli_sname ? info.dli_sname : "?",
|
||
|
+ info.dli_saddr);
|
||
|
#endif
|
||
|
if (!(act.sa_flags & SA_SIGINFO) && (act.sa_handler != SIG_IGN))
|
||
|
act.sa_handler (signum);
|
||
|
diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c
|
||
|
index ebb8f56..20ae0e7 100644
|
||
|
--- a/modules/demux/avi/avi.c
|
||
|
+++ b/modules/demux/avi/avi.c
|
||
|
@@ -1280,15 +1280,16 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent )
|
||
|
{
|
||
|
|
||
|
demux_sys_t *p_sys = p_demux->p_sys;
|
||
|
- unsigned int i_stream;
|
||
|
msg_Dbg( p_demux, "seek requested: %"PRId64" seconds %d%%",
|
||
|
i_date / 1000000, i_percent );
|
||
|
|
||
|
if( p_sys->b_seekable )
|
||
|
{
|
||
|
+ unsigned i_stream;
|
||
|
+
|
||
|
if( !p_sys->i_length )
|
||
|
{
|
||
|
- avi_track_t *p_stream;
|
||
|
+ avi_track_t *p_stream = NULL;
|
||
|
int64_t i_pos;
|
||
|
|
||
|
/* use i_percent to create a true i_date */
|
||
|
@@ -1304,17 +1305,19 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent )
|
||
|
/* try to find chunk that is at i_percent or the file */
|
||
|
i_pos = __MAX( i_percent * stream_Size( p_demux->s ) / 100,
|
||
|
p_sys->i_movi_begin );
|
||
|
- /* search first selected stream (and prefer non eof ones) */
|
||
|
- for( i_stream = 0, p_stream = NULL;
|
||
|
- i_stream < p_sys->i_track; i_stream++ )
|
||
|
+ /* search first selected stream (and prefer non-EOF ones) */
|
||
|
+ for( unsigned i = 0; i < p_sys->i_track; i++ )
|
||
|
{
|
||
|
- if( !p_stream || p_stream->b_eof )
|
||
|
- p_stream = p_sys->track[i_stream];
|
||
|
+ avi_track_t *p_track = p_sys->track[i];
|
||
|
+ if( !p_track->b_activated )
|
||
|
+ continue;
|
||
|
|
||
|
- if( p_stream->b_activated && !p_stream->b_eof )
|
||
|
+ p_stream = p_track;
|
||
|
+ i_stream = i;
|
||
|
+ if( !p_track->b_eof )
|
||
|
break;
|
||
|
}
|
||
|
- if( !p_stream || !p_stream->b_activated )
|
||
|
+ if( p_stream == NULL )
|
||
|
{
|
||
|
msg_Warn( p_demux, "cannot find any selected stream" );
|
||
|
return VLC_EGENERIC;
|
||
|
diff --git a/modules/gui/macosx/about.m b/modules/gui/macosx/about.m
|
||
|
index e0ebf78..551d19b 100644
|
||
|
--- a/modules/gui/macosx/about.m
|
||
|
+++ b/modules/gui/macosx/about.m
|
||
|
@@ -100,8 +100,7 @@ static VLAboutBox *_o_sharedInstance = nil;
|
||
|
#else
|
||
|
compiler = [NSString stringWithFormat:@"gcc %s", __VERSION__];
|
||
|
#endif
|
||
|
- [o_revision_field setStringValue:
|
||
|
- [NSString stringWithFormat: _NS("Compiled by %s with %@"), VLC_CompileBy(), compiler]];
|
||
|
+ [o_revision_field setStringValue: [NSString stringWithFormat: _NS("Compiled by %@ with %@"), [NSString stringWithUTF8String:VLC_CompileBy()], compiler]];
|
||
|
|
||
|
/* Setup the nameversion field */
|
||
|
[o_name_version_field setStringValue: [NSString stringWithFormat:@"Version %s (%s)", VLC_Version(), PLATFORM]];
|
||
|
diff --git a/modules/gui/macosx/intf.h b/modules/gui/macosx/intf.h
|
||
|
index 7e14eea..e7e0511 100644
|
||
|
--- a/modules/gui/macosx/intf.h
|
||
|
+++ b/modules/gui/macosx/intf.h
|
||
|
@@ -104,7 +104,7 @@ struct intf_sys_t
|
||
|
id o_bookmarks; /* VLCBookmarks */
|
||
|
id o_embedded_list; /* VLCEmbeddedList*/
|
||
|
id o_coredialogs; /* VLCCoreDialogProvider */
|
||
|
- VLCInformation * o_info; /* VLCInformation */
|
||
|
+ id o_info; /* VLCInfo */
|
||
|
id o_eyetv; /* VLCEyeTVController */
|
||
|
BOOL nib_main_loaded; /* main nibfile */
|
||
|
BOOL nib_open_loaded; /* open nibfile */
|
||
|
diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m
|
||
|
index 535e9b9..bdcfdcb 100644
|
||
|
--- a/modules/gui/macosx/intf.m
|
||
|
+++ b/modules/gui/macosx/intf.m
|
||
|
@@ -2589,9 +2589,8 @@ end:
|
||
|
|
||
|
o_attr = [NSDictionary dictionaryWithObject: pp_color[i_type]
|
||
|
forKey: NSForegroundColorAttributeName];
|
||
|
- o_msg = [[[o_notification userInfo] objectForKey: @"Message"] stringByAppendingString: @"\n"];
|
||
|
- o_msg_color = [[NSAttributedString alloc]
|
||
|
- initWithString: o_msg attributes: o_attr];
|
||
|
+ o_msg = [NSString stringWithFormat:@"%@\n", [[o_notification userInfo] objectForKey: @"Message"]];
|
||
|
+ o_msg_color = [[NSAttributedString alloc] initWithString: o_msg attributes: o_attr];
|
||
|
[o_msg_arr addObject: [o_msg_color autorelease]];
|
||
|
|
||
|
b_msg_arr_changed = YES;
|
||
|
diff --git a/modules/meta_engine/taglib.cpp b/modules/meta_engine/taglib.cpp
|
||
|
index 6bc2926..6a0567a 100644
|
||
|
--- a/modules/meta_engine/taglib.cpp
|
||
|
+++ b/modules/meta_engine/taglib.cpp
|
||
|
@@ -74,6 +74,8 @@
|
||
|
# define TAGLIB_HAVE_AIFF_WAV_H
|
||
|
# include <aifffile.h>
|
||
|
# include <wavfile.h>
|
||
|
+#else
|
||
|
+# include <id3v2tag.h>
|
||
|
#endif
|
||
|
|
||
|
#if TAGLIB_VERSION >= VERSION_INT(1,6,1) && defined(TAGLIB_WITH_MP4)
|
||
|
diff --git a/modules/misc/audioscrobbler.c b/modules/misc/audioscrobbler.c
|
||
|
index 9b18f1d..95780ce 100644
|
||
|
--- a/modules/misc/audioscrobbler.c
|
||
|
+++ b/modules/misc/audioscrobbler.c
|
||
|
@@ -122,7 +122,7 @@ static int PlayingChange ( vlc_object_t *, const char *, vlc_value_t,
|
||
|
|
||
|
static void AddToQueue ( intf_thread_t * );
|
||
|
static int Handshake ( intf_thread_t * );
|
||
|
-static int ReadMetaData ( intf_thread_t * );
|
||
|
+static void ReadMetaData ( intf_thread_t * );
|
||
|
static void DeleteSong ( audioscrobbler_song_t* );
|
||
|
static int ParseURL ( char *, char **, char **, int * );
|
||
|
static void HandleInterval ( mtime_t *, unsigned int * );
|
||
|
@@ -927,7 +927,7 @@ static void DeleteSong( audioscrobbler_song_t* p_song )
|
||
|
/*****************************************************************************
|
||
|
* ReadMetaData : Read meta data when parsed by vlc
|
||
|
*****************************************************************************/
|
||
|
-static int ReadMetaData( intf_thread_t *p_this )
|
||
|
+static void ReadMetaData( intf_thread_t *p_this )
|
||
|
{
|
||
|
input_thread_t *p_input;
|
||
|
input_item_t *p_item;
|
||
|
@@ -936,81 +936,65 @@ static int ReadMetaData( intf_thread_t *p_this )
|
||
|
|
||
|
p_input = playlist_CurrentInput( pl_Get( p_this ) );
|
||
|
if( !p_input )
|
||
|
- return( VLC_SUCCESS );
|
||
|
+ return;
|
||
|
|
||
|
p_item = input_GetItem( p_input );
|
||
|
if( !p_item )
|
||
|
- return VLC_SUCCESS;
|
||
|
-
|
||
|
- char *psz_meta;
|
||
|
-#define ALLOC_ITEM_META( a, b ) \
|
||
|
- psz_meta = input_item_Get##b( p_item ); \
|
||
|
- if( psz_meta && *psz_meta ) \
|
||
|
- { \
|
||
|
- a = encode_URI_component( psz_meta ); \
|
||
|
- if( !a ) \
|
||
|
- { \
|
||
|
- vlc_mutex_unlock( &p_sys->lock ); \
|
||
|
- vlc_object_release( p_input ); \
|
||
|
- free( psz_meta ); \
|
||
|
- return VLC_ENOMEM; \
|
||
|
- } \
|
||
|
+ {
|
||
|
+ vlc_object_release( p_input );
|
||
|
+ return;
|
||
|
}
|
||
|
|
||
|
+#define ALLOC_ITEM_META( a, b ) do { \
|
||
|
+ char *psz_meta = input_item_Get##b( p_item ); \
|
||
|
+ if( psz_meta && *psz_meta ) \
|
||
|
+ a = encode_URI_component( psz_meta ); \
|
||
|
+ free( psz_meta ); \
|
||
|
+ } while(0)
|
||
|
+
|
||
|
vlc_mutex_lock( &p_sys->lock );
|
||
|
|
||
|
p_sys->b_meta_read = true;
|
||
|
|
||
|
- ALLOC_ITEM_META( p_sys->p_current_song.psz_a, Artist )
|
||
|
- else
|
||
|
+ ALLOC_ITEM_META( p_sys->p_current_song.psz_a, Artist );
|
||
|
+ if( !p_sys->p_current_song.psz_a )
|
||
|
{
|
||
|
- vlc_mutex_unlock( &p_sys->lock );
|
||
|
msg_Dbg( p_this, "No artist.." );
|
||
|
- vlc_object_release( p_input );
|
||
|
- free( psz_meta );
|
||
|
- return VLC_EGENERIC;
|
||
|
+ DeleteSong( &p_sys->p_current_song );
|
||
|
+ goto end;
|
||
|
}
|
||
|
- free( psz_meta );
|
||
|
|
||
|
- ALLOC_ITEM_META( p_sys->p_current_song.psz_t, Title )
|
||
|
- else
|
||
|
+ ALLOC_ITEM_META( p_sys->p_current_song.psz_t, Title );
|
||
|
+ if( !p_sys->p_current_song.psz_t )
|
||
|
{
|
||
|
- vlc_mutex_unlock( &p_sys->lock );
|
||
|
msg_Dbg( p_this, "No track name.." );
|
||
|
- vlc_object_release( p_input );
|
||
|
- free( p_sys->p_current_song.psz_a );
|
||
|
- free( psz_meta );
|
||
|
- return VLC_EGENERIC;
|
||
|
+ DeleteSong( &p_sys->p_current_song );
|
||
|
+ goto end;
|
||
|
}
|
||
|
- free( psz_meta );
|
||
|
|
||
|
/* Now we have read the mandatory meta data, so we can submit that info */
|
||
|
p_sys->b_submit = true;
|
||
|
|
||
|
- ALLOC_ITEM_META( p_sys->p_current_song.psz_b, Album )
|
||
|
- else
|
||
|
+ ALLOC_ITEM_META( p_sys->p_current_song.psz_b, Album );
|
||
|
+ if( !p_sys->p_current_song.psz_b )
|
||
|
p_sys->p_current_song.psz_b = calloc( 1, 1 );
|
||
|
- free( psz_meta );
|
||
|
|
||
|
- ALLOC_ITEM_META( p_sys->p_current_song.psz_m, TrackID )
|
||
|
- else
|
||
|
+ ALLOC_ITEM_META( p_sys->p_current_song.psz_m, TrackID );
|
||
|
+ if( !p_sys->p_current_song.psz_m )
|
||
|
p_sys->p_current_song.psz_m = calloc( 1, 1 );
|
||
|
- free( psz_meta );
|
||
|
|
||
|
p_sys->p_current_song.i_l = input_item_GetDuration( p_item ) / 1000000;
|
||
|
|
||
|
- ALLOC_ITEM_META( p_sys->p_current_song.psz_n, TrackNum )
|
||
|
- else
|
||
|
+ ALLOC_ITEM_META( p_sys->p_current_song.psz_n, TrackNum );
|
||
|
+ if( !p_sys->p_current_song.psz_n )
|
||
|
p_sys->p_current_song.psz_n = calloc( 1, 1 );
|
||
|
- free( psz_meta );
|
||
|
#undef ALLOC_ITEM_META
|
||
|
|
||
|
msg_Dbg( p_this, "Meta data registered" );
|
||
|
|
||
|
+end:
|
||
|
vlc_mutex_unlock( &p_sys->lock );
|
||
|
vlc_object_release( p_input );
|
||
|
- return VLC_SUCCESS;
|
||
|
-
|
||
|
}
|
||
|
|
||
|
static void HandleInterval( mtime_t *next, unsigned int *i_interval )
|
||
|
diff --git a/modules/misc/gnutls.c b/modules/misc/gnutls.c
|
||
|
index 71876b5..328e019 100644
|
||
|
--- a/modules/misc/gnutls.c
|
||
|
+++ b/modules/misc/gnutls.c
|
||
|
@@ -130,7 +130,7 @@ static int gnutls_Init (vlc_object_t *p_this)
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
- const char *psz_version = gnutls_check_version ("1.3.3");
|
||
|
+ const char *psz_version = gnutls_check_version ("1.7.4");
|
||
|
if (psz_version == NULL)
|
||
|
{
|
||
|
msg_Err (p_this, "unsupported GnuTLS version");
|
||
|
@@ -356,8 +356,8 @@ gnutls_HandshakeAndValidate( tls_session_t *session )
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
- assert( p_sys->psz_hostname != NULL );
|
||
|
- if ( !gnutls_x509_crt_check_hostname( cert, p_sys->psz_hostname ) )
|
||
|
+ if( p_sys->psz_hostname != NULL
|
||
|
+ && !gnutls_x509_crt_check_hostname( cert, p_sys->psz_hostname ) )
|
||
|
{
|
||
|
msg_Err( session, "Certificate does not match \"%s\"",
|
||
|
p_sys->psz_hostname );
|
||
|
@@ -731,7 +731,7 @@ static int OpenClient (vlc_object_t *obj)
|
||
|
|
||
|
char *servername = var_GetNonEmptyString (p_session, "tls-server-name");
|
||
|
if (servername == NULL )
|
||
|
- msg_Err (p_session, "server name missing for TLS session");
|
||
|
+ abort ();
|
||
|
else
|
||
|
gnutls_server_name_set (p_sys->session.session, GNUTLS_NAME_DNS,
|
||
|
servername, strlen (servername));
|
||
|
@@ -1046,7 +1046,7 @@ gnutls_ServerAddCRL( tls_server_t *p_server, const char *psz_crl_path )
|
||
|
(p_server->p_sys))->x509_cred,
|
||
|
psz_local_path,
|
||
|
GNUTLS_X509_FMT_PEM );
|
||
|
- LocaleFree( psz_crl_path );
|
||
|
+ LocaleFree( psz_local_path );
|
||
|
if( val < 0 )
|
||
|
{
|
||
|
msg_Err( p_server, "cannot add CRL (%s): %s", psz_crl_path,
|
||
|
diff --git a/modules/stream_out/rtp.c b/modules/stream_out/rtp.c
|
||
|
index e6a247a..954a3c1 100644
|
||
|
--- a/modules/stream_out/rtp.c
|
||
|
+++ b/modules/stream_out/rtp.c
|
||
|
@@ -42,6 +42,8 @@
|
||
|
#include <vlc_rand.h>
|
||
|
#ifdef HAVE_SRTP
|
||
|
# include <srtp.h>
|
||
|
+# include <gcrypt.h>
|
||
|
+# include <vlc_gcrypt.h>
|
||
|
#endif
|
||
|
|
||
|
#include "rtp.h"
|
||
|
@@ -1006,6 +1008,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
|
||
|
char *key = var_CreateGetNonEmptyString (p_stream, SOUT_CFG_PREFIX"key");
|
||
|
if (key)
|
||
|
{
|
||
|
+ vlc_gcrypt_init ();
|
||
|
id->srtp = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 10,
|
||
|
SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
|
||
|
if (id->srtp == NULL)
|
||
|
diff --git a/modules/stream_out/smem.c b/modules/stream_out/smem.c
|
||
|
index 784c31b..59f27cf 100644
|
||
|
--- a/modules/stream_out/smem.c
|
||
|
+++ b/modules/stream_out/smem.c
|
||
|
@@ -369,6 +369,13 @@ static int SendAudio( sout_stream_t *p_stream, sout_stream_id_t *id,
|
||
|
int i_samples = 0;
|
||
|
|
||
|
i_size = p_buffer->i_buffer;
|
||
|
+ if (id->format->audio.i_channels <= 0)
|
||
|
+ {
|
||
|
+ msg_Warn( p_stream, "No buffer given!" );
|
||
|
+ block_ChainRelease( p_buffer );
|
||
|
+ return VLC_EGENERIC;
|
||
|
+ }
|
||
|
+
|
||
|
i_samples = i_size / ( ( id->format->audio.i_bitspersample / 8 ) * id->format->audio.i_channels );
|
||
|
/* Calling the prerender callback to get user buffer */
|
||
|
p_sys->pf_audio_prerender_callback( id->p_data, &p_pcm_buffer, i_size );
|
||
|
diff --git a/modules/video_filter/Modules.am b/modules/video_filter/Modules.am
|
||
|
index c07f263..afa6330 100644
|
||
|
--- a/modules/video_filter/Modules.am
|
||
|
+++ b/modules/video_filter/Modules.am
|
||
|
@@ -1,4 +1,5 @@
|
||
|
SUBDIRS = dynamicoverlay
|
||
|
+
|
||
|
SOURCES_mosaic = mosaic.c mosaic.h
|
||
|
SOURCES_transform = transform.c
|
||
|
SOURCES_invert = invert.c
|
||
|
@@ -17,7 +18,13 @@ SOURCES_marq = marq.c
|
||
|
SOURCES_rss = rss.c
|
||
|
SOURCES_motiondetect = motiondetect.c
|
||
|
SOURCES_rv32 = rv32.c
|
||
|
-SOURCES_osdmenu = osdmenu.c
|
||
|
+
|
||
|
+libosdmenu_plugin_la_SOURCES = osdmenu.c
|
||
|
+libosdmenu_plugin_la_CFLAGS = $(AM_CFLAGS) -DPKGDATADIR=\"$(vlcdatadir)\"
|
||
|
+libosdmenu_plugin_la_LIBADD = $(AM_LIBADD)
|
||
|
+libosdmenu_plugin_la_DEPENDENCIES =
|
||
|
+EXTRA_LTLIBRARIES += libosdmenu_plugin.la
|
||
|
+
|
||
|
SOURCES_remoteosd = remoteosd.c remoteosd_rfbproto.h
|
||
|
SOURCES_magnify = magnify.c
|
||
|
SOURCES_wave = wave.c
|
||
|
diff --git a/modules/video_filter/osdmenu.c b/modules/video_filter/osdmenu.c
|
||
|
index 377f740..87416bf 100644
|
||
|
--- a/modules/video_filter/osdmenu.c
|
||
|
+++ b/modules/video_filter/osdmenu.c
|
||
|
@@ -105,7 +105,7 @@ static int MouseEvent( vlc_object_t *, char const *,
|
||
|
#if defined( WIN32 ) || defined( UNDER_CE )
|
||
|
#define OSD_DEFAULT_CFG "osdmenu/default.cfg"
|
||
|
#else
|
||
|
-#define OSD_DEFAULT_CFG "share/osdmenu/default.cfg"
|
||
|
+#define OSD_DEFAULT_CFG PKGDATADIR"/osdmenu/default.cfg"
|
||
|
#endif
|
||
|
|
||
|
#define OSD_UPDATE_MIN 0
|
||
|
diff --git a/modules/video_output/msw/events.c b/modules/video_output/msw/events.c
|
||
|
index d2d5e26..3a40829 100644
|
||
|
--- a/modules/video_output/msw/events.c
|
||
|
+++ b/modules/video_output/msw/events.c
|
||
|
@@ -122,6 +122,8 @@ struct event_thread_t
|
||
|
video_format_t source;
|
||
|
vout_display_place_t place;
|
||
|
|
||
|
+ HICON vlc_icon;
|
||
|
+
|
||
|
bool has_moved;
|
||
|
};
|
||
|
|
||
|
@@ -498,7 +500,6 @@ static int DirectXCreateWindow( event_thread_t *p_event )
|
||
|
HMENU hMenu;
|
||
|
RECT rect_window;
|
||
|
WNDCLASS wc; /* window class components */
|
||
|
- HICON vlc_icon;
|
||
|
char vlc_path[MAX_PATH+1];
|
||
|
int i_style, i_stylex;
|
||
|
|
||
|
@@ -537,11 +538,11 @@ static int DirectXCreateWindow( event_thread_t *p_event )
|
||
|
#endif
|
||
|
|
||
|
/* Get the Icon from the main app */
|
||
|
- vlc_icon = NULL;
|
||
|
+ p_event->vlc_icon = NULL;
|
||
|
#ifndef UNDER_CE
|
||
|
if( GetModuleFileName( NULL, vlc_path, MAX_PATH ) )
|
||
|
{
|
||
|
- vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
|
||
|
+ p_event->vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
@@ -551,7 +552,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
|
||
|
wc.cbClsExtra = 0; /* no extra class data */
|
||
|
wc.cbWndExtra = 0; /* no extra window data */
|
||
|
wc.hInstance = hInstance; /* instance */
|
||
|
- wc.hIcon = vlc_icon; /* load the vlc big icon */
|
||
|
+ wc.hIcon = p_event->vlc_icon; /* load the vlc big icon */
|
||
|
wc.hCursor = p_event->is_cursor_hidden ? p_event->cursor_empty :
|
||
|
p_event->cursor_arrow;
|
||
|
wc.hbrBackground = GetStockObject(BLACK_BRUSH); /* background color */
|
||
|
@@ -561,8 +562,8 @@ static int DirectXCreateWindow( event_thread_t *p_event )
|
||
|
/* Register the window class */
|
||
|
if( !RegisterClass(&wc) )
|
||
|
{
|
||
|
- if( vlc_icon )
|
||
|
- DestroyIcon( vlc_icon );
|
||
|
+ if( p_event->vlc_icon )
|
||
|
+ DestroyIcon( p_event->vlc_icon );
|
||
|
|
||
|
msg_Err( vd, "DirectXCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() );
|
||
|
return VLC_EGENERIC;
|
||
|
@@ -607,6 +608,12 @@ static int DirectXCreateWindow( event_thread_t *p_event )
|
||
|
{
|
||
|
i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD;
|
||
|
i_stylex = 0;
|
||
|
+
|
||
|
+ /* allow user to regain control over input events if requested */
|
||
|
+ bool b_mouse_support = var_InheritBool( vd, "mouse-events" );
|
||
|
+ bool b_key_support = var_InheritBool( vd, "keyboard-events" );
|
||
|
+ if( !b_mouse_support && !b_key_support )
|
||
|
+ i_style |= WS_DISABLED;
|
||
|
}
|
||
|
|
||
|
p_event->i_window_style = i_style;
|
||
|
@@ -711,6 +718,9 @@ static void DirectXCloseWindow( event_thread_t *p_event )
|
||
|
vout_display_DeleteWindow( vd, p_event->parent_window );
|
||
|
p_event->hwnd = NULL;
|
||
|
|
||
|
+ if( p_event->vlc_icon )
|
||
|
+ DestroyIcon( p_event->vlc_icon );
|
||
|
+
|
||
|
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||
|
UnregisterClass( p_event->class_video, hInstance );
|
||
|
UnregisterClass( p_event->class_main, hInstance );
|
||
|
diff --git a/modules/video_output/xcb/xvideo.c b/modules/video_output/xcb/xvideo.c
|
||
|
index 356f3c5..d899a17 100644
|
||
|
--- a/modules/video_output/xcb/xvideo.c
|
||
|
+++ b/modules/video_output/xcb/xvideo.c
|
||
|
@@ -297,10 +297,11 @@ FindFormat (vout_display_t *vd,
|
||
|
static int Open (vlc_object_t *obj)
|
||
|
{
|
||
|
vout_display_t *vd = (vout_display_t *)obj;
|
||
|
- vout_display_sys_t *p_sys = malloc (sizeof (*p_sys));
|
||
|
+ vout_display_sys_t *p_sys;
|
||
|
|
||
|
if (!var_CreateGetBool (obj, "overlay"))
|
||
|
return VLC_EGENERIC;
|
||
|
+ p_sys = malloc (sizeof (*p_sys));
|
||
|
if (p_sys == NULL)
|
||
|
return VLC_ENOMEM;
|
||
|
|
||
|
diff --git a/src/control/audio.c b/src/control/audio.c
|
||
|
index edde5b7..90333a8 100644
|
||
|
--- a/src/control/audio.c
|
||
|
+++ b/src/control/audio.c
|
||
|
@@ -266,9 +266,9 @@ void libvlc_audio_output_device_set( libvlc_media_player_t *mp,
|
||
|
return;
|
||
|
if( asprintf( &psz_config_name, "%s-audio-device", psz_audio_output ) == -1 )
|
||
|
return;
|
||
|
- if( !var_Type( mp, psz_audio_output ) )
|
||
|
+ if( !var_Type( mp, psz_config_name ) )
|
||
|
/* Don't recreate the same variable over and over and over... */
|
||
|
- var_Create( mp, psz_audio_output, VLC_VAR_STRING );
|
||
|
+ var_Create( mp, psz_config_name, VLC_VAR_STRING );
|
||
|
var_SetString( mp, psz_config_name, psz_device_id );
|
||
|
free( psz_config_name );
|
||
|
}
|
||
|
diff --git a/src/input/demux.c b/src/input/demux.c
|
||
|
index 981799f..ab01a13 100644
|
||
|
--- a/src/input/demux.c
|
||
|
+++ b/src/input/demux.c
|
||
|
@@ -162,8 +162,9 @@ demux_t *__demux_New( vlc_object_t *p_obj, input_thread_t *p_parent_input,
|
||
|
/* ID3/APE tags will mess-up demuxer probing so we skip it here.
|
||
|
* ID3/APE parsers will called later on in the demuxer to access the
|
||
|
* skipped info. */
|
||
|
- if( !SkipID3Tag( p_demux ) )
|
||
|
- SkipAPETag( p_demux );
|
||
|
+ while (SkipID3Tag( p_demux ))
|
||
|
+ ;
|
||
|
+ SkipAPETag( p_demux );
|
||
|
|
||
|
p_demux->p_module =
|
||
|
module_need( p_demux, "demux", psz_module,
|
||
|
diff --git a/libs/srtp/Makefile.am b/libs/srtp/Makefile.am
|
||
|
index 8b7522b..b90bed1 100644
|
||
|
--- a/libs/srtp/Makefile.am
|
||
|
+++ b/libs/srtp/Makefile.am
|
||
|
@@ -32,11 +32,6 @@ srtp_LDADD = libvlc_srtp.la
|
||
|
test_recv_LDADD = libvlc_srtp.la
|
||
|
test_aes_LDADD = @GCRYPT_LIBS@
|
||
|
|
||
|
-if !HAVE_WIN32
|
||
|
-libvlc_srtp_la_LIBADD += -lpthread
|
||
|
-test_aes_LDADD += -lpthread
|
||
|
-endif
|
||
|
-
|
||
|
lcov-run:
|
||
|
rm -Rf *.gcda lcov
|
||
|
$(MAKE) $(AM_MAKEFLAGS) check
|
||
|
diff --git a/libs/srtp/srtp.c b/libs/srtp/srtp.c
|
||
|
index f2f2c95..766834c 100644
|
||
|
--- a/libs/srtp/srtp.c
|
||
|
+++ b/libs/srtp/srtp.c
|
||
|
@@ -43,8 +43,6 @@
|
||
|
# include <winsock2.h>
|
||
|
#else
|
||
|
# include <netinet/in.h>
|
||
|
-# include <pthread.h>
|
||
|
-GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
||
|
#endif
|
||
|
|
||
|
#define debug( ... ) (void)0
|
||
|
@@ -86,41 +84,6 @@ static inline unsigned rcc_mode (const srtp_session_t *s)
|
||
|
return (s->flags >> 4) & 3;
|
||
|
}
|
||
|
|
||
|
-static bool libgcrypt_usable = false;
|
||
|
-
|
||
|
-static void initonce_libgcrypt (void)
|
||
|
-{
|
||
|
-#ifndef WIN32
|
||
|
- gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
|
||
|
-#endif
|
||
|
-
|
||
|
- if ((gcry_check_version ("1.1.94") == NULL)
|
||
|
- || gcry_control (GCRYCTL_DISABLE_SECMEM, 0)
|
||
|
- || gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0))
|
||
|
- return;
|
||
|
-
|
||
|
- libgcrypt_usable = true;
|
||
|
-}
|
||
|
-
|
||
|
-static int init_libgcrypt (void)
|
||
|
-{
|
||
|
- int retval;
|
||
|
-#ifndef WIN32
|
||
|
- static pthread_once_t once = PTHREAD_ONCE_INIT;
|
||
|
-
|
||
|
- pthread_once (&once, initonce_libgcrypt);
|
||
|
-#else
|
||
|
-# warning FIXME: This is not thread-safe.
|
||
|
- if (!libgcrypt_usable)
|
||
|
- initonce_libgcrypt ();
|
||
|
-#endif
|
||
|
-
|
||
|
- retval = libgcrypt_usable ? 0 : -1;
|
||
|
-
|
||
|
- return retval;
|
||
|
-
|
||
|
-}
|
||
|
-
|
||
|
|
||
|
static void proto_destroy (srtp_proto_t *p)
|
||
|
{
|
||
|
@@ -170,7 +133,7 @@ static int proto_create (srtp_proto_t *p, int gcipher, int gmd)
|
||
|
srtp_session_t *
|
||
|
srtp_create (int encr, int auth, unsigned tag_len, int prf, unsigned flags)
|
||
|
{
|
||
|
- if ((flags & ~SRTP_FLAGS_MASK) || init_libgcrypt ())
|
||
|
+ if ((flags & ~SRTP_FLAGS_MASK))
|
||
|
return NULL;
|
||
|
|
||
|
int cipher, md;
|
||
|
@@ -833,7 +796,7 @@ srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
|
||
|
|
||
|
len += 4; /* Digests SRTCP index too */
|
||
|
|
||
|
- const uint8_t *tag = rtcp_digest (s->rtp.mac, buf, len);
|
||
|
+ const uint8_t *tag = rtcp_digest (s->rtcp.mac, buf, len);
|
||
|
memcpy (buf + len, tag, s->tag_len);
|
||
|
*lenp = len + s->tag_len;
|
||
|
return 0;
|
||
|
@@ -861,7 +824,7 @@ srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
|
||
|
return EINVAL;
|
||
|
len -= s->tag_len;
|
||
|
|
||
|
- const uint8_t *tag = rtcp_digest (s->rtp.mac, buf, len);
|
||
|
+ const uint8_t *tag = rtcp_digest (s->rtcp.mac, buf, len);
|
||
|
if (memcmp (buf + len, tag, s->tag_len))
|
||
|
return EACCES;
|
||
|
|
||
|
diff --git a/libs/srtp/srtp.h b/libs/srtp/srtp.h
|
||
|
index b58b9d6..67e8026 100644
|
||
|
--- a/libs/srtp/srtp.h
|
||
|
+++ b/libs/srtp/srtp.h
|
||
|
@@ -24,36 +24,36 @@ typedef struct srtp_session_t srtp_session_t;
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
- SRTP_UNENCRYPTED=0x1, // do not encrypt SRTP packets
|
||
|
- SRTCP_UNENCRYPTED=0x2, // do not encrypt SRTCP packets
|
||
|
- SRTP_UNAUTHENTICATED=0x4, // authenticate only SRTCP packets
|
||
|
+ SRTP_UNENCRYPTED=0x1, //< do not encrypt SRTP packets
|
||
|
+ SRTCP_UNENCRYPTED=0x2, //< do not encrypt SRTCP packets
|
||
|
+ SRTP_UNAUTHENTICATED=0x4, //< authenticate only SRTCP packets
|
||
|
|
||
|
- SRTP_RCC_MODE1=0x10, // use Roll-over-Counter Carry mode 1
|
||
|
- SRTP_RCC_MODE2=0x20, // use Roll-over-Counter Carry mode 2
|
||
|
- SRTP_RCC_MODE3=0x30, // use Roll-over-Counter Carry mode 3 (insecure)
|
||
|
+ SRTP_RCC_MODE1=0x10, //< use Roll-over-Counter Carry mode 1
|
||
|
+ SRTP_RCC_MODE2=0x20, //< use Roll-over-Counter Carry mode 2
|
||
|
+ SRTP_RCC_MODE3=0x30, //< use Roll-over-Counter Carry mode 3 (insecure)
|
||
|
|
||
|
- SRTP_FLAGS_MASK=0x38
|
||
|
+ SRTP_FLAGS_MASK=0x37 //< mask for valid flags
|
||
|
};
|
||
|
|
||
|
-/* SRTP encryption algorithms (ciphers); same values as MIKEY */
|
||
|
+/** SRTP encryption algorithms (ciphers); same values as MIKEY */
|
||
|
enum
|
||
|
{
|
||
|
- SRTP_ENCR_NULL=0,
|
||
|
- SRTP_ENCR_AES_CM=1,
|
||
|
- SRTP_ENCR_AES_F8=2 // not implemented
|
||
|
+ SRTP_ENCR_NULL=0, //< no encryption
|
||
|
+ SRTP_ENCR_AES_CM=1, //< AES counter mode
|
||
|
+ SRTP_ENCR_AES_F8=2, //< AES F8 mode (not implemented)
|
||
|
};
|
||
|
|
||
|
-/* SRTP authenticaton algorithms; same values as MIKEY */
|
||
|
+/** SRTP authenticaton algorithms; same values as MIKEY */
|
||
|
enum
|
||
|
{
|
||
|
- SRTP_AUTH_NULL=0,
|
||
|
- SRTP_AUTH_HMAC_SHA1=1
|
||
|
+ SRTP_AUTH_NULL=0, //< no authentication code
|
||
|
+ SRTP_AUTH_HMAC_SHA1=1, //< HMAC-SHA1
|
||
|
};
|
||
|
|
||
|
-/* SRTP pseudo random function; same values as MIKEY */
|
||
|
+/** SRTP pseudo random function; same values as MIKEY */
|
||
|
enum
|
||
|
{
|
||
|
- SRTP_PRF_AES_CM=0
|
||
|
+ SRTP_PRF_AES_CM=0, //< AES counter mode
|
||
|
};
|
||
|
|
||
|
# ifdef __cplusplus
|
||
|
diff --git a/libs/srtp/test-aes.c b/libs/srtp/test-aes.c
|
||
|
index 463f0b1..ae55f34 100644
|
||
|
--- a/libs/srtp/test-aes.c
|
||
|
+++ b/libs/srtp/test-aes.c
|
||
|
@@ -143,8 +143,6 @@ static void test_keystream (void)
|
||
|
|
||
|
static void srtp_test (void)
|
||
|
{
|
||
|
- if (init_libgcrypt ())
|
||
|
- fatal ("Libgcrypt initialization error");
|
||
|
test_derivation ();
|
||
|
test_keystream ();
|
||
|
}
|