tags:

views:

550

answers:

4

I'm trying to figure out the proper technique for performing skipping ahead or seeking within an mp4 (or m4a) audio file while playing it using the AudioFileStream and AudioQueue APIs on the iPhone.

If I pass the complete mp4 header (up to the mdat box) to an open AudioFileStream, the underlying audio file type is properly identified (in my case, AAC) and when I then pass the actual mdat data portion of the file, the AudioFileStream correctly begins generating audio packets and these can be sent to the AudioQueue and playback works.

However, if I try a random access approach to the playing back the file, I can't seem to get it to work properly, unless I always send the first frame of the mdat box to the AudioFileStream. If instead, after sending the mp4 header to the AudioFileStream, I then attempt to initially skip ahead to a later frame in the mdat by first calling AudioFileStreamSeek() and then passing the data for the associated packets, the AudioFileStream appears to generate audio packets, but when I pass these on to the AudioQueue and call AudioQueuePrime(), I always get an error of 'nope' returned.

My question is this: am I always required to at least pass in the first packet of the mdat box before attempting to do random playback of other packets in the mp4 file?

I can't seem to find any documentation on doing random playback of sections of an mp4 file while using an AudioFileStream and an AudioQueue. I've found Apple's QuickTime File Format pdf which describes the technique of randomly seeking within an mp4 file, but it's just a high level description and doesn't have any mention of using specific APIs (such as AudioFileStream).

Thanks for any insights.

+1  A: 

It turns out the approach I was using with AudioFileStreamSeek() is valid, I just wasn't sending the full initial mp4 header to the AudioFileStreamParseBytes() routine.

The problem was I had assumed the packets began immediately after the mdat box tag. By examining the data offset value (kAudioFileStreamProperty_DataOffset) returned by the AudioFileStream Property Listener callback, I discovered the true start of the packet data was 18 bytes later.

These 18 bytes are considered part of the initial mp4 header that must be sent to the AudioFileStream parser before sending the data of arbitrary packets after calls to AudioFileStreamSeek().

If these extra bytes are left out, then the AudioQueuePrime() call will always fail with a 'nope' error even though you may have sent valid parsed audio packets to the AudioQueue.

Brian Stormont
A: 

Can you provide some code for how you got this to work. I'm trying to use seek with MP4 AAC but can't seem to get it to work. Does it need to be an ADTS file?

N355A
at this point i'm settling with progressive download and allowing the user to seek within the range that has been downloaded. I'm not sure how i'm going to translate slider positon to packet offset for the audio file stream seek. When you use AudioFileStreamSeek(), remember to add the kAudioFileStreamProperty_DataOffset to the byte offset returned.
N355A
A: 

same with my case, we have 2 problems 1. i am trying with m4a format and not able to seek. i am appending the header at the beginning of seeked chunk. Even then i am getting 'nope' error. If i try to pass the header in chunks then it gives another problem of 'handleAudioPackets' call back not begin called even parsing is success. 2. And in some cases header will be found at the end so how to stream the files. Can you help us solving these 2 problems.

vikky