private async Task <AudioEncodingProperties> ParseEncodingFromMediaAsync() { //grab the first frame and strip it for information AudioEncodingProperties obtainedProperties = null; IBuffer buffer = null; if (AudioInfo.AudioFormat == StreamAudioFormat.AAC) { //obtainedProperties = AudioEncodingProperties.CreateAac(0, 2, 0); throw new Exception("Not supported."); } var provider = AudioProviderFactory.GetAudioProvider(AudioInfo.AudioFormat); ServerAudioInfo firstFrame = await provider.GrabFrameInfoAsync(streamProcessor, AudioInfo).ConfigureAwait(false); //loop until we receive a few "frames" with identical information. while (true) { cancelTokenSource.Token.ThrowIfCancellationRequested(); ServerAudioInfo secondFrame = await provider.GrabFrameInfoAsync(streamProcessor, AudioInfo).ConfigureAwait(false); if (firstFrame.BitRate == secondFrame.BitRate && firstFrame.SampleRate == secondFrame.SampleRate) { //both frames are identical, use one of them and escape the loop. AudioInfo = firstFrame; break; } else { //frames aren't identical, get rid of the first one using the second frame and loop back. firstFrame = secondFrame; continue; } } cancelTokenSource.Token.ThrowIfCancellationRequested(); if (AudioInfo.AudioFormat == StreamAudioFormat.MP3) { //skip the entire first frame/sample to get back on track await socket.LoadAsync(MP3Parser.mp3_sampleSize - MP3Parser.HeaderLength); buffer = await socket.ReadBufferAsync(MP3Parser.mp3_sampleSize - MP3Parser.HeaderLength); //streamProcessor.byteOffset += MP3Parser.mp3_sampleSize - MP3Parser.HeaderLength; obtainedProperties = AudioEncodingProperties.CreateMp3((uint)AudioInfo.SampleRate, (uint)AudioInfo.ChannelCount, AudioInfo.BitRate); } else if (AudioInfo.AudioFormat == StreamAudioFormat.AAC_ADTS) { //skip the entire first frame/sample to get back on track await socket.LoadAsync(AAC_ADTSParser.aac_adts_sampleSize - AAC_ADTSParser.HeaderLength); buffer = await socket.ReadBufferAsync(AAC_ADTSParser.aac_adts_sampleSize - AAC_ADTSParser.HeaderLength); //streamProcessor.byteOffset += AAC_ADTSParser.aac_adts_sampleSize - AAC_ADTSParser.HeaderLength; obtainedProperties = AudioEncodingProperties.CreateAacAdts((uint)AudioInfo.SampleRate, (uint)AudioInfo.ChannelCount, AudioInfo.BitRate); } else { throw new Exception("Unsupported format."); } if (serverSettings.RequestSongMetdata) { streamProcessor.metadataPos += buffer.Length; //very important or it will throw everything off! } return(obtainedProperties); }
internal async Task <MediaStreamSample> GetNextSampleAsync(CancellationToken cancelToken) { if (sampleProvider == null) { sampleProvider = AudioProviderFactory.GetAudioProvider(shoutcastStream.AudioInfo.AudioFormat); } //todo check for internet connection and socket connection as well cancelToken.ThrowIfCancellationRequested(); MediaStreamSample sample = null; uint sampleLength = 0; //if metadataPos is less than sampleSize away from metadataInt if (shoutcastStream.serverSettings.RequestSongMetdata && (shoutcastStream.metadataInt - metadataPos <= sampleProvider.GetSampleSize() && shoutcastStream.metadataInt - metadataPos > 0)) { //parse part of the frame. byte[] partialFrame = new byte[shoutcastStream.metadataInt - metadataPos]; var read = await socket.LoadAsync(shoutcastStream.metadataInt - metadataPos); if (read == 0 || read < partialFrame.Length) { //disconnected. throw new ShoutcastDisconnectionException(); } await socket.ReadBytesAsync(partialFrame); metadataPos += shoutcastStream.metadataInt - metadataPos; Tuple <MediaStreamSample, uint> result = await sampleProvider.ParseSampleAsync(this, socket, partial : true, partialBytes : partialFrame).ConfigureAwait(false); sample = result.Item1; sampleLength = result.Item2; cancelToken.ThrowIfCancellationRequested(); } else { await HandleMetadataAsync(cancelToken); Tuple <MediaStreamSample, uint> result = await sampleProvider.ParseSampleAsync(this, socket).ConfigureAwait(false); sample = result.Item1; sampleLength = result.Item2; cancelToken.ThrowIfCancellationRequested(); if (sample == null || sampleLength == 0) //OLD bug: on RELEASE builds, sample.Buffer causes the app to die due to a possible .NET Native bug { //MediaStreamSource.NotifyError(MediaStreamSourceErrorStatus.DecodeError); //deferral.Complete(); //return; return(null); } else { if (shoutcastStream.serverSettings.RequestSongMetdata) { metadataPos += sampleLength; } } } return(sample); }