From a5be6c84a94cbff15aa10e83db37a70f53c957d7 Mon Sep 17 00:00:00 2001 From: Damian Minkov <damencho@jitsi.org> Date: Thu, 6 Dec 2012 16:12:51 +0000 Subject: [PATCH] Changes needed for android merge. Exposing several bundle contexts. Some public constants. Changes in sound notifications to use String as resource uri, and obtaining resource input stream and stream format info from AudioSystem, so it can be overridden in different implementations. --- src/native/ffmpeg/README | 13 ++++ src/org/jitsi/impl/libjitsi/LibJitsiImpl.java | 2 +- .../codec/video/h264/DePacketizer.java | 2 +- .../impl/neomedia/device/AudioSystem.java | 75 +++++++++++++++++++ .../neomedia/device/DeviceConfiguration.java | 4 +- .../notify/AudioNotifierServiceImpl.java | 24 +----- .../neomedia/notify/AudioSystemClipImpl.java | 37 ++++----- .../neomedia/notify/JavaSoundClipImpl.java | 8 +- .../audionotifier/AbstractSCAudioClip.java | 14 ++-- .../service/neomedia/codec/Constants.java | 7 ++ 10 files changed, 128 insertions(+), 58 deletions(-) diff --git a/src/native/ffmpeg/README b/src/native/ffmpeg/README index a7e4e7ab..8e9bc91d 100644 --- a/src/native/ffmpeg/README +++ b/src/native/ffmpeg/README @@ -45,6 +45,12 @@ patch -Np1 -i x264-01-freebsd.patch ./configure --enable-pic +- For android +NDK_BASE=/../android-ndk-r8c +./configure --enable-pic --host=arm-linux --disable-asm \ + --sysroot="$NDK_BASE/platforms/android-9/arch-arm/" \ + --cross-prefix=$NDK_BASE/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi- + 3. ffmpeg patch -Np1 -i ffmpeg-01-libavcodec_libx264.c-zero_latency.patch @@ -82,6 +88,13 @@ Add the following to the configure line: Add the following to the configure line: --enable-pic --enable-pthreads --enable-memalign-hack +- For android remove lame and add + --arch=arm \ + --target-os=linux \ + --enable-runtime-cpudetect \ + --sysroot="$NDK_BASE/platforms/android-9/arch-arm/" \ + --cross-prefix=$NDK_BASE/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi- + 4. jnffmpeg Define the environment variable JAVA_HOME so that the JNI headers can be found. diff --git a/src/org/jitsi/impl/libjitsi/LibJitsiImpl.java b/src/org/jitsi/impl/libjitsi/LibJitsiImpl.java index 30118303..2f7615fd 100644 --- a/src/org/jitsi/impl/libjitsi/LibJitsiImpl.java +++ b/src/org/jitsi/impl/libjitsi/LibJitsiImpl.java @@ -155,7 +155,7 @@ else if (logger.isInfoEnabled()) logger.info( "Failed to initialize service implementation " + serviceImplClassName - + ". Will continue without it."); + + ". Will continue without it.", exception); } return service; diff --git a/src/org/jitsi/impl/neomedia/codec/video/h264/DePacketizer.java b/src/org/jitsi/impl/neomedia/codec/video/h264/DePacketizer.java index a6010103..8e665126 100644 --- a/src/org/jitsi/impl/neomedia/codec/video/h264/DePacketizer.java +++ b/src/org/jitsi/impl/neomedia/codec/video/h264/DePacketizer.java @@ -46,7 +46,7 @@ public class DePacketizer * structure contains the first NAL unit of an access unit in decoding * order". */ - private static final byte[] NAL_PREFIX = { 0, 0, 1 }; + public static final byte[] NAL_PREFIX = { 0, 0, 1 }; /** * The indicator which determines whether incomplete NAL units are output diff --git a/src/org/jitsi/impl/neomedia/device/AudioSystem.java b/src/org/jitsi/impl/neomedia/device/AudioSystem.java index f495ac0a..fade77f7 100644 --- a/src/org/jitsi/impl/neomedia/device/AudioSystem.java +++ b/src/org/jitsi/impl/neomedia/device/AudioSystem.java @@ -6,9 +6,17 @@ */ package org.jitsi.impl.neomedia.device; +import java.io.*; +import java.net.*; import java.util.*; +import org.jitsi.service.libjitsi.*; import org.jitsi.service.neomedia.*; +import org.jitsi.service.resources.*; +import org.jitsi.util.*; + +import javax.media.*; +import javax.sound.sampled.*; /** * Represents a <tt>DeviceSystem</tt> which provides support for the devices to @@ -59,6 +67,11 @@ public abstract class AudioSystem public static final String LOCATOR_PROTOCOL_PULSEAUDIO = "pulseaudio"; + /** + * The <tt>Logger</tt> used by this instance for logging output. + */ + private static Logger logger = Logger.getLogger(AudioSystem.class); + public static AudioSystem getAudioSystem(String locatorProtocol) { AudioSystem[] audioSystems = getAudioSystems(); @@ -317,4 +330,66 @@ public void propertyChange( { firePropertyChange(property, oldValue, newValue); } + + /** + * Obtains an audio input stream from the URL provided. + * @param uri a valid uri to a sound resource. + * @return the input stream to audio data. + * @throws IOException if an I/O exception occurs + */ + public InputStream getAudioInputStream(String uri) + throws IOException + { + AudioInputStream audioStream = null; + + ResourceManagementService resources + = LibJitsi.getResourceManagementService(); + URL url + = (resources == null) + ? null + : resources.getSoundURLForPath(uri); + + try + { + if (url == null) + { + // Not found by the class loader. Perhaps it's a local file. + url = new URL(uri); + } + + audioStream = javax.sound.sampled.AudioSystem + .getAudioInputStream(url); + } + catch (MalformedURLException e) + { + return null; + } + catch (UnsupportedAudioFileException uafex) + { + logger.error("Unsupported format of audio stream " + url, uafex); + } + + return audioStream; + } + + /** + * Returns the audio format for the <tt>InputStream</tt>. Or null + * if format cannot be obtained. + * @param audioInputStream the input stream. + * @return the format of the audio stream. + */ + public Format getFormat(InputStream audioInputStream) + { + if(!(audioInputStream instanceof AudioInputStream)) + return null; + + AudioFormat audioStreamFormat = + ((AudioInputStream)audioInputStream).getFormat(); + + return new javax.media.format.AudioFormat( + javax.media.format.AudioFormat.LINEAR, + audioStreamFormat.getSampleRate(), + audioStreamFormat.getSampleSizeInBits(), + audioStreamFormat.getChannels()); + } } diff --git a/src/org/jitsi/impl/neomedia/device/DeviceConfiguration.java b/src/org/jitsi/impl/neomedia/device/DeviceConfiguration.java index bba9a8a5..d41bce55 100644 --- a/src/org/jitsi/impl/neomedia/device/DeviceConfiguration.java +++ b/src/org/jitsi/impl/neomedia/device/DeviceConfiguration.java @@ -66,8 +66,8 @@ public class DeviceConfiguration private static final String[] CUSTOM_RENDERERS = new String[] { - OSUtils.IS_ANDROID ? "net.java.sip.communicator.impl.neomedia.jmfext.media.renderer.audio.AudioTrackRenderer" : null, - OSUtils.IS_ANDROID ? "net.java.sip.communicator.impl.neomedia.jmfext.media.renderer.audio.OpenSLESRenderer" : null, + OSUtils.IS_ANDROID ? "org.jitsi.impl.neomedia.jmfext.media.renderer.audio.AudioTrackRenderer" : null, + OSUtils.IS_ANDROID ? "org.jitsi.impl.neomedia.jmfext.media.renderer.audio.OpenSLESRenderer" : null, OSUtils.IS_LINUX ? ".audio.PulseAudioRenderer" : null, OSUtils.IS_ANDROID ? null : ".audio.PortAudioRenderer", "net.java.sip.communicator.impl.neomedia.jmfext.media.renderer.video.JAWTRenderer" diff --git a/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java b/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java index 27d4fa1c..574716fb 100644 --- a/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java +++ b/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java @@ -124,26 +124,6 @@ public SCAudioClip createAudio(String uri, boolean playback) if (audio == null) { - ResourceManagementService resources - = LibJitsi.getResourceManagementService(); - URL url - = (resources == null) - ? null - : resources.getSoundURLForPath(uri); - - if (url == null) - { - // Not found by the class loader. Perhaps it's a local file. - try - { - url = new URL(uri); - } - catch (MalformedURLException e) - { - return null; - } - } - try { AudioSystem audioSystem @@ -151,7 +131,7 @@ public SCAudioClip createAudio(String uri, boolean playback) if (audioSystem == null) { - audio = new JavaSoundClipImpl(url, this); + audio = new JavaSoundClipImpl(uri, this); } else if (NoneAudioSystem.LOCATOR_PROTOCOL.equalsIgnoreCase( audioSystem.getLocatorProtocol())) @@ -162,7 +142,7 @@ else if (NoneAudioSystem.LOCATOR_PROTOCOL.equalsIgnoreCase( { audio = new AudioSystemClipImpl( - url, + uri, this, audioSystem, playback); diff --git a/src/org/jitsi/impl/neomedia/notify/AudioSystemClipImpl.java b/src/org/jitsi/impl/neomedia/notify/AudioSystemClipImpl.java index c5be2d52..4ab84310 100644 --- a/src/org/jitsi/impl/neomedia/notify/AudioSystemClipImpl.java +++ b/src/org/jitsi/impl/neomedia/notify/AudioSystemClipImpl.java @@ -7,12 +7,11 @@ package org.jitsi.impl.neomedia.notify; import java.io.*; -import java.net.*; import javax.media.*; -import javax.sound.sampled.*; import org.jitsi.impl.neomedia.codec.audio.speex.*; +import org.jitsi.impl.neomedia.device.*; import org.jitsi.service.audionotifier.*; import org.jitsi.util.*; @@ -32,8 +31,7 @@ public class AudioSystemClipImpl private static final Logger logger = Logger.getLogger(AudioSystemClipImpl.class); - private final org.jitsi.impl.neomedia.device.AudioSystem - audioSystem; + private final AudioSystem audioSystem; private Buffer buffer; @@ -53,9 +51,9 @@ public class AudioSystemClipImpl * @throws IOException cannot audio clip with supplied URL. */ public AudioSystemClipImpl( - URL url, + String url, AudioNotifierService audioNotifier, - org.jitsi.impl.neomedia.device.AudioSystem audioSystem, + AudioSystem audioSystem, boolean playback) throws IOException { @@ -107,20 +105,17 @@ protected void exitRunOnceInPlayThread() protected boolean runOnceInPlayThread() { - AudioInputStream audioStream = null; + InputStream audioStream = null; try { - audioStream = AudioSystem.getAudioInputStream(url); + audioStream = audioSystem.getAudioInputStream(uri); } catch (IOException ioex) { - logger.error("Failed to get audio stream " + url, ioex); - } - catch (UnsupportedAudioFileException uafex) - { - logger.error("Unsupported format of audio stream " + url, uafex); + logger.error("Failed to get audio stream " + uri, ioex); } + if (audioStream == null) return false; @@ -128,13 +123,13 @@ protected boolean runOnceInPlayThread() try { - AudioFormat audioStreamFormat = audioStream.getFormat(); - Format rendererFormat - = new javax.media.format.AudioFormat( - javax.media.format.AudioFormat.LINEAR, - audioStreamFormat.getSampleRate(), - audioStreamFormat.getSampleSizeInBits(), - audioStreamFormat.getChannels()); + Format rendererFormat = audioSystem.getFormat(audioStream); + + if(rendererFormat == null) + { + return false; + } + Format resamplerFormat = null; if (renderer.setInputFormat(rendererFormat) == null) @@ -215,7 +210,7 @@ protected boolean runOnceInPlayThread() } catch (IOException ioex) { - logger.error("Failed to read from audio stream " + url, ioex); + logger.error("Failed to read from audio stream " + uri, ioex); return false; } catch (ResourceUnavailableException ruex) diff --git a/src/org/jitsi/impl/neomedia/notify/JavaSoundClipImpl.java b/src/org/jitsi/impl/neomedia/notify/JavaSoundClipImpl.java index dc67a062..7e333f81 100644 --- a/src/org/jitsi/impl/neomedia/notify/JavaSoundClipImpl.java +++ b/src/org/jitsi/impl/neomedia/notify/JavaSoundClipImpl.java @@ -101,7 +101,7 @@ public Constructor<AudioClip> run() * audio stored at a specific <tt>URL</tt> using * <tt>java.applet.AudioClip</tt>. * - * @param url the <tt>URL</tt> at which the audio is stored and which the + * @param uri the <tt>URL</tt> at which the audio is stored and which the * new instance is to load * @param audioNotifier the <tt>AudioNotifierService</tt> which is * initializing the new instance and whose <tt>mute</tt> property/state is @@ -109,12 +109,12 @@ public Constructor<AudioClip> run() * @throws IOException if a <tt>java.applet.AudioClip</tt> could not be * initialized or the audio at the specified <tt>url</tt> could not be read */ - public JavaSoundClipImpl(URL url, AudioNotifierService audioNotifier) + public JavaSoundClipImpl(String uri, AudioNotifierService audioNotifier) throws IOException { - super(url, audioNotifier); + super(uri, audioNotifier); - audioClip = createAppletAudioClip(url.openStream()); + audioClip = createAppletAudioClip(new URL(uri).openStream()); } /** diff --git a/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java b/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java index b2d48e0e..5d484612 100644 --- a/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java +++ b/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java @@ -70,17 +70,17 @@ public abstract class AbstractSCAudioClip private final Object sync = new Object(); /** - * The <tt>URL</tt> of the audio to be played by this instance. + * The <tt>String</tt> uri of the audio to be played by this instance. * <tt>AbstractSCAudioClip</tt> does not use it and just remembers it in * order to make it available to extenders. */ - protected final URL url; + protected final String uri; protected AbstractSCAudioClip( - URL url, + String uri, AudioNotifierService audioNotifier) { - this.url = url; + this.uri = uri; this.audioNotifier = audioNotifier; } @@ -201,7 +201,7 @@ public boolean isInvalid() /** * Determines whether this instance plays the audio it represents in a loop. * - * @param <tt>true</tt> if this instance plays the audio it represents in a + * @return <tt>true</tt> if this instance plays the audio it represents in a * loop; <tt>false</tt>, otherwise */ public boolean isLooping() @@ -500,8 +500,8 @@ public void setInvalid(boolean invalid) * instance and the <tt>loopInterval</tt> and <tt>loopCondition</tt> * parameters of {@link #play(int, Callable)} anyway. * - * @param <tt>true</tt> to mark this instance that it should play the audio - * it represents in a loop; otherwise, <tt>false</tt> + * @param looping <tt>true</tt> to mark this instance that it should play + * the audio it represents in a loop; otherwise, <tt>false</tt> */ public void setLooping(boolean looping) { diff --git a/src/org/jitsi/service/neomedia/codec/Constants.java b/src/org/jitsi/service/neomedia/codec/Constants.java index a49ea447..1c1e7743 100644 --- a/src/org/jitsi/service/neomedia/codec/Constants.java +++ b/src/org/jitsi/service/neomedia/codec/Constants.java @@ -94,6 +94,13 @@ public class Constants */ public static final String TELEPHONE_EVENT = "telephone-event"; + /** + * The list of well-known sample rates of audio data used throughout + * neomedia. + */ + public static final double[] AUDIO_SAMPLE_RATES + = { 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 }; + /** * mode : Frame size for the encoding/decoding * 20 - 20 ms -- GitLab