Joe Drew wrote:
At this point, I've implemented an array of pointers to each of the frame boundaries (which I calculate, since the high-level API doesn't give me this information)
Random access timing information isn't available in a vanilla mp3 stream. You have the option of calculating this in advance and storing it somewhere useful (header, separate data file, etc..) or calculating it on the fly as you describe here.
and I know very easily how to fast-forward through an mp3 (that is, just skip frames.) Is there any way other than restarting the whole decoding process and skipping frames up to the point we were looking for to seek backwards with the high-level API?
You can approximate doing so for fixed bit rate files, but for VBR you need to calculate time starting from some known accurate point of reference. In the worst case, that is the beginning of the stream. However since you have already made a pass of the stream from beginning to the current offset, keeping (time, frame) indices on a second or 1/10th second basis should be sufficiently accurate and would consume a minimal amount of memory. When you want to rewind to a prior location, find the closest index to the point of interest and start from there. Note if you want to be dead accurate and avoid any decoding artifacts, you will need to start searching/decoding from a point 2 frames ahead of the desired target (see the mad-dev mail archives for reference).
If you really don't want to "get close then seek to target", and you don't need to be dead accurate, you may be able to interpolate between two indices even in a VBR file. However in this case you need to recognize when your approximate reverse seek encounters a valid frame index in the current set and resynchronize the current time to this accurate index. However the former approach seems more straightforward to me.
I can't think of any way to re-set the stream pointers.
Note also that in your 'fast-forward' operation as well as in the normal course of decoding the input stream, you will need to inspect the existing (time, frame) indices generated thus far and extend them as you encounter new ground in the input stream.
-john