pasluc74669 pasluc74669 - 2 months ago 12
iOS Question

xamarin.ios mp3 streaming from url stops before its end

I'm developing an ios app with xamarin, that contains some mp3 files to stream in the app.

i used thissample, and it seems to work fine...

but the mp3 stops before its end, always at around 2' 30"

this is the code i used:

public partial class PlayerViewController : UIViewController
{
NSTimer updatingTimer;
StreamingPlayback player;

public event EventHandler<ErrorArg> ErrorOccurred;

public string SourceUrl { get; private set; }

public string Title { get; private set; }

public PlayerOption PlayerOption { get; private set; }

public bool IsPlaying { get; private set; }

public PlayerViewController (PlayerOption playerOption, string sourceUrl, string title) : base ("PlayerViewController", null)
{
PlayerOption = playerOption;
SourceUrl = sourceUrl;
Title = title;
}

public override void ViewDidLoad ()
{
base.ViewDidLoad ();

this.View = View;
volumeSlider.TouchUpInside += SetVolume;
playPauseButton.TouchUpInside += PlayPauseButtonClickHandler;
headerMusic.Text = this.Title;
}

void SetVolume (object sender, EventArgs e)
{
if (player == null)
return;

player.Volume = volumeSlider.Value;
}

public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
Title = PlayerOption == PlayerOption.Stream ? "Stream " : "Stream & Save";
playPauseButton.TitleLabel.Text = "Pause";
timeLabel.Text = string.Empty;

// Create a shared intance session & check
var session = AVAudioSession.SharedInstance ();
if (session == null) {
var alert = new UIAlertView ("Playback error", "Unable to playback stream", null, "Cancel");
alert.Show ();
alert.Clicked += (object sender, UIButtonEventArgs e) => alert.DismissWithClickedButtonIndex (0, true);
} else {
StartPlayback ();
IsPlaying = true;

// Set up the session for playback category
NSError error;
session.SetCategory (AVAudioSessionCategory.Playback, AVAudioSessionCategoryOptions.DefaultToSpeaker);
session.OverrideOutputAudioPort (AVAudioSessionPortOverride.Speaker, out error);
}
}

public override void ViewDidDisappear (bool animated)
{
base.ViewDidDisappear (animated);

if (updatingTimer != null)
updatingTimer.Invalidate ();

if (player != null) {
player.FlushAndClose ();
player = null;
}
}

void PlayPauseButtonClickHandler (object sender, EventArgs e)
{
if (player == null)
return;

if (IsPlaying)
player.Pause ();
else
player.Play ();

var title = IsPlaying ? "Play" : "Pause";
playPauseButton.SetTitle (title, UIControlState.Normal);
playPauseButton.SetTitle (title, UIControlState.Selected);
IsPlaying = !IsPlaying;
}

void StartPlayback ()
{
try {
var request = (HttpWebRequest)WebRequest.Create (SourceUrl);
request.BeginGetResponse (StreamDownloadedHandler, request);
} catch (Exception e) {
string.Format ("Error: {0}", e.ToString ());
}
}

void RaiseErrorOccurredEvent (string message)
{
var handler = ErrorOccurred;
if (handler != null)
handler (this, new ErrorArg { Description = message });
}

void StreamDownloadedHandler (IAsyncResult result)
{
var buffer = new byte [8192];
int l = 0;
int inputStreamLength;
double sampleRate = 0;

Stream inputStream;
AudioQueueTimeline timeline = null;

var request = result.AsyncState as HttpWebRequest;
try {
var response = request.EndGetResponse (result);
var responseStream = response.GetResponseStream ();

if (PlayerOption == PlayerOption.StreamAndSave)
inputStream = GetQueueStream (responseStream);
else
inputStream = responseStream;

using (player = new StreamingPlayback ()) {
player.OutputReady += delegate {
timeline = player.OutputQueue.CreateTimeline ();
sampleRate = player.OutputQueue.SampleRate;
};

InvokeOnMainThread (delegate {
if (updatingTimer != null)
updatingTimer.Invalidate ();

updatingTimer = NSTimer.CreateRepeatingScheduledTimer (0.5, (timer) => RepeatingAction (timeline, sampleRate));
});

while ((inputStreamLength = inputStream.Read (buffer, 0, buffer.Length)) != 0 && player != null) {
l += inputStreamLength;
player.ParseBytes (buffer, inputStreamLength, false, l == (int)response.ContentLength);

InvokeOnMainThread (delegate {
progressBar.Progress = l / (float)response.ContentLength;
});
}
}

} catch (Exception e) {
RaiseErrorOccurredEvent ("Error fetching response stream\n" + e);
Debug.WriteLine (e);
InvokeOnMainThread (delegate {
if (NavigationController != null)
NavigationController.PopToRootViewController (true);
});
}
}

void RepeatingAction (AudioQueueTimeline timeline, double sampleRate)
{
var queue = player.OutputQueue;
if (queue == null || timeline == null)
return;

bool disc = false;
var time = new AudioTimeStamp ();
queue.GetCurrentTime (timeline, ref time, ref disc);

playbackTime.Text = FormatTime (time.SampleTime / sampleRate);
}

string FormatTime (double time)
{
double minutes = time / 60;
double seconds = time % 60;

return String.Format ("{0}:{1:D2}", (int)minutes, (int)seconds);
}

Stream GetQueueStream (Stream responseStream)
{
var queueStream = new QueueStream (Environment.GetFolderPath (Environment.SpecialFolder.Personal) + "/copy.mp3");
var t = new Thread ((x) => {
var tbuf = new byte [8192];
int count;

while ((count = responseStream.Read (tbuf, 0, tbuf.Length)) != 0)
queueStream.Push (tbuf, 0, count);

});
t.Start ();
return queueStream;
}
}


how can i solve this problem?
thanks in advance

Answer

Had the same issue. Open the StreamingPlayback.cs file

Change the variable

int bufferSize = 128 * 1024

Into

int bufferSize = 128 * 128

Or try other sizes..

It worked for me