Fail Parsing M4A, AAC file with Apple Audio File Stream Services, iOS 7
Asked Answered
M

2

10

I'm using this tutorial Multipeer Connectivity Audio Stream To Multiple Peers and this project Github Repository , in order to stream audio from NSInputStream, which is obtained by:

-(void)session:didReceiveStream:withName:fromPeer:

MCSession delegate method.

After, this open a new Audio File Stream (TDAudioFileStreamer/Classes/AudioFileStream.m:39):

OSStatus err = AudioFileStreamOpen((__bridge void *)self, TDAudioFileStreamPropertyListener, TDAudioFileStreamPacketsListener, 0, &_audioFileStreamID); 

Then read bytes from NSInputStream and try to parse by this way (TDAudioFileStreamer/Classes/AudioFileStream.m:98):

err = AudioFileStreamParseBytes(self.audioFileStreamID, length, data, kAudioFileStreamParseFlag_Discontinuity);

Or:

err = AudioFileStreamParseBytes(self.audioFileStreamID, length, data, 0);

Depending of the data flow.

And finally, this fill AudioQueue Buffer with the parsed data in order to playback (i guess - TDAudioFileStreamer/Classes/TDAudioQueueFiller.m) .

This works really nice for MP3 format files, but with others formats when try to parse the bytes get "unsupported file format" error.

The Apple documentation, says Audio File Stream services support a lot of formats and they are listed in this Link: Apple Stream Services supported formats, but for me only works with MP3.

I was trying too, when open the Audio File Stream pass a hint about file format like this and send a M4A or AAC file:

OSStatus err = AudioFileStreamOpen((__bridge void *)self, TDAudioFileStreamPropertyListener, TDAudioFileStreamPacketsListener, kAudioFileAAC_ADTSType, &_audioFileStreamID);

Where kAudioFileAAC_ADTSType is the type of sent file that will be streamed, by this way , the "unsupported file format error" disappears , but the application crashes and get a new error enter image description here

This says: io: lpc and client: aac.

  • Someone know what this mean?
  • The Queue is expecting AAC format file?
  • Why LPCM( Linear Pulse Code Modulation), i'm sending M4A or AAC not LPCM?

Thanks in advance.

Mancuso answered 6/5, 2014 at 19:17 Comment(3)
Hello i'm facing with the same problem. Did you find any solution for this problem.Gaultiero
Not yet, only I find a lot of pain. Sry.Mancuso
You probably has tried this already, but you know that there are protected sound types. What I meant to say is try different types of .m4a. Some are protected and can't be played. Most of them are from the itunes store themself and can't be played.Settee
F
4

In order stream/parse M4A with AudioFileStream, the m4a file needs to be optimized for streaming.

That means the header needs to be in the front of the file and has the correct information that will let your parser to do its job.

Some encoders will optimize the m4a for you, but some encoders wont. For example If you create an m4a file with itunes player, by simply right clicking and choosing "Create AAC Version", that will create an m4a file that is optimized for streaming.

You can check it by using http://ridiculousfish.com/hexfiend/

enter image description here

but if you use lets say encoding.com to encode your m4a files, you will get a different type of encoding.

they will both work when playing the whole file from disk but optimized version will be parsed/streamed correctly.

Now the error you are getting tells you that parser couldnt get the correct AudioStreamBasicDescription from the file you are parsing, file probably refuse to give the bitrate info...

Try to take a look at this code for better understanding handling m4a types http://www.cocoawithlove.com/2010/03/streaming-mp3aac-audio-again.html

Foeman answered 14/5, 2015 at 16:20 Comment(0)
A
-1

The trick here is that you need to get and set the necessary properties for m4a format in the right place, namely in the callback (in your case) TDAudioFileStreamPropertyListener. Check argument AudioFileStreamPropertyID when it will fit property kAudioFileStreamProperty_ReadyToProducePackets and then paste this:

 UInt32 cookieSize = 0;
            OSStatus error = AudioFileStreamGetPropertyInfo(audioFileStream, kAudioFilePropertyMagicCookieData, &cookieSize, NULL);
            // If there is an error here, then track from stream doesn't have a cookie
            if (error == noErr && cookieSize != 0) {
                char *cookie = malloc(cookieSize * sizeof(char));
                error = AudioFileStreamGetProperty(audioFileStream, kAudioFilePropertyMagicCookieData, &cookieSize, cookie);
                if (error == noErr) {
                    error = AudioConverterSetProperty(audioConverterRef, kAudioConverterDecompressionMagicCookie, cookieSize, cookie);
                    if (error != noErr) {
                        printf("Could not Set kAudioConverterDecompressionMagicCookie on the Audio Converter!");
                    }
                } else {
                    printf("Could not Get kAudioFilePropertyMagicCookieData from stream!");
                }
                free(cookie);
            }
Apyretic answered 23/11, 2018 at 21:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.