ashish-codeware / xuggle

Automatically exported from code.google.com/p/xuggle
0 stars 0 forks source link

IPacket.get and IPacket.getByteBuffer bork on MP3 streams with variable length frames #266

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
The underlying ByteBuffer appears to be reused (of fixed capacity) and doesn't 
seem to like variable length packets (frames) that are present in MP3 streams. 
Even with CBR MP3 files, when the first packet/frame is smaller than any 
subsequent packets then calls to the ByteBuffer will fail on those packets.

// Allocate a new IContainer object and open an MP3 file in READ mode:
IContainer container = IContainer.make();
container.open([MP3_FILE], IContainer.Type.READ, null);

// Allocate a new IPacket
IPacket packet = IPacket.make();

// Allocate a new byte array as an intermediary buffer large enough for any
//   potential packet
byte[] buffer = new byte[32 * 1024];

// Read first packet in stream to get it out of the way
container.readNextPacket(packet);

// Grab the rest
while (container.readNextPacket(packet) >= 0) {

    // Returns NULL if this packet size > first packet size
    // (Internal overflow)    
    packet.getByteBuffer();

    // Throws IndexOutOfBoundsException on the underlying ByteBuffer if
    //   this packet size > first packet size
    //  ---------------------------------------------------------
    //     IBuffer.validateArgs --
    //       if (bufferPos + length > bufferSize) throw new IndexOutOfBoundsException();
    //  (bufferSize is always first packet size and length is from packet.size)
    packet.get(0, buffer, 0, packet.size());
}

For example with a CBR 320kbps MP3 stream, when the first frame is 1044 bytes 
and 90% of the rest are 1045 (padding bit set, so one byte longer) you must 
discard the last byte for each. When reading a VBR stream and the first frame 
is short (silence, for example), the rest of the stream is entirely unusable.

XugglerJNI.IStreamCoder_decodeAudio doesn't seem the have this issue (verified 
with DecodeAndPlayAudio on my test files) as it is using a pointer to the 
underlying native packet object to get and process the stream.

As a side note (and possibly a separate issue) IPacket.getPosition will often 
return -1 on one of my test files (a VBR MPEG-1 Layer 3 stream).

Tested on Windows 7 x64, JRE 7 32-bit

Original issue reported on code.google.com by adriangu...@gmail.com on 2 Jun 2011 at 5:53

GoogleCodeExporter commented 9 years ago
Seems this issue is related to this one: 
http://code.google.com/p/xuggle/issues/detail?id=229

Original comment by juangon@gmail.com on 10 Nov 2011 at 11:42