Update ffmpeg/x264 which provide amongs the other periodic intra refresh feature (instead of a big keyframe, the keyframe is spread over many frames). It provides also resilience to packet loss.

cusax-fix
Sebastien Vincent 16 years ago
parent 81c23e6cd0
commit 7ff79a95ef

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1,15 +1,13 @@
1. x264-snapshot-20091208-2245
1. x264-snapshot-20100518-2245
- Windows
32-bit
Download yasm for Windows (32-bit or 64-bit) at http://www.tortall.net/projects/yasm/wiki/Download
and copy it to C:\MinGW\bin (or in a directory registered in the PATH environment variable).
./configure --disable-pthread
make
64-bit
./configure --disable-pthread --disable-avs-input --disable-asm
make
- FreeBSD
Apply x264_bsd.diff patch first and compile:
@ -22,14 +20,14 @@ gmake
./configure --enable-pic
make
2. ffmpeg-r20783
2. ffmpeg-r23181
First patch ffmpeg with ffmpeg-libx264-keyframe.diff:
$ patch -p0 < ffmpeg-libx264-keyframe.diff
First patch ffmpeg with ffmpeg-23181.diff
patch -p0 < ffmpeg-23181.diff
- Windows
32-bit
32-bit:
./configure \
--target-os=mingw32 \
--enable-memalign-hack \
@ -44,10 +42,10 @@ $ patch -p0 < ffmpeg-libx264-keyframe.diff
--disable-ffserver --disable-ffplay --disable-ffmpeg \
--disable-pthreads --enable-w32threads
64-bit
Edit configure script and remove the following lines:
check_cpp_condition _mingw.h "(__MINGW32_MAJOR_VERSION > 3) || (__MINGW32_MAJOR_VERSION == 3 && __MINGW32_MINOR_VERSION >= 15)" ||
die "ERROR: MinGW runtime version must be >= 3.15."
64-bit:
Patch again ffmpeg with ffmpeg-win64.diff
patch -p0 < ffmpeg-win64.diff
Then run:
./configure \
@ -109,12 +107,3 @@ Be careful to correctly set X264_HOME, FFMPEG_HOME and JAVA_HOME variables.
Then run:
make (gmake on FreeBSD)
Note:
If compilation errors related to "relocation" occured, you
have to patch ffmpeg, libswscale and x264.
Apply the following patches in the relevant directory:
- x264-20091208-visibility-hidden.patch
- ffmpeg-visibility-hidden.patch
- ffmpeg-libswcale-visibility-hidden.patch

@ -0,0 +1,73 @@
Index: libavcodec/libx264.c
===================================================================
--- libavcodec/libx264.c (revision 23181)
+++ libavcodec/libx264.c (working copy)
@@ -99,15 +99,17 @@
}
x4->pic.i_pts = frame->pts;
- x4->pic.i_type = X264_TYPE_AUTO;
+ x4->pic.i_type = frame->key_frame ? X264_TYPE_IDR : X264_TYPE_AUTO;
}
+ do {
if (x264_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL, &pic_out) < 0)
return -1;
bufsize = encode_nals(ctx, buf, bufsize, nal, nnal, 0);
if (bufsize < 0)
return -1;
+ } while(!bufsize && !frame && x264_encoder_delayed_frames(x4->enc));
/* FIXME: libx264 now provides DTS, but AVFrame doesn't have a field for it. */
x4->out_pic.pts = pic_out.i_pts;
@@ -156,7 +158,7 @@
x4->params.p_log_private = avctx;
x4->params.i_keyint_max = avctx->gop_size;
- x4->params.b_intra_refresh = avctx->flags2 & CODEC_FLAG2_INTRA_REFRESH;
+ x4->params.b_intra_refresh = 1; /* avctx->flags2 & CODEC_FLAG2_INTRA_REFRESH; */
x4->params.rc.i_bitrate = avctx->bit_rate / 1000;
x4->params.rc.i_vbv_buffer_size = avctx->rc_buffer_size / 1000;
x4->params.rc.i_vbv_max_bitrate = avctx->rc_max_rate / 1000;
@@ -173,7 +175,7 @@
x4->params.rc.i_qp_constant = avctx->cqp;
}
}
-
+
// if neither crf nor cqp modes are selected we have to enable the RC
// we do it this way because we cannot check if the bitrate has been set
if (!(avctx->crf || (avctx->cqp > -1)))
@@ -186,7 +188,7 @@
x4->params.i_bframe_pyramid = avctx->flags2 & CODEC_FLAG2_BPYRAMID ? X264_B_PYRAMID_NORMAL : X264_B_PYRAMID_NONE;
avctx->has_b_frames = avctx->flags2 & CODEC_FLAG2_BPYRAMID ? 2 : !!avctx->max_b_frames;
- x4->params.i_keyint_min = avctx->keyint_min;
+ x4->params.i_keyint_min = 0; /* avctx->keyint_min; */
if (x4->params.i_keyint_min > x4->params.i_keyint_max)
x4->params.i_keyint_min = x4->params.i_keyint_max;
@@ -293,6 +295,13 @@
if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER)
x4->params.b_repeat_headers = 0;
+
+ /* zero latency */
+ x4->params.rc.i_lookahead = 0;
+ x4->params.i_sync_lookahead = 0;
+ x4->params.i_bframe = 0;
+ x4->params.b_sliced_threads = 1;
+ x4->params.b_vfr_input = 0;
x4->enc = x264_encoder_open(&x4->params);
if (!x4->enc)
@@ -313,7 +322,7 @@
avctx->extradata = av_malloc(s);
avctx->extradata_size = encode_nals(avctx, avctx->extradata, s, nal, nnal, 1);
}
-
+
return 0;
}

@ -1,13 +0,0 @@
Index: libavcodec/libx264.c
===================================================================
--- libavcodec/libx264.c (révision 20783)
+++ libavcodec/libx264.c (copie de travail)
@@ -99,7 +99,7 @@
}
x4->pic.i_pts = frame->pts;
- x4->pic.i_type = X264_TYPE_AUTO;
+ x4->pic.i_type = frame->key_frame ? X264_TYPE_IDR : X264_TYPE_AUTO;
}
if (x264_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL, &pic_out) < 0)

@ -0,0 +1,22 @@
Index: libswscale/swscale_template.c
===================================================================
--- libswscale/swscale_template.c (révision 31187)
+++ libswscale/swscale_template.c (copie de travail)
@@ -2252,7 +2252,7 @@
"shrl $9, %%esi \n\t" \
static inline void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst,
- long dstWidth, const uint8_t *src, int srcW,
+ x86_reg dstWidth, const uint8_t *src, int srcW,
int xInc)
{
#if ARCH_X86
@@ -2401,7 +2401,7 @@
}
static inline void RENAME(hcscale_fast)(SwsContext *c, int16_t *dst,
- long dstWidth, const uint8_t *src1,
+ x86_reg dstWidth, const uint8_t *src1,
const uint8_t *src2, int srcW, int xInc)
{
#if ARCH_X86

@ -527,7 +527,7 @@ JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_codec_video_
ret
= sws_scale (
(struct SwsContext *) context,
(uint8_t **) srcPicture->data, (int *) srcPicture->linesize,
(const uint8_t * const *) srcPicture->data, (int *) srcPicture->linesize,
(int) srcSliceY, (int) srcSliceH,
(uint8_t **) dstPicture.data,
(int *) dstPicture.linesize);

@ -158,7 +158,10 @@ public class MediaUtils
= new HashMap<String, String>();
h264FormatParams.put("packetization-mode", "1");
h264AdvancedAttributes.put("rtcp-fb", "nack pli");
/* disable PLI since we use periodic intra-refresh feature
* of ffmpeg/x264
*/
//h264AdvancedAttributes.put("rtcp-fb", "nack pli");
ScreenDevice screen = NeomediaActivator.getMediaServiceImpl().
getDefaultScreenDevice();

@ -284,7 +284,7 @@ protected void configureDataOutputStream(
{
super.configureDataOutputStream(dataOutputStream);
dataOutputStream.setMaxPacketsPerMillis(1, 10);
dataOutputStream.setMaxPacketsPerMillis(-1, 10);
}
/**

@ -35,9 +35,9 @@ public class JNIEncoder
= { new VideoFormat(Constants.H264) };
/**
* Key frame every 300 frames.
* Key frame every 45 frames.
*/
private static final int IFRAME_INTERVAL = 300;
private static final int IFRAME_INTERVAL = 45;
/**
* Padding size.
@ -91,8 +91,19 @@ public class JNIEncoder
/**
* Force encoder to send a key frame.
* First frame have to be a keyframe.
*/
private boolean forceKeyFrame = false;
private boolean forceKeyFrame = true;
/**
* Peer that receive stream from latest ffmpeg/x264 aware peer does not
* manage to decode the first keyframe and must wait for the next periodic
* intra refresh to display the video to the user.
*
* Temporary solution for this probolem: send the two first frames as
* keyframe to display video stream.
*/
private boolean secondKeyFrame = true;
/**
* Last keyframe request time.
@ -233,7 +244,7 @@ public synchronized void open()
FFmpeg.avcodeccontext_set_bit_rate(avcontext, _bitRate);
// so to be 1 in x264
FFmpeg.avcodeccontext_set_bit_rate_tolerance(avcontext, _bitRate);
FFmpeg.avcodeccontext_set_rc_max_rate(avcontext, _bitRate);
//FFmpeg.avcodeccontext_set_rc_max_rate(avcontext, 0);
FFmpeg.avcodeccontext_set_sample_aspect_ratio(avcontext, 0, 0);
FFmpeg.avcodeccontext_set_thread_count(avcontext, 1);
// time_base should be 1 / frame rate
@ -265,7 +276,7 @@ public synchronized void open()
FFmpeg.avcodeccontext_set_gop_size(avcontext, IFRAME_INTERVAL);
FFmpeg.avcodeccontext_set_i_quant_factor(avcontext, 1f / 1.4f);
FFmpeg.avcodeccontext_set_refs(avcontext, 4);
FFmpeg.avcodeccontext_set_refs(avcontext, 1);
FFmpeg.avcodeccontext_set_trellis(avcontext, 2);
/*
@ -343,11 +354,21 @@ public synchronized int process(Buffer inBuffer, Buffer outBuffer)
(byte[]) inBuffer.getData(), inBuffer.getOffset(),
encFrameLen);
if (framesSinceLastIFrame >= IFRAME_INTERVAL || forceKeyFrame)
if (/* framesSinceLastIFrame >= IFRAME_INTERVAL || */ forceKeyFrame)
{
FFmpeg.avframe_set_key_frame(avframe, true);
framesSinceLastIFrame = 0;
forceKeyFrame = false;
/* send keyframe for the first two frames */
if(secondKeyFrame)
{
secondKeyFrame = false;
forceKeyFrame = true;
}
else
{
forceKeyFrame = false;
}
}
else
{
@ -518,7 +539,8 @@ public void feedbackReceived(RTCPFeedbackEvent event)
+ PLI_INTERVAL)
{
lastKeyframeRequestTime = System.currentTimeMillis();
forceKeyFrame = true;
/* disable PLI */
//forceKeyFrame = true;
}
break;
default:

Loading…
Cancel
Save