Skip to content
Snippets Groups Projects
Commit 3f9b8c17 authored by Lyubomir Marinov's avatar Lyubomir Marinov
Browse files

Fixes a failure to generate key frames in the H.264 encoder.

parent a9c5793a
No related branches found
No related tags found
No related merge requests found
...@@ -121,7 +121,7 @@ public class JNIEncoder ...@@ -121,7 +121,7 @@ public class JNIEncoder
* The name of the integer <tt>ConfigurationService</tt> property which * The name of the integer <tt>ConfigurationService</tt> property which
* specifies the maximum GOP (group of pictures) size i.e. the maximum * specifies the maximum GOP (group of pictures) size i.e. the maximum
* interval between keyframes. FFmpeg calls it <tt>gop_size</tt>, x264 * interval between keyframes. FFmpeg calls it <tt>gop_size</tt>, x264
* refers to it <tt>keyint</tt> or <tt>i_keyint_max</tt>. * refers to it as <tt>keyint</tt> or <tt>i_keyint_max</tt>.
*/ */
public static final String KEYINT_PNAME public static final String KEYINT_PNAME
= "org.jitsi.impl.neomedia.codec.video.h264.keyint"; = "org.jitsi.impl.neomedia.codec.video.h264.keyint";
...@@ -223,6 +223,19 @@ else if(HIGH_PROFILE.equalsIgnoreCase(profile)) ...@@ -223,6 +223,19 @@ else if(HIGH_PROFILE.equalsIgnoreCase(profile))
private KeyFrameControl.KeyFrameRequestee keyFrameRequestee; private KeyFrameControl.KeyFrameRequestee keyFrameRequestee;
/**
* The maximum GOP (group of pictures) size i.e. the maximum interval
* between keyframes (with which {@link #open()} has been invoked without an
* intervening {@link #close()}). FFmpeg calls it <tt>gop_size</tt>, x264
* refers to it as <tt>keyint</tt> or <tt>i_keyint_max</tt>.
*/
private int keyint;
/**
* The number of frames processed since the last keyframe.
*/
private int lastKeyFrame;
/** /**
* The time in milliseconds of the last request for a key frame from the * The time in milliseconds of the last request for a key frame from the
* remote peer to this local peer. * remote peer to this local peer.
...@@ -424,7 +437,16 @@ private boolean isKeyFrame() ...@@ -424,7 +437,16 @@ private boolean isKeyFrame()
forceKeyFrame = false; forceKeyFrame = false;
} }
else else
keyFrame = false; {
/*
* In order to be sure that keyint will be respected, we will
* implement it ourselves (regardless of the fact that we have told
* FFmpeg and x264 about it). Otherwise, we may end up not
* generating keyframes at all (apart from the two generated after
* open).
*/
keyFrame = (lastKeyFrame == keyint);
}
return keyFrame; return keyFrame;
} }
...@@ -650,6 +672,16 @@ else if ("h264.profile".equals(k)) ...@@ -650,6 +672,16 @@ else if ("h264.profile".equals(k))
sizeInBytes / 4); sizeInBytes / 4);
FFmpeg.avframe_set_linesize(avFrame, width, width / 2, width / 2); FFmpeg.avframe_set_linesize(avFrame, width, width / 2, width / 2);
/*
* In order to be sure that keyint will be respected, we will implement
* it ourselves (regardless of the fact that we have told FFmpeg and
* x264 about it). Otherwise, we may end up not generating keyframes at
* all (apart from the two generated after open).
*/
forceKeyFrame = true;
this.keyint = keyint;
lastKeyFrame = 0;
/* /*
* Implement the ability to have the remote peer request key frames from * Implement the ability to have the remote peer request key frames from
* this local peer. * this local peer.
...@@ -714,7 +746,19 @@ public synchronized int process(Buffer inBuffer, Buffer outBuffer) ...@@ -714,7 +746,19 @@ public synchronized int process(Buffer inBuffer, Buffer outBuffer)
(byte[]) inBuffer.getData(), inBuffer.getOffset(), (byte[]) inBuffer.getData(), inBuffer.getOffset(),
rawFrameLen); rawFrameLen);
FFmpeg.avframe_set_key_frame(avFrame, isKeyFrame()); boolean keyFrame = isKeyFrame();
FFmpeg.avframe_set_key_frame(avFrame, keyFrame);
/*
* In order to be sure that keyint will be respected, we will implement
* it ourselves (regardless of the fact that we have told FFmpeg and
* x264 about it). Otherwise, we may end up not generating keyframes at
* all (apart from the two generated after open).
*/
if (keyFrame)
lastKeyFrame = 0;
else
lastKeyFrame++;
// Encode avFrame into the data of outBuffer. // Encode avFrame into the data of outBuffer.
byte[] out byte[] out
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment