I am trying to create a compressed h264 video file from a series of raw rgb24 pixel data. Pixel data is streamed from java application to ffmpeg.exe which is its subprocess.
For testing purposes I've created a byte array with rgb24 pixel data and then sent it to ffmpeg's input stream.
Everything works fine except one issue.
It looks like the frame rate of the encoded file is wrong. FFMpeg should compress the video file with 30fps rate (-r 30).
I am sending 30*20 frames. So I supposed to get a video file with length of 20 seconds. But instead of that the video file's length is 24 seconds. When I check the compressed file properties, it shows 30fps as expected.
It looks like the ratio between expected and actual frame rate is 5 to 6 (20 --> 24,30 --> 36). I have also tried to stream rgb32 pixel data but I had the same results.
code:
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
//building the frame
for (int i=0; i<1024*800; i++)
{
byteArray.write(i&0xFF); //r
byteArray.write(i&0xFF); //g
byteArray.write(i&0xFF); //b
}
byte pixelData[] = byteArray.toByteArray();
File ffmpeg_output_msg = new File("ffmpeg_output_msg.txt");
ProcessBuilder pb = new ProcessBuilder("ffmpeg.exe","-vcodec","rawvideo","-f","rawvideo","-pix_fmt","rgb24","-s","1024x800","-i","pipe:0","-r","30","-y","-c:v","libx264","out.mkv");
pb.redirectErrorStream(true);
pb.redirectOutput(ffmpeg_output_msg);
Process p = pb.start();
OutputStream ffmpegInput = p.getOutputStream();
//30fps, 20secs
for(int i=0;i<30*20;i++)
{
ffmpegInput.write(pixelData);
}
ffmpegInput.flush();
ffmpegInput.close();
Any ideas what could be the origin of that problem? Thanks in advance
UPDATE I have changed the frame rate to other values and it looks like the ffmpeg completely ignores that parameter. It always uses 25fps. using "-r 30" effects only on the data that's written in file's properties (Video: MPEG4 Video (H264) 1024x800 30fps [Video])
Is it possible that there are two different framerates in the encoded file?
ok, solved it.
I had to force fps on the output and also on the input streams. Adding -r 30 before -i, tells ffmpeg that input stream has 30 fps rate.
final ffmpeg:
ffmpeg.exe -r 30 -vcodec rawvideo -f rawvideo -pix_fmt rgb24 -s 1024x800 -i pipe:0 -y -c:v libx264 -r 30 out.mkv