[vlc-devel] [PATCH 1/3] qtsound: added audio capture functionality for MAC OS X

Michael Feurstein michael.feurstein at gmail.com
Thu Sep 22 20:33:04 CEST 2011


Tested with Built-in Input, Built-in Microphone and Griffin iMic USB system
Usage: qtsound://"Built-In Input" or qtsound://"iMic USB audio system"
---
 configure.ac              |   13 +
 modules/access/Modules.am |    1 +
 modules/access/qtsound.m  |  562 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 576 insertions(+), 0 deletions(-)
 create mode 100644 modules/access/qtsound.m

diff --git a/configure.ac b/configure.ac
index f2ce200..501275d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3806,6 +3806,19 @@ then
   VLC_ADD_PLUGIN([qtcapture])
 fi
 
+AC_ARG_ENABLE(macosx-qtsound,
+  [  --enable-macosx-qtsound Mac OS X qtsound (input) module (default enabled on Mac OS X)])
+if test "x${enable_macosx_qtsound}" != "xno" &&
+  (test "${SYS}" = "darwin" || test "${enable_macosx_qtsound}" = "yes")
+then
+  VLC_ADD_LIBS([qtsound], [-Wl,-framework,Cocoa])
+  VLC_ADD_LIBS([qtsound], [-Wl,-framework,QTKit])
+  VLC_ADD_LIBS([qtsound], [-Wl,-framework,CoreAudio])
+  VLC_ADD_LIBS([qtsound], [-Wl,-framework,QuartzCore])
+  VLC_ADD_LIBS([qtsound], [-Wl,-framework,CoreVideo])
+  VLC_ADD_PLUGIN([qtsound])
+fi
+
 AC_ARG_ENABLE(macosx-eyetv,
   [  --enable-macosx-eyetv   Mac OS X EyeTV (TNT Tuner) module (default enabled on Mac OS X)])
 if test "x${enable_macosx_eyetv}" != "xno" &&
diff --git a/modules/access/Modules.am b/modules/access/Modules.am
index 8b4d22d..b81b2dc 100644
--- a/modules/access/Modules.am
+++ b/modules/access/Modules.am
@@ -56,6 +56,7 @@ SOURCES_dvdread = dvdread.c
 SOURCES_dc1394 = dc1394.c
 SOURCES_pvr = pvr.c
 SOURCES_qtcapture = qtcapture.m
+SOURCES_qtsound = qtsound.m
 SOURCES_linsys_sdi = linsys/linsys_sdi.c linsys/linsys_sdi.h
 SOURCES_linsys_hdsdi = \
 	linsys/linsys_hdsdi.c \
diff --git a/modules/access/qtsound.m b/modules/access/qtsound.m
new file mode 100644
index 0000000..0239a97
--- /dev/null
+++ b/modules/access/qtsound.m
@@ -0,0 +1,562 @@
+/*****************************************************************************
+* qtcapture.m: qtkit (Mac OS X) based capture module
+*****************************************************************************
+* Copyright (C) 2008 the VideoLAN team
+*
+* Authors: Pierre d'Herbemont <pdherbemont at videolan.org>
+*
+*****************************************************************************
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2 of the License.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+
+#include <vlc_demux.h>
+#include <vlc_dialog.h>
+
+#import <QTKit/QTKit.h>
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this );
+static void Close( vlc_object_t *p_this );
+static int Demux( demux_t *p_demux );
+static int Control( demux_t *, int, va_list );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+vlc_module_begin()
+set_shortname( N_("Quicktime Sound Capture") )
+set_description( N_("Quicktime Sound Capture") )
+set_category( CAT_INPUT )
+set_subcategory( SUBCAT_INPUT_ACCESS )
+add_shortcut( "qtsound" )
+set_capability( "access_demux", 10 )
+set_callbacks( Open, Close )
+vlc_module_end ()
+
+
+/*****************************************************************************
+ * QTKit Bridge
+ *****************************************************************************/
+ at interface VLCDecompressedAudioOutput : QTCaptureDecompressedAudioOutput
+{
+	AudioBuffer *currentAudioBuffer;
+	int lenghtForAllSamples, numberOfSamples;
+    mtime_t currentPts;
+    mtime_t previousPts;
+}
+- (id)init;
+- (void)outputAudioSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection;
+- (mtime_t)copyCurrentAudioBytesToBuffer:(void *)buffer;
+ at end
+
+ at implementation VLCDecompressedAudioOutput : QTCaptureDecompressedAudioOutput
+- (id)init
+{
+    if( self = [super init] )
+    {
+        currentAudioBuffer = nil;
+        currentPts = 0;
+        previousPts = 0;
+    }
+    return self;
+}
+- (void)dealloc
+{
+    @synchronized (self)
+    {
+		if (currentAudioBuffer) 
+		{
+			free(currentAudioBuffer);
+			currentAudioBuffer = nil;
+		}
+    }
+    [super dealloc];
+}
+
+- (void)outputAudioSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection
+{
+	AudioBufferList *tempAudioBufferList;
+	NSMutableData *rawAudioData;
+	int audioDataSize = 0;
+	int count = 0;
+
+	@synchronized (self)
+    {
+		currentPts = (mtime_t)(1000000L / [sampleBuffer presentationTime].timeScale * [sampleBuffer presentationTime].timeValue);
+
+		tempAudioBufferList = [sampleBuffer audioBufferListWithOptions:0];
+		if (tempAudioBufferList->mNumberBuffers > 1)
+		{
+			for ( count = 0; count < tempAudioBufferList->mNumberBuffers; count++ ) 
+			{
+				audioDataSize += tempAudioBufferList->mBuffers[count].mDataByteSize;
+			}
+			rawAudioData = malloc(audioDataSize * 2);
+		}
+
+		/* transcode raw data */
+		if ( audioDataSize ) 
+		{
+			int i;
+			/* mono (built-in mic, built-in input)
+			 tested with 1.2-git version - works
+			 */
+			float *p_mono;
+			signed short *p_raw = (signed short *)rawAudioData;
+
+			for (count = 0; count < tempAudioBufferList->mNumberBuffers; count++) 
+			{
+				for ( i = 0, p_mono = (float *) tempAudioBufferList->mBuffers[count].mData; i < 512; i++ )
+				{
+					*p_raw = (signed short)(round((*p_mono) * 32767.00));
+					p_mono ++;
+					p_raw ++;
+				}
+			}
+
+			/* this one works with griffin iMic which is stereo
+			 tested with 1.1.11 source ball - works
+			 tested with 1.2-git - seems broken
+			 */
+			/*
+			float *b1Ptr, *b2Ptr;
+			signed short *uPtr;
+
+			for (i = 0,
+				 uPtr = (signed short *)rawAudioData,
+				 b1Ptr = (float *) tempAudioBufferList->mBuffers[0].mData,
+				 b2Ptr = (float *) tempAudioBufferList->mBuffers[1].mData;
+				 i < 512; i++) 
+			 {
+				*uPtr = (signed short)(round((*b1Ptr) * 32767.00));
+				uPtr ++;
+				b1Ptr ++;
+				*uPtr = (signed short)(round((*b2Ptr) * 32767.00));
+				uPtr ++;
+				b2Ptr ++;
+			}
+			 */
+
+			if (currentAudioBuffer == nil) 
+			{
+				currentAudioBuffer = (AudioBuffer *)malloc(sizeof(AudioBuffer));
+				if (NULL == currentAudioBuffer) {
+					free(rawAudioData);
+					return;
+				}
+			}
+			currentAudioBuffer->mNumberChannels = 2;
+			currentAudioBuffer->mDataByteSize = audioDataSize;
+			currentAudioBuffer->mData = rawAudioData;
+		}
+    }
+}
+
+- (mtime_t)copyCurrentAudioBytesToBuffer:(void *)buffer
+{
+	AudioBuffer *audioBuffer;
+    mtime_t pts;
+
+    if( !currentAudioBuffer || currentPts == previousPts )
+	{
+		return 0;
+	}
+
+    @synchronized (self)
+    {
+		pts = previousPts = currentPts;
+		/* copy raw data */
+		memcpy( buffer, currentAudioBuffer->mData, currentAudioBuffer->mDataByteSize );
+    }
+
+	if(currentAudioBuffer->mData)
+		return currentPts;
+	else
+		return 0;
+}
+
+
+ at end
+
+/*****************************************************************************
+ * Struct
+ *****************************************************************************/
+
+struct demux_sys_t {
+    QTCaptureSession * session;
+	QTCaptureDevice * audiodevice;
+	VLCDecompressedAudioOutput * audiooutput;
+	int i_audio_max_buffer_size;
+	block_t *p_block_audio;
+	es_out_id_t *p_es_audio;
+};
+
+/*****************************************************************************
+ * Open: initialize interface
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+    demux_t     *p_demux = (demux_t*)p_this;
+    demux_sys_t *p_sys = NULL;
+	es_format_t audiofmt;
+    int i;
+    int result = 0;
+	char *psz_uid = NULL;
+
+    /* Only when selected */
+    if( *p_demux->psz_access == '\0' )
+        return VLC_EGENERIC;
+
+	if(p_demux->psz_location && *p_demux->psz_location ){
+        psz_uid = strdup(p_demux->psz_location);
+    }
+    msg_Dbg( p_demux, "qtsound uid = %s", psz_uid );
+    NSString *qtk_curraudiodevice_uid = [[NSString alloc] initWithFormat:@"%s", psz_uid];
+
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+    /* Set up p_demux */
+    p_demux->pf_demux = Demux;
+    p_demux->pf_control = Control;
+    p_demux->info.i_update = 0;
+    p_demux->info.i_title = 0;
+    p_demux->info.i_seekpoint = 0;
+
+    p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
+    if( !p_sys )
+        return VLC_ENOMEM;
+
+    msg_Dbg( p_demux, "qtsound : uid = %s", [qtk_curraudiodevice_uid UTF8String]);
+	NSArray *myAudioDevices = [[[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeSound] arrayByAddingObjectsFromArray:[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeMuxed]] retain];
+    if([myAudioDevices count] == 0)
+    {
+        dialog_FatalWait( p_demux, _("No Audio Input device found"),
+						 _("Your Mac does not seem to be equipped with a suitable audio input device. "
+						   "Please check your connectors and drivers.") );
+        msg_Err( p_demux, "Can't find any Audio device" );
+
+        goto error;
+    }
+    int iaudio;
+    for(iaudio = 0; iaudio < [myAudioDevices count]; iaudio++){
+        QTCaptureDevice *qtk_audioDevice;
+        qtk_audioDevice = [myAudioDevices objectAtIndex:iaudio];
+        msg_Dbg( p_demux, "qtsound audio %d/%d localizedDisplayName: %s uniqueID: %s", iaudio, [myAudioDevices count], [[qtk_audioDevice localizedDisplayName] UTF8String], [[qtk_audioDevice uniqueID] UTF8String]);
+        if([[[qtk_audioDevice localizedDisplayName]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:qtk_curraudiodevice_uid]){
+            msg_Dbg( p_demux, "Device found" );
+			break;
+        }
+    }
+
+	memset( &audiofmt, 0, sizeof( es_format_t ) );
+
+	QTCaptureDeviceInput * audioInput = nil;
+    NSError *o_returnedAudioError;
+    if(iaudio < [myAudioDevices count]){
+		p_sys->audiodevice = [myAudioDevices objectAtIndex:iaudio];
+	}
+	else
+    {
+        /* cannot find designated audio device, fall back to open default audio device */
+        msg_Dbg(p_demux, "Cannot find designated uid audio device as %s. Fall back to open default audio device.", [qtk_curraudiodevice_uid UTF8String]);
+        p_sys->audiodevice = [QTCaptureDevice defaultInputDeviceWithMediaType: QTMediaTypeSound];
+    }
+    if( !p_sys->audiodevice )
+    {
+        dialog_FatalWait( p_demux, _("No audio input device found"),
+						 _("Your Mac does not seem to be equipped with a suitable audio input device. "
+						   "Please check your connectors and drivers.") );
+        msg_Err( p_demux, "Can't find any Audio device" );
+
+        goto error;
+    }
+
+    if( ![p_sys->audiodevice open: &o_returnedAudioError] )
+    {
+        msg_Err( p_demux, "Unable to open the audio capture device (%d)", [o_returnedAudioError code] );
+        goto error;
+    }
+
+    if( [p_sys->audiodevice isInUseByAnotherApplication] == YES )
+    {
+        msg_Err( p_demux, "default audio capture device is exclusively in use by another application" );
+        goto error;
+    }
+    audioInput = [[QTCaptureDeviceInput alloc] initWithDevice: p_sys->audiodevice];
+    if( !audioInput )
+    {
+        msg_Err( p_demux, "can't create a valid audio capture input facility" );
+        goto error;
+    } else {
+		msg_Dbg( p_demux, "created valid audio capture input facility" );
+	}
+
+	p_sys->audiooutput = [[VLCDecompressedAudioOutput alloc] init];
+	msg_Dbg ( p_demux, "initialized audio output" );
+
+    /* Get the formats */
+	/*
+	 FIXME: the format description gathered here does not seem to be the same when having started the QTCaptureSession. This information needs to be updated some other place.
+	 [0x2f7068] qtcapture demux debug: Audio localized format summary: Linear PCM, 16 bit little-endian signed integer, 2 channels, 44100 Hz
+	 [0x2f7068] qtcapture demux debug: Sample Rate: 44100.000000; Format ID: lpcm; Format Flags: 0000000c; Bytes per Packet: 4; Frames per Packet: 1; Bytes per Frame: 4; Channels per Frame: 2; Bits per Channel: 16
+	 [0x2f7068] qtcapture demux debug: Flag float 0 bigEndian 0 signedInt 1 packed 1 alignedHigh 0 non interleaved 0 non mixable 0
+	 canonical 1 nativeFloatPacked 1 nativeEndian 0
+
+	 should be for iMic
+
+	 number of samples in samplebuffer: 512
+	 Audio localized format summary: Linear PCM, 32 bit little-endian floating point, 2 channels, 44100 Hz
+	 Sample Rate: 44100; Format ID: lpcm; Format Flags: 00000029; Bytes per Packet: 4; Frames per Packet: 1; Bytes per Frame: 4; Channels per Frame: 2; Bits per Channel: 32
+	 Flag float 1 bigEndian 0 signedInt 0 packed 1 alignedHigh 0 non interleaved 1 non mixable 0
+	 canonical 1 nativeFloatPacked 1 nativeEndian 0
+	 */
+	NSArray *audioformat_array = [p_sys->audiodevice formatDescriptions];
+    QTFormatDescription* audio_format = NULL;
+    for( int k = 0; k < [audioformat_array count]; k++ )
+    {
+        audio_format = (QTFormatDescription *)[audioformat_array objectAtIndex: k];
+
+		msg_Dbg( p_demux, "Audio localized format summary: %s", [[audio_format localizedFormatSummary] UTF8String]);
+		msg_Dbg( p_demux, "Audio format description attributes: %s",[[[audio_format formatDescriptionAttributes] description] UTF8String]);	
+
+		AudioStreamBasicDescription asbd = {0};
+		NSValue *asbdValue =  [audio_format attributeForKey:QTFormatDescriptionAudioStreamBasicDescriptionAttribute];
+		[asbdValue getValue:&asbd];
+
+		char formatIDString[5];
+		UInt32 formatID = CFSwapInt32HostToBig (asbd.mFormatID);
+		bcopy (&formatID, formatIDString, 4);
+		formatIDString[4] = '\0';
+
+		msg_Dbg( p_demux, "Sample Rate: %.0lf; Format ID: %s; Format Flags: %.8x; Bytes per Packet: %d; Frames per Packet: %d; Bytes per Frame: %d; Channels per Frame: %d; Bits per Channel: %d", 
+				asbd.mSampleRate,
+				formatIDString,
+				asbd.mFormatFlags,
+				asbd.mBytesPerPacket,
+				asbd.mFramesPerPacket,
+				asbd.mBytesPerFrame,
+				asbd.mChannelsPerFrame,
+				asbd.mBitsPerChannel);
+
+		msg_Dbg( p_demux, "Flag float %d bigEndian %d signedInt %d packed %d alignedHigh %d non interleaved %d non mixable %d\ncanonical %d nativeFloatPacked %d nativeEndian %d", 
+				(asbd.mFormatFlags & kAudioFormatFlagIsFloat) != 0,
+				(asbd.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0,
+				(asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0,
+				(asbd.mFormatFlags & kAudioFormatFlagIsPacked) != 0,
+				(asbd.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0,
+				(asbd.mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0,
+				(asbd.mFormatFlags & kAudioFormatFlagIsNonMixable) != 0,
+
+
+				(asbd.mFormatFlags & kAudioFormatFlagsCanonical) != 0,
+				(asbd.mFormatFlags & kAudioFormatFlagsNativeFloatPacked) != 0,
+				(asbd.mFormatFlags & kAudioFormatFlagsNativeEndian) != 0
+				);
+
+    }
+
+    if( [audioformat_array count] )
+        audio_format = [audioformat_array objectAtIndex: 0];
+    else goto error;
+
+    /* Now we can init */
+	//
+	int audiocodec = VLC_CODEC_S16L;
+	//int audiocodec = VLC_CODEC_F32L;
+
+	es_format_Init( &audiofmt, AUDIO_ES, audiocodec);
+
+	/* FIXME: these values need to be read later and set dynamically. works with iMic */
+	p_sys->i_audio_max_buffer_size = 4096;
+
+	audiofmt.audio.i_format = audiocodec;
+	audiofmt.audio.i_rate = 44100;
+	/* i_physical_channels Describes the channels configuration of the samples (ie. number of
+     * channels which are available in the buffer, and positions). */
+	audiofmt.audio.i_physical_channels = 2;
+    /* i_original_channels Describes from which original channels, before downmixing, the
+     * buffer is derived. */
+	audiofmt.audio.i_original_channels = 2;
+    /* i_bytes_per_frame Optional - for A/52, SPDIF and DTS types : */
+    /* Bytes used by one compressed frame, depends on bitrate. */
+    audiofmt.audio.i_bytes_per_frame = 4;
+    /* Number of sampleframes contained in one compressed frame. */
+    audiofmt.audio.i_frame_length = 1;
+    /* Please note that it may be completely arbitrary - buffers are not
+     * obliged to contain a integral number of so-called "frames". It's
+     * just here for the division :
+     * buffer_size = i_nb_samples * i_bytes_per_frame / i_frame_length
+     */
+    audiofmt.audio.i_bitspersample = 16;
+	audiofmt.audio.i_channels = 2;
+	audiofmt.audio.i_blockalign = audiofmt.audio.i_channels * audiofmt.audio.i_bitspersample / 8;
+
+	audiofmt.i_bitrate = audiofmt.audio.i_channels * audiofmt.audio.i_rate * audiofmt.audio.i_bitspersample;
+
+    p_sys->session = [[QTCaptureSession alloc] init];
+
+	bool retAudio = [p_sys->session addInput:audioInput error: &o_returnedAudioError];
+    if( !retAudio )
+    {
+        msg_Err( p_demux, "the audio capture device could not be added to capture session (%d)", [o_returnedAudioError code] );
+        goto error;
+    }
+
+	bool retAudioOutput = [p_sys->session addOutput:p_sys->audiooutput error: &o_returnedAudioError];
+    if( !retAudioOutput )
+    {
+        msg_Err( p_demux, "audio output could not be added to capture session (%d)", [o_returnedAudioError code] );
+        goto error;
+    }
+
+    [p_sys->session startRunning];
+
+	msg_Dbg( p_demux, "New audio es %d channels %dHz",
+            audiofmt.audio.i_channels, audiofmt.audio.i_rate );
+
+	p_sys->p_es_audio = es_out_Add( p_demux->out, &audiofmt );
+
+	[audioInput release];
+    [pool release];
+
+    msg_Dbg( p_demux, "QTSound: We have an audio device ready!" );
+
+    return VLC_SUCCESS;
+error:
+	[audioInput release];
+    [pool release];
+
+    free( p_sys );
+
+    return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * Close: destroy interface
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+    demux_t     *p_demux = (demux_t*)p_this;
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    /* Hack: if libvlc was killed, main interface thread was,
+     * and poor QTKit needs it, so don't tell him.
+     * Else we dead lock. */
+    if( vlc_object_alive(p_this->p_libvlc))
+    {
+        // Perform this on main thread, as the framework itself will sometimes try to synchronously
+        // work on main thread. And this will create a dead lock.
+        [p_sys->session performSelectorOnMainThread:@selector(stopRunning) withObject:nil waitUntilDone:NO];
+		[p_sys->audiooutput performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
+        [p_sys->session performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
+    }
+    free( p_sys );
+
+    [pool release];
+}
+
+/*****************************************************************************
+ * Demux:
+ *****************************************************************************/
+static int Demux( demux_t *p_demux )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    block_t *p_blocka = NULL;
+
+	p_blocka = block_New( p_demux, p_sys->i_audio_max_buffer_size );
+
+	if( !p_blocka )
+    {
+        msg_Err( p_demux, "cannot get audio block" );
+        return 0;
+    }
+
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+    @synchronized (p_sys->audiooutput)
+    {
+		p_blocka->i_pts = [p_sys->audiooutput copyCurrentAudioBytesToBuffer: p_blocka->p_buffer];
+		/* FIXME: set this dynamically */
+		p_blocka->i_nb_samples = 512;
+		p_blocka->i_buffer = 4096;
+		p_blocka->i_buffer = 2048;
+    }
+
+	if( !p_blocka->i_pts )
+    {
+        // Nothing to transfer yet, just forget
+        block_Release( p_blocka );
+        [pool release];
+        msleep( 10000 );
+        return 1;
+    }
+
+	[pool release];
+
+	if( p_blocka )
+	{
+		es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_blocka->i_pts );
+		es_out_Send( p_demux->out, p_sys->p_es_audio, p_blocka );
+	}
+
+    return 1;
+}
+
+/*****************************************************************************
+ * Control:
+ *****************************************************************************/
+static int Control( demux_t *p_demux, int i_query, va_list args )
+{
+    bool *pb;
+    int64_t    *pi64;
+
+    switch( i_query )
+    {
+			/* Special for access_demux */
+        case DEMUX_CAN_PAUSE:
+        case DEMUX_CAN_SEEK:
+        case DEMUX_SET_PAUSE_STATE:
+        case DEMUX_CAN_CONTROL_PACE:
+			pb = (bool*)va_arg( args, bool * );
+			*pb = false;
+			return VLC_SUCCESS;
+
+        case DEMUX_GET_PTS_DELAY:
+			pi64 = (int64_t*)va_arg( args, int64_t * );
+			*pi64 = (int64_t)DEFAULT_PTS_DELAY;
+			return VLC_SUCCESS;
+
+        default:
+			return VLC_EGENERIC;
+    }
+    return VLC_EGENERIC;
+}
\ No newline at end of file
-- 
1.7.4.1




More information about the vlc-devel mailing list