Created
November 19, 2015 05:20
-
-
Save tmm1/a54d4fef79f2c2b3f0ee to your computer and use it in GitHub Desktop.
wip vlc avplayer audio_output module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From: Aman <aman@tmm1.net> | |
Date: Fri Aug 10 16:02:07 2012 +0200 | |
Subject: add AVPlayer audio output module | |
--- | |
diff --git a/extras/package/ios/build.sh b/extras/package/ios/build.sh | |
index c2a1462..3070c02 100755 | |
--- a/extras/package/ios/build.sh | |
+++ b/extras/package/ios/build.sh | |
@@ -453,7 +453,6 @@ speex_resampler | |
remoteosd | |
magnify | |
gradient | |
-tospdif | |
dtstofloat32 | |
logger | |
visual | |
diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST | |
index 1644fde..507452c 100644 | |
--- a/modules/MODULES_LIST | |
+++ b/modules/MODULES_LIST | |
@@ -59,6 +59,7 @@ $Id$ | |
* avformat: libavformat demuxer | |
* avi: AVI file stream demuxer | |
* avio: Access and Stream output module using libavformat network | |
+ * avplayer_ios: AVPlayer output plugin for iOS | |
* ball: Augmented reality ball video filter module | |
* bandlimited_resampler: Bandlimited interpolation audio resampler | |
* blend: a picture filter that blends two pictures | |
diff --git a/modules/audio_output/Makefile.am b/modules/audio_output/Makefile.am | |
index 5850947..cf20295 100644 | |
--- a/modules/audio_output/Makefile.am | |
+++ b/modules/audio_output/Makefile.am | |
@@ -114,6 +114,16 @@ if HAVE_TVOS | |
aout_LTLIBRARIES += libaudiounit_ios_plugin.la | |
endif | |
+libavplayer_ios_plugin_la_SOURCES = audio_output/avplayer_ios.m \ | |
+ audio_output/TPCircularBuffer.h audio_output/TPCircularBuffer.c | |
+libavplayer_ios_plugin_la_LDFLAGS = $(AM_LDFLAGS) -Wl,-framework,CoreAudio,-framework,AudioUnit,-framework,AudioToolbox,-framework,CoreServices,-framework,UIKit,-framework,AVFoundation -rpath '$(aoutdir)' | |
+if HAVE_IOS | |
+aout_LTLIBRARIES += libavplayer_ios_plugin.la | |
+endif | |
+if HAVE_TVOS | |
+aout_LTLIBRARIES += libavplayer_ios_plugin.la | |
+endif | |
+ | |
libaudioqueue_plugin_la_SOURCES = audio_output/audioqueue.c | |
libaudioqueue_plugin_la_LDFLAGS = $(AM_LDFLAGS) -Wl,-framework,CoreAudio,-framework,AudioUnit,-framework,AudioToolbox,-framework,CoreServices -rpath '$(aoutdir)' | |
EXTRA_LTLIBRARIES += libaudioqueue_plugin.la | |
diff --git a/modules/audio_output/avplayer_ios.m b/modules/audio_output/avplayer_ios.m | |
new file mode 100644 | |
index 0000000..f67f6a7 | |
--- /dev/null | |
+++ b/modules/audio_output/avplayer_ios.m | |
@@ -0,0 +1,306 @@ | |
+/***************************************************************************** | |
+ * avplayer_ios.m: AVPlayer output plugin for iOS | |
+ ***************************************************************************** | |
+ * Copyright (C) 2012 - 2015 VLC authors and VideoLAN | |
+ * $Id$ | |
+ * | |
+ * Authors: Aman Gupta <vlc at tmm1 dot net> | |
+ * | |
+ * This program 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; either version 2.1 of the License, or | |
+ * (at your option) any later version. | |
+ * | |
+ * This program 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 program; if not, write to the Free Software Foundation, | |
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. | |
+ *****************************************************************************/ | |
+ | |
+#pragma mark includes | |
+ | |
+#ifdef HAVE_CONFIG_H | |
+# import "config.h" | |
+#endif | |
+ | |
+#import <vlc_common.h> | |
+#import <vlc_plugin.h> | |
+#import <vlc_aout.h> | |
+ | |
+#import <AVFoundation/AVFoundation.h> | |
+#import <mach/mach_time.h> | |
+ | |
+#import "TPCircularBuffer.h" | |
+ | |
+#pragma mark - | |
+#pragma mark private declarations | |
+ | |
+@interface ResourceLoader : NSObject <AVAssetResourceLoaderDelegate> | |
+@property (nonatomic) struct aout_sys_t *p_sys; | |
+@end | |
+ | |
+/***************************************************************************** | |
+ * aout_sys_t: private audio output method descriptor | |
+ ***************************************************************************** | |
+ * This structure is part of the audio output thread descriptor. | |
+ * It describes the CoreAudio specific properties of an output thread. | |
+ *****************************************************************************/ | |
+struct aout_sys_t | |
+{ | |
+ TPCircularBuffer circular_buffer; /* circular buffer to swap the audio data */ | |
+ | |
+ AVPlayer *player; | |
+ ResourceLoader *delegate; | |
+ | |
+ int i_rate; /* media sample rate */ | |
+ int i_bytes_per_sample; | |
+ | |
+ bool b_paused; | |
+ | |
+ vlc_mutex_t lock; | |
+ vlc_cond_t cond; | |
+}; | |
+ | |
+#pragma mark - | |
+#pragma mark local prototypes & module descriptor | |
+ | |
+static int Open (vlc_object_t *); | |
+static void Close (vlc_object_t *); | |
+static int Start (audio_output_t *, audio_sample_format_t *); | |
+static int StartAnalog (audio_output_t *, audio_sample_format_t *); | |
+static void Stop (audio_output_t *); | |
+ | |
+static void Play (audio_output_t *, block_t *); | |
+static void Pause (audio_output_t *, bool, mtime_t); | |
+static int MuteSet (audio_output_t *aout, bool mute); | |
+static void Flush (audio_output_t *, bool); | |
+static int TimeGet (audio_output_t *, mtime_t *); | |
+static OSStatus RenderCallback (vlc_object_t *, AudioUnitRenderActionFlags *, const AudioTimeStamp *, | |
+ UInt32 , UInt32, AudioBufferList *); | |
+ | |
+vlc_module_begin () | |
+ set_shortname("avplayer_ios") | |
+ set_description(N_("AVPlayer output for iOS")) | |
+ set_capability("audio output", 111) | |
+ set_category(CAT_AUDIO) | |
+ set_subcategory(SUBCAT_AUDIO_AOUT) | |
+ set_callbacks(Open, Close) | |
+vlc_module_end () | |
+ | |
+#pragma mark - | |
+#pragma mark initialization | |
+ | |
+static int Open(vlc_object_t *obj) | |
+{ | |
+ audio_output_t *aout = (audio_output_t *)obj; | |
+ aout_sys_t *sys = malloc(sizeof (*sys)); | |
+ | |
+ if (unlikely(sys == NULL)) | |
+ return VLC_ENOMEM; | |
+ | |
+ vlc_mutex_init(&sys->lock); | |
+ vlc_cond_init(&sys->cond); | |
+ sys->b_paused = false; | |
+ | |
+ aout->sys = sys; | |
+ aout->start = Start; | |
+ aout->stop = Stop; | |
+ | |
+ return VLC_SUCCESS; | |
+} | |
+ | |
+static void Close(vlc_object_t *obj) | |
+{ | |
+ audio_output_t *aout = (audio_output_t *)obj; | |
+ aout_sys_t *sys = aout->sys; | |
+ | |
+ vlc_mutex_destroy(&sys->lock); | |
+ vlc_cond_destroy(&sys->cond); | |
+ | |
+ free(sys); | |
+} | |
+ | |
+static int Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt) | |
+{ | |
+ struct aout_sys_t *p_sys = NULL; | |
+ | |
+ p_sys = p_aout->sys; | |
+ p_sys->i_bytes_per_sample = 0; | |
+ p_sys->i_rate = fmt->i_rate; | |
+ | |
+ aout_FormatPrint(p_aout, "VLC is looking for:", fmt); | |
+ if (!AOUT_FMT_SPDIF(fmt)) | |
+ return VLC_EGENERIC; | |
+ | |
+ /* setup circular buffer */ | |
+ TPCircularBufferInit(&p_sys->circular_buffer, 200 * AOUT_SPDIF_SIZE); | |
+ | |
+ p_sys->delegate = [ResourceLoader new]; | |
+ p_sys->delegate.p_sys = p_sys; | |
+ | |
+ NSURL *videoURL = [NSURL URLWithString:@"streaming://fake/out.ac3"]; | |
+ AVURLAsset *asset = [AVURLAsset URLAssetWithURL:videoURL options:nil]; | |
+ //[asset.resourceLoader setDelegate:p_sys->delegate queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; | |
+ [asset.resourceLoader setDelegate:p_sys->delegate queue:dispatch_get_main_queue()]; | |
+ | |
+ AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset]; | |
+ //[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:NULL]; | |
+ p_sys->player = [[AVPlayer alloc] initWithPlayerItem:playerItem]; | |
+ | |
+ p_aout->play = Play; | |
+ p_aout->flush = Flush; | |
+ p_aout->mute_set = MuteSet; | |
+ p_aout->time_get = TimeGet; | |
+ p_aout->pause = Pause; | |
+ | |
+ [p_sys->player play]; | |
+ | |
+ return VLC_SUCCESS; | |
+} | |
+ | |
+static void Stop(audio_output_t *p_aout) | |
+{ | |
+ struct aout_sys_t *p_sys = p_aout->sys; | |
+ OSStatus status; | |
+ | |
+ [p_sys->player pause]; | |
+ p_sys->player = nil; | |
+ p_sys->i_bytes_per_sample = 0; | |
+ | |
+ /* clean-up circular buffer */ | |
+ TPCircularBufferCleanup(&p_sys->circular_buffer); | |
+} | |
+ | |
+#pragma mark - | |
+#pragma mark actual playback | |
+ | |
+static void Play (audio_output_t * p_aout, block_t * p_block) | |
+{ | |
+ struct aout_sys_t *p_sys = p_aout->sys; | |
+ | |
+ if (p_block->i_nb_samples > 0) { | |
+ /* move data to buffer */ | |
+ if (unlikely(!TPCircularBufferProduceBytes(&p_sys->circular_buffer, p_block->p_buffer, p_block->i_buffer))) | |
+ msg_Warn(p_aout, "Audio buffer was dropped"); | |
+ | |
+ if (!p_sys->i_bytes_per_sample) | |
+ p_sys->i_bytes_per_sample = p_block->i_buffer / p_block->i_nb_samples; | |
+ } | |
+ | |
+ block_Release(p_block); | |
+} | |
+ | |
+static void Pause (audio_output_t *p_aout, bool pause, mtime_t date) | |
+{ | |
+ struct aout_sys_t * p_sys = p_aout->sys; | |
+ VLC_UNUSED(date); | |
+ | |
+ vlc_mutex_lock(&p_sys->lock); | |
+ p_sys->b_paused = pause; | |
+ vlc_mutex_unlock(&p_sys->lock); | |
+ | |
+ if (p_sys->player == NULL) { | |
+ return; | |
+ } | |
+ | |
+ [p_sys->player pause]; | |
+} | |
+ | |
+static int MuteSet(audio_output_t *p_aout, bool mute) | |
+{ | |
+ return VLC_EGENERIC; | |
+} | |
+ | |
+static void Flush(audio_output_t *p_aout, bool wait) | |
+{ | |
+ struct aout_sys_t *p_sys = p_aout->sys; | |
+ | |
+ int32_t availableBytes; | |
+ vlc_mutex_lock(&p_sys->lock); | |
+ TPCircularBufferTail(&p_sys->circular_buffer, &availableBytes); | |
+ | |
+ if (wait) { | |
+ while (availableBytes > 0) { | |
+ vlc_cond_wait(&p_sys->cond, &p_sys->lock); | |
+ TPCircularBufferTail(&p_sys->circular_buffer, &availableBytes); | |
+ } | |
+ } else { | |
+ /* flush circular buffer if data is left */ | |
+ if (availableBytes > 0) | |
+ TPCircularBufferClear(&p_aout->sys->circular_buffer); | |
+ } | |
+ | |
+ vlc_mutex_unlock(&p_sys->lock); | |
+} | |
+ | |
+static int TimeGet(audio_output_t *p_aout, mtime_t *delay) | |
+{ | |
+ struct aout_sys_t * p_sys = p_aout->sys; | |
+ | |
+ if (!p_sys->i_bytes_per_sample) | |
+ return -1; | |
+ | |
+ int32_t availableBytes; | |
+ TPCircularBufferTail(&p_sys->circular_buffer, &availableBytes); | |
+ | |
+ *delay = (availableBytes / p_sys->i_bytes_per_sample) * CLOCK_FREQ / p_sys->i_rate; | |
+ | |
+ return 0; | |
+} | |
+ | |
+@implementation ResourceLoader | |
+- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest{ | |
+ AVAssetResourceLoadingContentInformationRequest* contentRequest = loadingRequest.contentInformationRequest; | |
+ if (contentRequest) { | |
+ contentRequest.contentType = @"public.ac3-audio"; | |
+ contentRequest.contentLength = 2*1024*1024*1024; | |
+ contentRequest.byteRangeAccessSupported = YES; | |
+ NSLog(@"contentRequest: %@", contentRequest); | |
+ } | |
+ | |
+ AVAssetResourceLoadingDataRequest* dataRequest = loadingRequest.dataRequest; | |
+ if (dataRequest) { | |
+ NSLog(@"dataRequest: %@", dataRequest); | |
+ //dispatch_async(dispatch_get_main_queue(), ^{ | |
+ NSInteger reqLen = dataRequest.requestedLength; | |
+ if (reqLen == 2) { | |
+ [dataRequest respondWithData:[NSData dataWithBytes:"\vw" length:2]]; | |
+ [loadingRequest finishLoading]; | |
+ } else { | |
+ int bytesRequested = (int)reqLen; | |
+ struct aout_sys_t *p_sys = self.p_sys; | |
+ | |
+ vlc_mutex_lock(&p_sys->lock); | |
+ /* Pull audio from buffer */ | |
+ int32_t availableBytes; | |
+ void *buffer = TPCircularBufferTail(&p_sys->circular_buffer, &availableBytes); | |
+ | |
+ /* check if we have enough data */ | |
+ if (!availableBytes || p_sys->b_paused) { | |
+ /* return an empty buffer so silence is played until we have data */ | |
+ } else { | |
+ int32_t bytesToCopy = __MIN(bytesRequested, availableBytes); | |
+ | |
+ if (likely(bytesToCopy > 0)) { | |
+ NSData *data = [NSData dataWithBytes:buffer length:bytesToCopy]; | |
+ [dataRequest respondWithData:data]; | |
+ NSLog(@"sending %du bytes", [data length]); | |
+ TPCircularBufferConsume(&p_sys->circular_buffer, bytesToCopy); | |
+ } | |
+ } | |
+ | |
+ vlc_cond_signal(&p_sys->cond); | |
+ vlc_mutex_unlock(&p_sys->lock); | |
+ | |
+ [loadingRequest finishLoading]; | |
+ } | |
+ //}); | |
+ } | |
+ | |
+ return YES; | |
+} | |
+@end | |
diff --git a/modules/codec/a52.c b/modules/codec/a52.c | |
index 7450d6b..7ee1cce 100644 | |
--- a/modules/codec/a52.c | |
+++ b/modules/codec/a52.c | |
@@ -150,7 +150,7 @@ static int OpenCommon( vlc_object_t *p_this, bool b_packetizer ) | |
static int OpenDecoder( vlc_object_t *p_this ) | |
{ | |
/* HACK: Don't use this codec if we don't have an a52 audio filter */ | |
- if( !module_exists( "a52tofloat32" ) ) | |
+ if( !module_exists( "a52tofloat32" ) && !module_exists("a52tospdif") ) | |
return VLC_EGENERIC; | |
return OpenCommon( p_this, false ); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment