A patch that resolves the two bugs.
Hi all !
First of all, thanks for your great job !
I'm using FMJ's RTP Session Manager inside Sun's JMF framework.
I place FMJ.jar in my classpath, and I do something like this:
PackageManager.getProtocolPrefixList().add(0, "net.sf.fmj");
Then I have some troubles sending/receiving a Video stream: the buffer in RTPSendStream.transferData() is sometimes erased by other data, and wrong RTP packets are sent.
I looked up what was happening: Sun's JMF uses several buffers in their RawBufferMux (sort of double buffering). When read method is called, RawBufferMux swaps its internal buffer with the one we pass in parameters.
FMJ also does something like this:
if (recvBuffer.getData() != buffer)
System.arraycopy(recvBuffer.getData(), recvBuffer.getOffset(), buffer, RTPHeader.SIZE, recvBuffer.getLength());
As a result, we share the same buffer between Sun's JMF and FMJ ! And, then, buffer is sometimes erased by JMF !
I found a second bug about timestamp, still in RTPSendStream. In transferData, timestamp is directly taken from Buffer. But buffer's timestamp is in nanoseconds, and clockRate is not taken into account. Timestamp field in RTP is only 4 bytes... and time in nanoseconds may be greater than 4 bytes !
As a result, player receives packets with a random timestamp...
Here is a patch that resolves these bugs. It works for my application.
Thank you again for your work !
A patch that resolves the two bugs.
Logged In: NO
I've also detected that packets created by my packetizer are
overridden when sending it through the JMF RTP.
After some analyzation I've found the bug in the AbstractPacketizer.java
code.
In the process method the packetBuffer has to be recreated, because
it may be still in the output queue of the JMF (outputbuffer is not
already processed through the CircularBuffer), but there are more
incoming packets to the packetizer with further data. So code in
AbstractPacketizer may be
process(...)
...
if (packetComplete)
{
outputBuffer.setData(packetBuffer);
outputBuffer.setOffset(0);
outputBuffer.setLength(bytesInPacketBuffer);
bytesInPacketBuffer = 0;
packetBuffer = new byte[packetSize];
if (inputBuffer.getLength() == 0) result = BUFFER_PROCESSED_OK;
else
result = INPUT_BUFFER_NOT_CONSUMED;
}
....
As a workaround if you create your own packetizer create a copy of AbstractPacketizer and fix this if you subclass your packetizer from the FMJ's AbstractPacketizer.