[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