- Preliminary RTP friendly mode for H.263.
authorJuanjo <pulento@users.sourceforge.net>
Mon, 19 Nov 2001 02:13:14 +0000 (02:13 +0000)
committerJuanjo <pulento@users.sourceforge.net>
Mon, 19 Nov 2001 02:13:14 +0000 (02:13 +0000)
- GOB headers for H.263 coding on RTP mode.
- Improved GOB header detection for H.263 decoder.

Originally committed as revision 222 to svn://svn.ffmpeg.org/ffmpeg/trunk

Changelog
libavcodec/avcodec.h
libavcodec/h263.c
libavcodec/h263dec.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h

index 103de166f61ed0c1617fadd2634bd4a6199d9e4d..95422897aa61d5948b14b7565a68632d5ea7944f 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -5,6 +5,14 @@ version 0.4.6:
 - recoded dct and motion vector search with gcc (no longer depends on
   nasm).
 - fix quantization bug in AC3 encoder.
+- added GOB header parsing on H.263/H.263+ decoder. (Juanjo)
+- bug fix on MCBPC tables of H.263. (Juanjo)
+- added Advanced Prediction Mode on H.263/H.263+ decoder. (Juanjo)
+- now we can decode H.263 streams found on QuickTime files. (Juanjo)
+- now we can decode H.263 streams found on VIVO v1 files.(Juanjo)
+- preliminary RTP "friendly" mode for H.263/H.263+ coding. (Juanjo)
+- added GOB header for H.263/H.263+ coding on RTP mode. (Juanjo)
+- now H.263 picture size is returned on the first decoded frame. (Juanjo)
 
 version 0.4.5:
 
index b85db2d558ca891ccc5bfeba7d6476312b4e210a..10d19a9c319d874ba85c8f8c4011b0de509f9e9b 100644 (file)
@@ -103,6 +103,19 @@ typedef struct AVCodecContext {
     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 @@ void avcodec_register_all(void);
 
 #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
index 4aaf5d6ad494a699e0813ed329d5756ad10c76a4..3461b4f67689d7354e07ad3db4082ec03ec69668 100644 (file)
@@ -140,12 +140,45 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
     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 @@ void h263_decode_init_vlc(MpegEncContext *s)
     }
 }
 
-int h263_decode_mb(MpegEncContext *s,
-                   DCTELEM block[6][64])
+int h263_decode_gob_header(MpegEncContext *s)
 {
-    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;        
+    unsigned int val, 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 */
+    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);
+        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 */
+        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);
+        fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale);
 #endif
-        }
+        return 1;
     }
-    /* 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;
-    }        
+    return 0;
+            
+}
+
+int h263_decode_mb(MpegEncContext *s,
+                   DCTELEM block[6][64])
+{
+    int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant;
+    INT16 *mot_val;
+    static INT8 quant_tab[4] = { -1, -2, 1, 2 };
+    
     if (s->pict_type == P_TYPE) {
         if (get_bits1(&s->gb)) {
             /* skip mb */
index d56bc8252bebd9668dc48bd070441d110e3b3d8a..be76e3030f95c8fe97e38f371ae3228464ab6080 100644 (file)
@@ -140,6 +140,12 @@ static int h263_decode_frame(AVCodecContext *avctx,
 
     /* 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);
index 148d7e142cb1f853d2f2af60552a710c41bdf1ba..11ac7dcafc28ce9a967cef372aa7f6e05955dd42 100644 (file)
@@ -249,6 +249,9 @@ int MPV_encode_init(AVCodecContext *avctx)
     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 @@ int MPV_encode_init(AVCodecContext *avctx)
         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 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
 
 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 @@ static void encode_picture(MpegEncContext *s, int picture_number)
     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 @@ static void encode_picture(MpegEncContext *s, int picture_number)
 
             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, 
index 7b473aaa5a1b75a5a5359b44e2c8faa76386e2d3..e653edb9b4ce0a5e2f6706212ec713dabc8ff6f6 100644 (file)
@@ -131,6 +131,7 @@ typedef struct MpegEncContext {
     
     /* H.263 specific */
     int gob_number;
+    int gob_index;
     int first_gob_line;
     
     /* H.263+ specific */
@@ -185,7 +186,14 @@ typedef struct MpegEncContext {
     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 @@ typedef struct RLTable {
 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 @@ void h263_encode_mb(MpegEncContext *s,
                     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_encode_init_vlc(MpegEncContext *s);
 
 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,