changeset 162:de80712db90b libavcodec

- Preliminary RTP friendly mode for H.263. - GOB headers for H.263 coding on RTP mode. - Improved GOB header detection for H.263 decoder.
author pulento
date Mon, 19 Nov 2001 02:13:14 +0000
parents 7ce36cf13055
children 32e7f17a04a7
files avcodec.h h263.c h263dec.c mpegvideo.c mpegvideo.h
diffstat 5 files changed, 130 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/avcodec.h	Sat Nov 17 21:14:54 2001 +0000
+++ b/avcodec.h	Mon Nov 19 02:13:14 2001 +0000
@@ -103,6 +103,19 @@
     struct AVCodec *codec;
     void *priv_data;
 
+    /* The following data is for RTP friendly coding */
+    /* By now only H.263/H.263+ coder honours this   */
+    int rtp_mode;   /* 1 for activate RTP friendly-mode           */
+                    /* highers numbers represent more error-prone */
+                    /* enviroments, by now just "1" exist         */
+    
+    int rtp_payload_size;   /* The size of the RTP payload, the coder will  */
+                            /* do it's best to deliver a chunk with size    */
+                            /* below rtp_payload_size, the chunk will start */
+                            /* with a start code on some codecs like H.263  */
+                            /* This doesn't take account of any particular  */
+                            /* headers inside the transmited RTP payload    */
+                 
     /* the following fields are ignored */
     void *opaque;   /* can be used to carry app specific stuff */
     char codec_name[32];
@@ -239,8 +252,8 @@
 
 #ifdef FF_POSTPROCESS
 #ifndef MBC
-#define MBC 120
-#define MBR 72
+#define MBC 48
+#define MBR 36
 #endif
 extern int quant_store[MBR+1][MBC+1]; // [Review]
 #endif
--- a/h263.c	Sat Nov 17 21:14:54 2001 +0000
+++ b/h263.c	Mon Nov 19 02:13:14 2001 +0000
@@ -140,12 +140,45 @@
     put_bits(&s->pb, 1, 0);	/* no PEI */
 }
 
+int h263_encode_gob_header(MpegEncContext * s, int mb_line)
+{
+    int pdif=0;
+    
+    /* Check to see if we need to put a new GBSC */
+    /* for RTP packetization                    */
+    if (s->rtp_mode) {
+        pdif = s->pb.buf_ptr - s->ptr_lastgob;
+        if (pdif >= s->rtp_payload_size) {
+            /* Bad luck, packet must be cut before */
+            align_put_bits(&s->pb);
+            s->ptr_lastgob = s->pb.buf_ptr;
+            put_bits(&s->pb, 17, 1); /* GBSC */
+            s->gob_number = mb_line;
+            put_bits(&s->pb, 5, s->gob_number); /* GN */
+            put_bits(&s->pb, 2, 1); /* GFID */
+            put_bits(&s->pb, 5, s->qscale); /* GQUANT */
+            return pdif;
+       } else if (pdif + s->mb_line_avgsize >= s->rtp_payload_size) {
+           /* Cut the packet before we can't */
+           align_put_bits(&s->pb);
+           s->ptr_lastgob = s->pb.buf_ptr;
+           put_bits(&s->pb, 17, 1); /* GBSC */
+           s->gob_number = mb_line;
+           put_bits(&s->pb, 5, s->gob_number); /* GN */
+           put_bits(&s->pb, 2, 1); /* GFID */
+           put_bits(&s->pb, 5, s->qscale); /* GQUANT */
+           return pdif;
+       }
+   }
+   return 0;
+}
+    
 void h263_encode_mb(MpegEncContext * s,
 		    DCTELEM block[6][64],
 		    int motion_x, int motion_y)
 {
     int cbpc, cbpy, i, cbp, pred_x, pred_y;
-
+   
     //    printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
    if (!s->mb_intra) {
 	   /* compute cbp */
@@ -772,42 +805,38 @@
     }
 }
 
+int h263_decode_gob_header(MpegEncContext *s)
+{
+    unsigned int val, gfid;
+    
+    /* Check for GOB Start Code */
+    val = show_bits(&s->gb, 16);
+    if (val == 0) {
+        /* We have a GBSC probably with GSTUFF */
+        skip_bits(&s->gb, 16); /* Drop the zeros */
+        while (get_bits1(&s->gb) == 0); /* Seek the '1' bit */
+#ifdef DEBUG
+        fprintf(stderr,"\nGOB Start Code at MB %d\n", (s->mb_y * s->mb_width) + s->mb_x);
+#endif
+        s->gob_number = get_bits(&s->gb, 5); /* GN */
+        gfid = get_bits(&s->gb, 2); /* GFID */
+        s->qscale = get_bits(&s->gb, 5); /* GQUANT */
+#ifdef DEBUG
+        fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale);
+#endif
+        return 1;
+    }
+    return 0;
+            
+}
+
 int h263_decode_mb(MpegEncContext *s,
                    DCTELEM block[6][64])
 {
     int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant;
-    unsigned int val;
     INT16 *mot_val;
     static INT8 quant_tab[4] = { -1, -2, 1, 2 };
-    unsigned int gfid;        
     
-    /* Check for GOB Start Code */
-    if (s->mb_x == 0) {
-        val = show_bits(&s->gb, 16);
-        if (val == 0) {
-            /* We have a GBSC probably with GSTUFF */
-            skip_bits(&s->gb, 16); /* Drop the zeros */
-            while (get_bits1(&s->gb) == 0); /* Seek the '1' bit */
-#ifdef DEBUG
-            fprintf(stderr,"\nGOB Start Code at MB %d\n", 
-                (s->mb_y * s->mb_width) + s->mb_x);
-#endif
-            s->gob_number = get_bits(&s->gb, 5); /* GN */
-            gfid = get_bits(&s->gb, 2); /* GFID */
-            s->qscale = get_bits(&s->gb, 5); /* GQUANT */
-#ifdef DEBUG
-            fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale);
-#endif
-        }
-    }
-    /* FIXME: In the future H.263+ will have intra prediction */
-    /* and we are gonna need another way to detect MPEG4      */
-    if (!s->h263_pred) {
-        if (s->mb_y == s->gob_number)
-            s->first_gob_line = 1;
-        else
-            s->first_gob_line = 0;
-    }        
     if (s->pict_type == P_TYPE) {
         if (get_bits1(&s->gb)) {
             /* skip mb */
--- a/h263dec.c	Sat Nov 17 21:14:54 2001 +0000
+++ b/h263dec.c	Mon Nov 19 02:13:14 2001 +0000
@@ -140,6 +140,12 @@
 
     /* decode each macroblock */
     for(s->mb_y=0; s->mb_y < s->mb_height; s->mb_y++) {
+        /* Check for GOB headers on H.263 */
+        /* FIXME: In the future H.263+ will have intra prediction */
+        /* and we are gonna need another way to detect MPEG4      */
+        if (s->mb_y && !s->h263_pred) {
+            s->first_gob_line = h263_decode_gob_header(s);
+        }
         for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) {
 #ifdef DEBUG
             printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
--- a/mpegvideo.c	Sat Nov 17 21:14:54 2001 +0000
+++ b/mpegvideo.c	Mon Nov 19 02:13:14 2001 +0000
@@ -249,6 +249,9 @@
     s->width = avctx->width;
     s->height = avctx->height;
     s->gop_size = avctx->gop_size;
+    s->rtp_mode = avctx->rtp_mode;
+    s->rtp_payload_size = avctx->rtp_payload_size;
+    
     if (s->gop_size <= 1) {
         s->intra_only = 1;
         s->gop_size = 12;
@@ -276,6 +279,8 @@
         break;
     case CODEC_ID_H263P:
         s->out_format = FMT_H263;
+        s->rtp_mode = 1;
+        s->rtp_payload_size = 1200; 
         s->h263_plus = 1;
         s->unrestricted_mv = 1;
         
@@ -819,7 +824,7 @@
 
 static void encode_picture(MpegEncContext *s, int picture_number)
 {
-    int mb_x, mb_y, wrap;
+    int mb_x, mb_y, wrap, last_gob;
     UINT8 *ptr;
     int i, motion_x, motion_y;
 
@@ -869,7 +874,29 @@
     s->mv_type = MV_TYPE_16X16;
     s->mv_dir = MV_DIR_FORWARD;
 
+    /* Get the GOB height based on picture height */
+    if (s->out_format == FMT_H263 && s->h263_plus) {
+        if (s->height <= 400)
+            s->gob_index = 1;
+        else if (s->height <= 800)
+            s->gob_index = 2;
+        else
+            s->gob_index = 4;
+    }
+        
     for(mb_y=0; mb_y < s->mb_height; mb_y++) {
+        /* Put GOB header based on RTP MTU */
+        if (!mb_y) {
+            s->ptr_lastgob = s->pb.buf_ptr;
+            s->ptr_last_mb_line = s->pb.buf_ptr;
+        } else if (s->out_format == FMT_H263 && s->h263_plus) {
+            last_gob = h263_encode_gob_header(s, mb_y);
+            if (last_gob) {
+                //fprintf(stderr,"\nLast GOB size: %d", last_gob);
+                s->first_gob_line = 1;
+            } else
+                s->first_gob_line = 0;
+        }
         for(mb_x=0; mb_x < s->mb_width; mb_x++) {
 
             s->mb_x = mb_x;
@@ -981,7 +1008,17 @@
 
             MPV_decode_mb(s, s->block);
         }
+        /* Obtain average MB line size for RTP */
+        if (!mb_y)
+            s->mb_line_avgsize = s->pb.buf_ptr - s->ptr_last_mb_line;
+        else    
+            s->mb_line_avgsize = (s->mb_line_avgsize + s->pb.buf_ptr - s->ptr_last_mb_line) >> 1;
+        //fprintf(stderr, "\nMB line: %d\tSize: %u\tAvg. Size: %u", s->mb_y, 
+        //                    (s->pb.buf_ptr - s->ptr_last_mb_line), s->mb_line_avgsize);
+        s->ptr_last_mb_line = s->pb.buf_ptr;
     }
+    //if (s->gob_number)
+    //    fprintf(stderr,"\nNumber of GOB: %d", s->gob_number);
 }
 
 static int dct_quantize(MpegEncContext *s, 
--- a/mpegvideo.h	Sat Nov 17 21:14:54 2001 +0000
+++ b/mpegvideo.h	Mon Nov 19 02:13:14 2001 +0000
@@ -131,6 +131,7 @@
     
     /* H.263 specific */
     int gob_number;
+    int gob_index;
     int first_gob_line;
     
     /* H.263+ specific */
@@ -185,7 +186,14 @@
     int interlaced_dct;
     int last_qscale;
     int first_slice;
-
+    
+    /* RTP specific */
+    int rtp_mode;
+    int rtp_payload_size;
+    UINT8 *ptr_lastgob;
+    UINT8 *ptr_last_mb_line;
+    UINT32 mb_line_avgsize;
+    
     DCTELEM block[6][64] __align8;
     void (*dct_unquantize)(struct MpegEncContext *s, 
                            DCTELEM *block, int n, int qscale);
@@ -236,7 +244,7 @@
 void init_rl(RLTable *rl);
 void init_vlc_rl(RLTable *rl);
 
-static inline int get_rl_index(const RLTable *rl, int last, int run, int level)
+extern inline int get_rl_index(const RLTable *rl, int last, int run, int level)
 {
     int index;
     index = rl->index_run[last][run];
@@ -251,6 +259,7 @@
                     DCTELEM block[6][64],
                     int motion_x, int motion_y);
 void h263_encode_picture_header(MpegEncContext *s, int picture_number);
+int h263_encode_gob_header(MpegEncContext * s, int mb_line);
 void h263_dc_scale(MpegEncContext *s);
 INT16 *h263_pred_motion(MpegEncContext * s, int block, 
                         int *px, int *py);
@@ -261,6 +270,7 @@
 
 void h263_decode_init_vlc(MpegEncContext *s);
 int h263_decode_picture_header(MpegEncContext *s);
+int h263_decode_gob_header(MpegEncContext *s);
 int mpeg4_decode_picture_header(MpegEncContext * s);
 int intel_h263_decode_picture_header(MpegEncContext *s);
 int h263_decode_mb(MpegEncContext *s,