Skip to content

Commit

Permalink
Important bug fixes, for RtpSocket and AAC streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
fyhertz committed Aug 20, 2013
1 parent 7d8931f commit bd1f006
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 65 deletions.
20 changes: 18 additions & 2 deletions src/net/majorkernelpanic/streaming/SessionBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import net.majorkernelpanic.streaming.audio.AACStream;
import net.majorkernelpanic.streaming.audio.AMRNBStream;
import net.majorkernelpanic.streaming.audio.AudioQuality;
import net.majorkernelpanic.streaming.audio.AudioStream;
import net.majorkernelpanic.streaming.video.H263Stream;
import net.majorkernelpanic.streaming.video.H264Stream;
Expand All @@ -33,6 +34,7 @@
import android.content.Context;
import android.hardware.Camera.CameraInfo;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.SurfaceHolder;

/**
Expand Down Expand Up @@ -61,7 +63,8 @@ public class SessionBuilder {
public final static int AUDIO_AAC = 5;

// Default configuration
private VideoQuality mVideoQuality = VideoQuality.defaultVideoQualiy.clone();
private VideoQuality mVideoQuality = new VideoQuality();
private AudioQuality mAudioQuality = new AudioQuality();
private Context mContext;
private int mVideoEncoder = VIDEO_H263;
private int mAudioEncoder = AUDIO_AMRNB;
Expand Down Expand Up @@ -134,13 +137,14 @@ public Session build() throws IOException {
if (session.getVideoTrack()!=null) {
VideoStream video = session.getVideoTrack();
video.setFlashState(mFlash);
video.setVideoQuality(mVideoQuality);
video.setVideoQuality(VideoQuality.merge(mVideoQuality,video.getVideoQuality()));
video.setPreviewDisplay(mSurfaceHolder);
video.setDestinationPorts(5006);
}

if (session.getAudioTrack()!=null) {
AudioStream audio = session.getAudioTrack();
audio.setAudioQuality(AudioQuality.merge(mAudioQuality,audio.getAudioQuality()));
audio.setDestinationPorts(5004);
}

Expand Down Expand Up @@ -180,6 +184,12 @@ public SessionBuilder setAudioEncoder(int encoder) {
mAudioEncoder = encoder;
return this;
}

/** Sets the audio quality. */
public SessionBuilder setAudioQuality(AudioQuality quality) {
mAudioQuality = AudioQuality.merge(quality, mAudioQuality);
return this;
}

/** Sets the default video encoder. */
public SessionBuilder setVideoEncoder(int encoder) {
Expand Down Expand Up @@ -245,6 +255,11 @@ public int getVideoEncoder() {
public VideoQuality getVideoQuality() {
return mVideoQuality;
}

/** Returns the AudioQuality set with {@link #setAudioQuality(AudioQuality)}. */
public AudioQuality getAudioQuality() {
return mAudioQuality;
}

/** Returns the flash state set with {@link #setFlashEnabled(boolean)}. */
public boolean getFlashState() {
Expand Down Expand Up @@ -273,6 +288,7 @@ public SessionBuilder clone() {
.setCamera(mCamera)
.setTimeToLive(mTimeToLive)
.setAudioEncoder(mAudioEncoder)
.setAudioQuality(mAudioQuality)
.setContext(mContext);
}

Expand Down
21 changes: 12 additions & 9 deletions src/net/majorkernelpanic/streaming/audio/AACStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@
public class AACStream extends AudioStream {

public final static String TAG = "AACStream";

protected AudioQuality mQuality = new AudioQuality(32000,32000);

/** MPEG-4 Audio Object Types supported by ADTS. **/
private static final String[] sAudioObjectTypes = {
private static final String[] AUDIO_OBJECT_TYPES = {
"NULL", // 0
"AAC Main", // 1
"AAC LC (Low Complexity)", // 2
Expand All @@ -52,7 +54,7 @@ public class AACStream extends AudioStream {
};

/** There are 13 supported frequencies by ADTS. **/
private static final int[] sADTSSamplingRates = {
public static final int[] ADTS_SAMPLING_RATES = {
96000, // 0
88200, // 1
64000, // 2
Expand Down Expand Up @@ -95,7 +97,7 @@ public AACStream() throws IOException {
catch (Exception ignore) {}

setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
setAudioSamplingRate(16000);
setAudioSamplingRate(mQuality.samplingRate);

}

Expand Down Expand Up @@ -152,8 +154,8 @@ public String generateSessionDescription() throws IllegalStateException, IOExcep
private void testADTS() throws IllegalStateException, IOException {

if (mSettings!=null) {
if (mSettings.contains("aac-"+mSamplingRate)) {
String[] s = mSettings.getString("aac-"+mSamplingRate, "").split(",");
if (mSettings.contains("aac-"+mQuality.samplingRate)) {
String[] s = mSettings.getString("aac-"+mQuality.samplingRate, "").split(",");
mActualSamplingRate = Integer.valueOf(s[0]);
mConfig = Integer.valueOf(s[1]);
mChannel = Integer.valueOf(s[2]);
Expand All @@ -177,7 +179,8 @@ private void testADTS() throws IllegalStateException, IOException {
mMediaRecorder.setOutputFormat(mOutputFormat);
mMediaRecorder.setAudioEncoder(mAudioEncoder);
mMediaRecorder.setAudioChannels(1);
mMediaRecorder.setAudioSamplingRate(mSamplingRate);
mMediaRecorder.setAudioSamplingRate(mQuality.samplingRate);
mMediaRecorder.setAudioEncodingBitRate(mQuality.bitRate);
mMediaRecorder.setOutputFile(TESTFILE);
mMediaRecorder.prepare();
mMediaRecorder.start();
Expand Down Expand Up @@ -208,22 +211,22 @@ private void testADTS() throws IllegalStateException, IOException {
mSamplingRateIndex = (buffer[1]&0x3C) >> 2;
mProfile = ( (buffer[1]&0xC0) >> 6 ) + 1 ;
mChannel = (buffer[1]&0x01) << 2 | (buffer[2]&0xC0) >> 6 ;
mActualSamplingRate = sADTSSamplingRates[mSamplingRateIndex];
mActualSamplingRate = ADTS_SAMPLING_RATES[mSamplingRateIndex];

// 5 bits for the object type / 4 bits for the sampling rate / 4 bits for the channel / padding
mConfig = mProfile<<11 | mSamplingRateIndex<<7 | mChannel<<3;

Log.i(TAG,"MPEG VERSION: " + ( (buffer[0]&0x08) >> 3 ) );
Log.i(TAG,"PROTECTION: " + (buffer[0]&0x01) );
Log.i(TAG,"PROFILE: " + sAudioObjectTypes[ mProfile ] );
Log.i(TAG,"PROFILE: " + AUDIO_OBJECT_TYPES[ mProfile ] );
Log.i(TAG,"SAMPLING FREQUENCY: " + mActualSamplingRate );
Log.i(TAG,"CHANNEL: " + mChannel );

raf.close();

if (mSettings!=null) {
Editor editor = mSettings.edit();
editor.putString("aac-"+mSamplingRate, mActualSamplingRate+","+mConfig+","+mChannel);
editor.putString("aac-"+mQuality.samplingRate, mActualSamplingRate+","+mConfig+","+mChannel);
editor.commit();
}

Expand Down
2 changes: 1 addition & 1 deletion src/net/majorkernelpanic/streaming/audio/AMRNBStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public AMRNBStream() throws IOException {
}

setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
setAudioSamplingRate(8000);
setAudioSamplingRate(mQuality.samplingRate);

}

Expand Down
78 changes: 78 additions & 0 deletions src/net/majorkernelpanic/streaming/audio/AudioQuality.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (C) 2011-2013 GUIGUI Simon, [email protected]
*
* This file is part of Spydroid (http://code.google.com/p/spydroid-ipcamera/)
*
* Spydroid is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This source code 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

package net.majorkernelpanic.streaming.audio;

/**
* A class that represents the quality of an audio stream.
*/
public class AudioQuality {

/** Default audio stream quality. */
public final static AudioQuality DEFAULT_AUDIO_QUALITY = new AudioQuality(8000,32000);

/** Represents a quality for a video stream. */
public AudioQuality() {}

/**
* Represents a quality for an audio stream.
* @param samplingRate The sampling rate
* @param bitRate The bitrate in bit per seconds
*/
public AudioQuality(int samplingRate, int bitRate) {
this.samplingRate = samplingRate;
this.bitRate = bitRate;
}

public int samplingRate = 0;
public int bitRate = 0;

public boolean equals(AudioQuality quality) {
if (quality==null) return false;
return (quality.samplingRate == this.samplingRate &
quality.bitRate == this.bitRate);
}

public AudioQuality clone() {
return new AudioQuality(samplingRate, bitRate);
}

public static AudioQuality parseQuality(String str) {
AudioQuality quality = new AudioQuality(0,0);
if (str != null) {
String[] config = str.split("-");
try {
quality.bitRate = Integer.parseInt(config[0])*1000; // conversion to bit/s
quality.samplingRate = Integer.parseInt(config[1]);
}
catch (IndexOutOfBoundsException ignore) {}
}
return quality;
}

public static AudioQuality merge(AudioQuality audioQuality, AudioQuality withAudioQuality) {
if (withAudioQuality != null && audioQuality != null) {
if (audioQuality.samplingRate==0) audioQuality.samplingRate = withAudioQuality.samplingRate;
if (audioQuality.bitRate==0) audioQuality.bitRate = withAudioQuality.bitRate;
}
return audioQuality;
}

}
33 changes: 28 additions & 5 deletions src/net/majorkernelpanic/streaming/audio/AudioStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import java.io.IOException;

import android.media.MediaRecorder;

import net.majorkernelpanic.streaming.MediaStream;
import net.majorkernelpanic.streaming.video.VideoQuality;
import android.media.MediaRecorder;
import android.util.Log;

/**
* Don't use this class directly.
Expand All @@ -14,7 +15,7 @@ public abstract class AudioStream extends MediaStream {
protected int mAudioSource;
protected int mOutputFormat;
protected int mAudioEncoder;
protected int mSamplingRate;
protected AudioQuality mQuality = AudioQuality.DEFAULT_AUDIO_QUALITY.clone();

public void setAudioSource(int audioSource) {
mAudioSource = audioSource;
Expand All @@ -29,21 +30,43 @@ public void setAudioEncoder(int audioEncoder) {
}

public void setAudioSamplingRate(int samplingRate) {
mSamplingRate = samplingRate;
mQuality.samplingRate = samplingRate;
}

public void setAudioQuality(AudioQuality quality) {
mQuality = quality;
}

/**
* Returns the quality of the stream.
*/
public AudioQuality getAudioQuality() {
return mQuality;
}

/**
* Sets the encoding bit rate for the stream.
* @param bitRate bit rate in bit per second
*/
public void setAudioEncodingBitRate(int bitRate) {
mQuality.bitRate = bitRate;
}

@Override
protected void encodeWithMediaRecorder() throws IOException {

// We need a local socket to forward data output by the camera to the packetizer
createSockets();

Log.v(TAG,"Requested audio with "+mQuality.bitRate/1000+"kbps"+" at "+mQuality.samplingRate/1000+"kHz");

mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(mAudioSource);
mMediaRecorder.setOutputFormat(mOutputFormat);
mMediaRecorder.setAudioEncoder(mAudioEncoder);
mMediaRecorder.setAudioChannels(1);
mMediaRecorder.setAudioSamplingRate(mSamplingRate);
mMediaRecorder.setAudioSamplingRate(mQuality.samplingRate);
mMediaRecorder.setAudioEncodingBitRate(mQuality.bitRate);

// We write the ouput of the camera in a local socket instead of a file !
// This one little trick makes streaming feasible quiet simply: data from the camera
Expand Down
Loading

0 comments on commit bd1f006

Please sign in to comment.