#30 - changes audio broadcaster to send full/complete MP3 frames instead of partial frames in order to reduce remote server disconnnects due to MP3 frame sync loss on remote server.

This commit is contained in:
Denny
2016-12-29 08:20:10 -05:00
parent a4e3c53ba8
commit e71a1dbeda
3 changed files with 40 additions and 23 deletions

View File

@@ -265,7 +265,7 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
{ {
if(mBroadcastState != state) if(mBroadcastState != state)
{ {
mLog.info("[" + getStreamName() + "] changing state to: " + state); mLog.info("[" + getStreamName() + "] state: " + state);
mBroadcastState = state; mBroadcastState = state;
broadcast(new BroadcastEvent(this, BroadcastEvent.Event.BROADCASTER_STATE_CHANGE)); broadcast(new BroadcastEvent(this, BroadcastEvent.Event.BROADCASTER_STATE_CHANGE));
@@ -332,8 +332,9 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
{ {
private AtomicBoolean mProcessing = new AtomicBoolean(); private AtomicBoolean mProcessing = new AtomicBoolean();
private ByteArrayInputStream mInputStream; private ByteArrayInputStream mInputStream;
private int mAverageBytesPerInterval;
private long mFinalSilencePadding = 0; private long mFinalSilencePadding = 0;
private int mBytesStreamedActual = 0;
private int mBytesStreamedRequired = 0;
@Override @Override
public void run() public void run()
@@ -353,13 +354,20 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
if(mInputStream != null) if(mInputStream != null)
{ {
int length = Math.min(mAverageBytesPerInterval, mInputStream.available()); //We need to stream at 13.888 fps (144 byte frame) to achieve 2000 Bps or 16 kbps
mBytesStreamedRequired += 2000; //2000 bytes per second for 16 kbps data rate
int bytesToStream = mBytesStreamedRequired - mBytesStreamedActual;
//Trim length to whole-frame intervals (144 byte frame)
bytesToStream -= (bytesToStream % 144);
int length = Math.min(bytesToStream, mInputStream.available());
byte[] audio = new byte[length]; byte[] audio = new byte[length];
try try
{ {
mInputStream.read(audio); mBytesStreamedActual += mInputStream.read(audio);
broadcastAudio(audio); broadcastAudio(audio);
} }
@@ -382,6 +390,9 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
*/ */
private void nextRecording() private void nextRecording()
{ {
mBytesStreamedActual = 0;
mBytesStreamedRequired = 0;
boolean metadataUpdateRequired = false; boolean metadataUpdateRequired = false;
if(mInputStream != null) if(mInputStream != null)
@@ -408,15 +419,13 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
{ {
mInputStream = new ByteArrayInputStream(audio); mInputStream = new ByteArrayInputStream(audio);
double intervals = (double)recording.getRecordingLength() / (double)PROCESSOR_RUN_INTERVAL_MS; mFinalSilencePadding = PROCESSOR_RUN_INTERVAL_MS -
(recording.getRecordingLength() % PROCESSOR_RUN_INTERVAL_MS);
mAverageBytesPerInterval = (int)((double)mInputStream.available() / intervals); while(mFinalSilencePadding >= PROCESSOR_RUN_INTERVAL_MS)
{
int wholeIntervals = (int)Math.floor(intervals) + 1; mFinalSilencePadding -= PROCESSOR_RUN_INTERVAL_MS;
}
//Silence padding to transmit at the end to keep stream length at multiples of run interval
mFinalSilencePadding = (wholeIntervals * PROCESSOR_RUN_INTERVAL_MS) -
recording.getRecordingLength();
if(connected()) if(connected())
{ {

View File

@@ -248,7 +248,6 @@ public class ShoutcastV1AudioBroadcaster extends ShoutcastAudioBroadcaster
@Override @Override
public void messageReceived(IoSession session, Object object) throws Exception public void messageReceived(IoSession session, Object object) throws Exception
{ {
mLog.debug("Message Received:" + object.toString());
if(object instanceof String) if(object instanceof String)
{ {
String message = (String)object; String message = (String)object;

View File

@@ -57,18 +57,27 @@ public class MP3SilenceGenerator implements ISilenceGenerator
{ {
mLog.debug("Starting ..."); mLog.debug("Starting ...");
MP3SilenceGenerator generator = new MP3SilenceGenerator(); // MP3SilenceGenerator generator = new MP3SilenceGenerator();
//
// int sampleCount = 0;
//
// int block = 1;
//
// for(long x = 0; x < 5000; x ++)
// {
// byte[] silence = generator.generate(block);
//
// sampleCount += block;
//
// if(silence.length > 0)
// {
// mLog.debug("Silence:" + x + " Count:" + sampleCount + " Length:" + silence.length);
// }
// }
int sampleCount = 0; for(int x = 1; x <= 288; x++)
int block = 1;
for(long x = 0; x < 500; x ++)
{ {
byte[] silence = generator.generate(block); mLog.debug(x + ": " + (x / 144));
sampleCount += block;
mLog.debug("Silence:" + x + " Count:" + sampleCount + " Length:" + silence.length);
} }
mLog.debug("Finished"); mLog.debug("Finished");