[Sumover-dev] [svn commit] r4911 - in vic/branches/mpeg4: codec
video
sumover-dev at cs.ucl.ac.uk
sumover-dev at cs.ucl.ac.uk
Sun Nov 6 12:29:47 GMT 2011
Author: douglask
Date: Sun Nov 6 12:29:47 2011
New Revision: 4911
Modified:
vic/branches/mpeg4/codec/decoder-h264.cpp
vic/branches/mpeg4/codec/encoder-h264.cpp
vic/branches/mpeg4/codec/ffmpeg_codec.cpp
vic/branches/mpeg4/codec/x264encoder.cpp
vic/branches/mpeg4/main.cpp
vic/branches/mpeg4/video/deinterlace.cpp
Log:
Patch submitted by Andrew Ford:
I've been sitting on these changes for a while, thought I might send them in finally. It changes the x264 settings to be as low latency as possible (end result is roughly +100ms relative to h261), fixes a NAL packetizing issue that was blocking multi-slice encoding, and fixes a memory leak when deinterlacing is enabled.
Modified: vic/branches/mpeg4/codec/decoder-h264.cpp
==============================================================================
--- vic/branches/mpeg4/codec/decoder-h264.cpp (original)
+++ vic/branches/mpeg4/codec/decoder-h264.cpp Sun Nov 6 12:29:47 2011
@@ -52,7 +52,7 @@
int last_iframe;
bool startPkt;
- int aggregate_pkt; // Count of mbits for decoding IOCOM H.264
+ int aggregate_pkt; // Count of mbits for decoding IOCOM H.264
/* image */
UCHAR xxx_frame[MAX_FRAME_SIZE];
@@ -73,7 +73,7 @@
}
TclObject *match(const char *id)
{
- if ((strcasecmp(id, "h264") == 0 ) ||
+ if ((strcasecmp(id, "h264") == 0 ) ||
(strcasecmp(id, "h264_IOCOM") == 0))
return (new H264Decoder());
return (0);
@@ -96,7 +96,7 @@
inw_ = 352;
inh_ = 288;
- /*XXX*/
+ /*XXX*/
resize(inw_, inh_);
// libavcodec
@@ -123,7 +123,7 @@
//256 packets, each 1600 byte (default will not exceed 1600 byte)
//cout << "new PacketBuffer..\n";
- stream = new PacketBuffer(1024, 1600); //SV: 1024 = ???
+ stream = new PacketBuffer(1024, 1600); //SV: 1024 = ???
startPkt = false;
}
@@ -209,7 +209,7 @@
idx = seq;
last_seq = seq - 1;
}
-
+
int pktIdx = seq - idx;
if (pktIdx < 0) {
pktIdx = (0xFFFF - idx) + seq;
@@ -262,11 +262,11 @@
f = stream->getStream();
decodeLen = h264.decode((UCHAR *) f->getData(), f->getDataSize(), xxx_frame);
}
-
+
if (decodeLen < 0) {
debug_msg("H264_RTP: frame error\n");
}
-
+
if (inw_ != h264.width || inh_ != h264.height) {
inw_ = h264.width;
inh_ = h264.height;
Modified: vic/branches/mpeg4/codec/encoder-h264.cpp
==============================================================================
--- vic/branches/mpeg4/codec/encoder-h264.cpp (original)
+++ vic/branches/mpeg4/codec/encoder-h264.cpp Sun Nov 6 12:29:47 2011
@@ -140,15 +140,16 @@
//unsigned char f_total_pkt = 0;
int RTP_HDR_LEN = sizeof(rtphdr);
int NAL_FRAG_THRESH = tx->mtu() - RTP_HDR_LEN; /* payload max in one packet */
- //debug_msg( "MTU=%d, RTP_HDR_LEN=%d\n", NAL_FRAG_THRESH, RTP_HDR_LEN);
-
+#ifdef H264DEBUG
+ debug_msg( "MTU=%d, RTP_HDR_LEN=%d\n", NAL_FRAG_THRESH, RTP_HDR_LEN);
+#endif
tx->flush();
if (!state) {
state = true;
size(vf->width_, vf->height_);
- debug_msg("init x264 encoder with kbps:%d, fps:%d", kbps, fps);
+ debug_msg("init x264 encoder with kbps:%d, fps:%d\n", kbps, fps);
enc->setGOP(gop);
enc->init(vf->width_, vf->height_, kbps, fps);
frame_size = vf->width_ * vf->height_;
@@ -175,7 +176,9 @@
char *data = fOut->getData();
uint8_t NALhdr = data1[4]; //SV-XXX why does our x.264 provide 4-byte StartSync in the NALU?
uint8_t NALtype = NALhdr & 0x1f;
- //debug_msg( "Got NALhdr=0x%02x, NALtype=0x%02x from encoded frame.\n", NALhdr, NALtype);
+#ifdef H264DEBUG
+ debug_msg( "Got NALhdr=0x%02x, NALtype=0x%02x, nal size %i from encoded frame.\n", NALhdr, NALtype, nalSize );
+#endif
memcpy(data, &data1[5], nalSize);
sent_size += nalSize;
@@ -190,7 +193,9 @@
//Single NAL or last fragment of FU-A
//==============================================
- rh->rh_flags |= htons(RTP_M); // set M bit
+ if ( i == numNAL - 1 )
+ rh->rh_flags |= htons(RTP_M); // set M bit - ONLY if last NAL of frame
+
pb->len = nalSize + RTP_HDR_LEN + FU_HDR_LEN;
#ifdef H264DEBUG
Modified: vic/branches/mpeg4/codec/ffmpeg_codec.cpp
==============================================================================
--- vic/branches/mpeg4/codec/ffmpeg_codec.cpp (original)
+++ vic/branches/mpeg4/codec/ffmpeg_codec.cpp Sun Nov 6 12:29:47 2011
@@ -83,37 +83,36 @@
// put sample parameters */
c->bit_rate = bit_rate;
//c->bit_rate_tolerance = 2000*1000;
- // resolution must be a multiple of two
+ // resolution must be a multiple of two
c->width = width;
c->height = height;
// frames per second */
// OLD FFMPEG ver
- //c->frame_rate = frame_rate * FRAME_RATE_BASE;
+ //c->frame_rate = frame_rate * FRAME_RATE_BASE;
// New FFMPEG ver
c->time_base.den = frame_rate;
c->time_base.num = 1;
- // emit one intra frame every ten frames
+ // emit one intra frame every ten frames
c->gop_size = iframe_gap;
//c->flags |= CODEC_FLAG_EMU_EDGE;
//c->flags |= CODEC_FLAG_LOW_DELAY;
//c->flags |= CODEC_FLAG_PART;
- //c->flags |= CODEC_FLAG_ALT_SCAN;
+ //c->flags |= CODEC_FLAG_ALT_SCAN;
//c->flags |= CODEC_FLAG_PSNR;
//c->flags |= CODEC_FLAG_AC_PRED;
// in loop filter for low bitrate compression
c->flags |= CODEC_FLAG_LOOP_FILTER;
-
if (enable_hq_encoding) {
c->flags |= CODEC_FLAG_QPEL;
//c->flags |= CODEC_FLAG_GMC;
c->flags |= CODEC_FLAG_AC_PRED;
c->flags |= CODEC_FLAG_4MV;
- //c->flags |= CODEC_FLAG_QP_RD;
- //c->mb_decision = FF_MB_DECISION_RD;
+ //c->flags |= CODEC_FLAG_QP_RD;
+ //c->mb_decision = FF_MB_DECISION_RD;
}
c->me_method = ME_EPZS;
@@ -153,13 +152,14 @@
picture = avcodec_alloc_frame();
c = avcodec_alloc_context();
c->flags |= CODEC_FLAG_EMU_EDGE | CODEC_FLAG_PART;
- // c->flags |= CODEC_FLAG_ALT_SCAN;
+ // c->flags |= CODEC_FLAG_ALT_SCAN;
codec = avcodec_find_decoder(codecid);
if (!codec) {
//fprintf(stderr, "codec not found\n");
exit(1);
}
+
/* open it */
if (avcodec_open(c, codec) < 0) {
//fprintf(stderr, "could not open codec\n");
@@ -240,13 +240,13 @@
if (!got_picture || len < 0) {
return -1;
}
-
+
if (state) {
//H264Context *h = c->priv_data;
//printf("h->sps.ref_frame_count: %d",h->sps.ref_frame_count);
}
if (c->width != width || c->height != height) {
- debug_msg("ffmpegcodec: resize from %dx%d (framesize:%d) to %dx%d, (size: %d) got_picture: %d, len: %d\n", width, height,
+ debug_msg("ffmpegcodec: resize from %dx%d (framesize:%d) to %dx%d, (size: %d) got_picture: %d, len: %d\n", width, height,
frame_size, c->width, c->height, size, got_picture, len);
resize(c->width, c->height);
}
@@ -254,7 +254,7 @@
if(avpicture_deinterlace((AVPicture *)picture, (AVPicture *)picture,
c->pix_fmt, c->width, c->height) < 0) {
printf("deinterlace error\n");
- }
+ }
*/
pict_type = picture->pict_type;
memcpy(vf, picture->data[0], frame_size);
@@ -300,6 +300,6 @@
quality = q;
if (state) {
// MpegEncContext *s = (MpegEncContext*)c->priv_data;
-// s->qmax = c->qmax = c->mb_qmax = q;
+// s->qmax = c->qmax = c->mb_qmax = q;
}
}
Modified: vic/branches/mpeg4/codec/x264encoder.cpp
==============================================================================
--- vic/branches/mpeg4/codec/x264encoder.cpp (original)
+++ vic/branches/mpeg4/codec/x264encoder.cpp Sun Nov 6 12:29:47 2011
@@ -47,73 +47,46 @@
x264 *enc = (x264 *) encoder;
x264_param_t *param = &(enc->param);
x264_param_default(param);
+ // the speed preset here should probably be an option
+ x264_param_default_preset(param, "ultrafast", "zerolatency");
+ // necessary stuff
// * seting rate control
param->rc.i_bitrate = bps;
param->rc.i_rc_method = X264_RC_ABR;
-
- //param->analyse.inter = X264_ANALYSE_PSUB16x16;
- //DISALBE PARTITION MODE
- param->analyse.inter = 0;
- param->analyse.intra = 0; // try this for intra too
- //param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_NONE;
-
- //DISABLE CABAC for more frame rate
- param->b_cabac = 0;
-
- //DONOT ENABLE PSNR ANALYSE
- param->analyse.b_psnr = 0;
- param->analyse.b_ssim = 0;
-
+ param->rc.b_mb_tree = 0;
+
+ param->i_width = w;
+ param->i_height = h;
+
param->i_keyint_max = 50;
param->i_keyint_min = 20;
- param->i_bframe = 0;
-
- // deblocking filter
- // i_deblocking_filter_alphac0, [-6, 6] -6 light filter, 6 strong
- param->b_deblocking_filter = 1;
- param->i_deblocking_filter_alphac0 = 3;
-
+
param->i_fps_num = fps * 1000;
param->i_fps_den = 1000;
- // set frame reference to 1 to reduce encoding latency
- param->i_frame_reference = 1;
- param->i_scenecut_threshold = 0;
-
- // motion estimation method, using umh if higher quality is essential.
- //param->analyse.i_me_method = X264_ME_HEX;
- param->analyse.i_me_method = X264_ME_DIA; //supposedly DIA is faster
-
- //other optimization stuff
- //these seem to add a couple fps in non-threaded mode
- param->analyse.b_transform_8x8 = 0;
- param->analyse.i_subpel_refine = 0;
- param->rc.i_aq_mode = 0;
- param->analyse.b_mixed_references = 0;
- param->analyse.i_trellis = 0;
+ // if annexb is 1, x264 uses startcodes (0 -> plain size)
+ // starting Feb 2010, x264 uses short startcodes in some cases which throws
+ // off the packetizer since it assumes the NAL payload is at a constant byte
+ // offset from the header
+ param->b_annexb = 0;
+
+ // single-frame vbv, helps with latency
+ param->rc.i_vbv_max_bitrate = bps;
+ param->rc.i_vbv_buffer_size = bps / fps;
+ printf( "vbv buffer size set to %i\n", bps / fps );
+
+ // intra refresh - maybe this should be an option?
+ // should help with packet loss resiliency at low bitrates
+ param->b_intra_refresh = 1;
+
+ // may want to try slice_max_size=packet size (mtu=1450? need to check rtp
+ // header length), but might be higher than the normal max amount of slices
+ // supported by decoder (most builds of FFmpeg) (16) depending on bitrate
- param->i_width = w;
- param->i_height = h;
-
- // attempt to make threads
- param->i_threads = 0;
- param->b_deterministic = 1;
- // sliced threads might be nice for threading on the decoding side but just
- // seems to be broken
- //param->b_sliced_threads = 1;
-
- // make it completely 1-pass only
- param->rc.b_stat_read = 0;
- param->rc.b_stat_write = 0;
-
- // removing lookahead might reduce latency?
- #if X264_BUILD > 69
- param->rc.i_lookahead = 0;
- #endif
- #if X264_BUILD > 74
- param->i_sync_lookahead = 0;
- #endif
+ // just to be safe, make sure there are no b-frames (just in case it may be
+ // set by a slower speed preset)
+ param->i_bframe = 0;
x264_picture_alloc(&(enc->pic), X264_CSP_I420, param->i_width,
param->i_height);
@@ -137,7 +110,7 @@
int frame_size = param->i_width * param->i_height;
- //refresh
+ //refresh
enc->i_nal = 0;
enc->pic.img.plane[0] = buf;
enc->pic.img.plane[1] = buf + frame_size;
@@ -185,8 +158,9 @@
f->write( (char*)enc->nal[idx].p_payload, packetSize );
#endif
- //printf("i_nal=%d, idx=%d, size=%d\n", enc->i_nal, idx, packetSize);
-
+ //debug_msg("i_nal=%d, idx=%d, size=%d\n", enc->i_nal, idx, packetSize);
+ //debug_msg("nal type is %i\n", enc->nal[idx].i_type);
+
return isFrameEncoded;
}
Modified: vic/branches/mpeg4/main.cpp
==============================================================================
--- vic/branches/mpeg4/main.cpp (original)
+++ vic/branches/mpeg4/main.cpp Sun Nov 6 12:29:47 2011
@@ -543,7 +543,7 @@
usage(NULL);
}
#ifdef USE_ZVFS
- Tcl_FindExecutable(argv[0]);
+ Tcl_FindExecutable((char*)argv[0]);
#endif
Tcl::init("vic");
Tcl& tcl = Tcl::instance();
Modified: vic/branches/mpeg4/video/deinterlace.cpp
==============================================================================
--- vic/branches/mpeg4/video/deinterlace.cpp (original)
+++ vic/branches/mpeg4/video/deinterlace.cpp Sun Nov 6 12:29:47 2011
@@ -30,6 +30,9 @@
context = NULL;
}
+ width_ = width;
+ height_ = height;
+
int flags = 0;
flags |= (cpu_flags & FF_CPU_MMX ? PP_CPU_CAPS_MMX : 0);
flags |= (cpu_flags & FF_CPU_MMXEXT ? PP_CPU_CAPS_MMX2 : 0);
More information about the Sumover-dev
mailing list