I am having application to play 30 videos at a time. I am using Xuggler
to decode video files and Swing
windows for display.
But I am facing problems like:
- Videos not displaying smooth
- With profiler I found, around 25% time was spending for garbage collection.
How can I tune garbage collector and what other performance parameters, I should take care?
Is Xuggler-Java combination not good?
EDIT
My video decoding loop was:
private boolean decodeStreams() throws Exception {
IPacket packet = IPacket.make();
long firstTimestampInStream = Global.NO_PTS;
long systemClockStartTime = 0;
viewer.urlStatusUpdate(index, Globals.STATUS_PLAYING);
while (container.readNextPacket(packet) >= 0) {
if (stopPlaying) {
if (isStopPlaying(2)) {
return false;
}
}
if (packet.getStreamIndex() == videoStreamID) {
IVideoPicture picture = IVideoPicture.make(videoCoder.getPixelType(), videoCoder.getWidth(), videoCoder.getHeight());
int offset = 0;
while (offset < packet.getSize()) {
int bytesDecoded = videoCoder.decodeVideo(picture, packet, offset);
if (bytesDecoded < 0) {
throw new Exception("Got error on decoding video");
}
offset += bytesDecoded;
if (picture.isComplete()) {
if (firstTimestampInStream == Global.NO_PTS) {
firstTimestampInStream = picture.getTimeStamp();
systemClockStartTime = System.currentTimeMillis();
} else {
long millisecondsToSleep = (
((picture.getTimeStamp() - firstTimestampInStream) / 1000)
- (System.currentTimeMillis() - systemClockStartTime)
);
if (millisecondsToSleep > 50) {
try {
Thread.sleep(millisecondsToSleep - 50);
} catch (Exception e) {
}
}
}
viewer.videoImageUpdate(index, converter.toImage(picture));
}
}
}
}
return true;
}
And I changed place of IVideoPicture declaration:
private boolean decodeStreams() throws Exception {
IPacket packet = IPacket.make();
long firstTimestampInStream = Global.NO_PTS;
long systemClockStartTime = 0;
viewer.urlStatusUpdate(index, Globals.STATUS_PLAYING);
IVideoPicture picture = IVideoPicture.make(videoCoder.getPixelType(), videoCoder.getWidth(), videoCoder.getHeight());
while (container.readNextPacket(packet) >= 0) {
if (stopPlaying) {
if (isStopPlaying(2)) {
return false;
}
}
if (packet.getStreamIndex() == videoStreamID) {
int offset = 0;
while (offset < packet.getSize()) {
int bytesDecoded = videoCoder.decodeVideo(picture, packet, offset);
if (bytesDecoded < 0) {
throw new Exception("Got error on decoding video");
}
offset += bytesDecoded;
if (picture.isComplete()) {
if (firstTimestampInStream == Global.NO_PTS) {
firstTimestampInStream = picture.getTimeStamp();
systemClockStartTime = System.currentTimeMillis();
} else {
long millisecondsToSleep = (
((picture.getTimeStamp() - firstTimestampInStream) / 1000)
- (System.currentTimeMillis() - systemClockStartTime)
);
if (millisecondsToSleep > 50) {
try {
Thread.sleep(millisecondsToSleep - 50);
} catch (Exception e) {
}
}
}
viewer.videoImageUpdate(index, converter.toImage(picture));
}
}
}
}
return true;
}
Now GC is spending less than 10% time, around 5% to 8& normally. And I got all 30 videos playing smoothly at a time.
Is changing place (Putting IVideoPicture declaration outside, and allocating memory only once) can be problem? Will timestamps of picture set everytime new video picture is decoded on allocated memory?
Thanks