- Fixes on RTP and GOB headers for H.263.
authorJuanjo <pulento@users.sourceforge.net>
Sat, 9 Feb 2002 16:59:56 +0000 (16:59 +0000)
committerJuanjo <pulento@users.sourceforge.net>
Sat, 9 Feb 2002 16:59:56 +0000 (16:59 +0000)
- RTP callback system implemented for H.263/H.263+.
- Bug fix on DC coefficients of H.263.
- H.263 decoder now returns PTS on picture number.

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

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

index 9542289..30d04a1 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -7,6 +7,7 @@ version 0.4.6:
 - 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)
+- bug fix on DC coefficients 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)
index 9b02709..cc374c1 100644 (file)
@@ -115,6 +115,14 @@ typedef struct AVCodecContext {
                             /* 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 RTP callcack: This function is called  */
+    /* every time the encoder as a packet to send */
+    /* Depends on the encoder if the data starts  */
+    /* with a Start Code (it should) H.263 does   */
+    void (*rtp_callback)(void *data, int size, int packet_number); 
+
                  
     /* the following fields are ignored */
     void *opaque;   /* can be used to carry app specific stuff */
index da69441..3710af8 100644 (file)
@@ -62,7 +62,12 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
     int format;
 
     align_put_bits(&s->pb);
-    put_bits(&s->pb, 22, 0x20);
+
+    /* Update the pointer to last GOB */
+    s->ptr_lastgob = s->pb.buf_ptr;
+    s->gob_number = 0;
+
+    put_bits(&s->pb, 22, 0x20); /* PSC */
     put_bits(&s->pb, 8, ((s->picture_number * 30 * FRAME_RATE_BASE) / 
                          s->frame_rate) & 0xff);
 
@@ -151,22 +156,36 @@ int h263_encode_gob_header(MpegEncContext * s, int mb_line)
         if (pdif >= s->rtp_payload_size) {
             /* Bad luck, packet must be cut before */
             align_put_bits(&s->pb);
+            flush_put_bits(&s->pb);
+            /* Call the RTP callback to send the last GOB */
+            if (s->rtp_callback) {
+                pdif = s->pb.buf_ptr - s->ptr_lastgob;
+                s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number);
+            }
             s->ptr_lastgob = s->pb.buf_ptr;
             put_bits(&s->pb, 17, 1); /* GBSC */
-            s->gob_number = mb_line;
+            s->gob_number = mb_line / s->gob_index;
             put_bits(&s->pb, 5, s->gob_number); /* GN */
-            put_bits(&s->pb, 2, 1); /* GFID */
+            put_bits(&s->pb, 2, s->pict_type == I_TYPE); /* GFID */
             put_bits(&s->pb, 5, s->qscale); /* GQUANT */
+            //fprintf(stderr,"\nGOB: %2d size: %d", s->gob_number - 1, pdif);
             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);
+           flush_put_bits(&s->pb);
+           /* Call the RTP callback to send the last GOB */
+           if (s->rtp_callback) {
+               pdif = s->pb.buf_ptr - s->ptr_lastgob;
+               s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number);
+           }
            s->ptr_lastgob = s->pb.buf_ptr;
            put_bits(&s->pb, 17, 1); /* GBSC */
-           s->gob_number = mb_line;
+           s->gob_number = mb_line / s->gob_index;
            put_bits(&s->pb, 5, s->gob_number); /* GN */
-           put_bits(&s->pb, 2, 1); /* GFID */
+           put_bits(&s->pb, 2, s->pict_type == I_TYPE); /* GFID */
            put_bits(&s->pb, 5, s->qscale); /* GQUANT */
+           //fprintf(stderr,"\nGOB: %2d size: %d", s->gob_number - 1, pdif);
            return pdif;
        }
    }
@@ -413,20 +432,25 @@ static void h263_encode_block(MpegEncContext * s, DCTELEM * block, int n)
     RLTable *rl = &rl_inter;
 
     if (s->mb_intra) {
-       /* DC coef */
-       level = block[0];
+        /* DC coef */
+           level = block[0];
         /* 255 cannot be represented, so we clamp */
         if (level > 254) {
             level = 254;
             block[0] = 254;
         }
-       if (level == 128)
-           put_bits(&s->pb, 8, 0xff);
-       else
-           put_bits(&s->pb, 8, level & 0xff);
-       i = 1;
+        /* 0 cannot be represented also */
+        else if (!level) {
+            level = 1;
+            block[0] = 1;
+        }
+           if (level == 128)
+               put_bits(&s->pb, 8, 0xff);
+           else
+               put_bits(&s->pb, 8, level & 0xff);
+           i = 1;
     } else {
-       i = 0;
+           i = 0;
     }
 
     /* AC coefs */
@@ -1241,8 +1265,8 @@ int h263_decode_picture_header(MpegEncContext *s)
     /* picture header */
     if (get_bits(&s->gb, 22) != 0x20)
         return -1;
-    skip_bits(&s->gb, 8); /* picture timestamp */
-
+    s->picture_number = get_bits(&s->gb, 8); /* picture timestamp */
+    
     if (get_bits1(&s->gb) != 1)
         return -1;     /* marker */
     if (get_bits1(&s->gb) != 0)
index aadeb8b..ce2c12d 100644 (file)
@@ -225,6 +225,11 @@ static int h263_decode_frame(AVCodecContext *avctx,
     pict->linesize[2] = s->linesize / 2;
 
     avctx->quality = s->qscale;
+
+    /* Return the Picture timestamp as the frame number */
+    /* we substract 1 because it is added on utils.c    */
+    avctx->frame_number = s->picture_number - 1;
+
     *data_size = sizeof(AVPicture);
     return buf_size;
 }
index 72b8058..4c86c52 100644 (file)
@@ -264,6 +264,8 @@ int MPV_encode_init(AVCodecContext *avctx)
     s->gop_size = avctx->gop_size;
     s->rtp_mode = avctx->rtp_mode;
     s->rtp_payload_size = avctx->rtp_payload_size;
+    if (avctx->rtp_callback)
+        s->rtp_callback = avctx->rtp_callback;
     s->avctx = avctx;
     
     if (s->gop_size <= 1) {
@@ -868,7 +870,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, last_gob;
+    int mb_x, mb_y, wrap, last_gob, pdif = 0;
     UINT8 *ptr;
     int i, motion_x, motion_y;
 
@@ -919,7 +921,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
     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->out_format == FMT_H263 && !s->h263_pred && !s->h263_msmpeg4) {
         if (s->height <= 400)
             s->gob_index = 1;
         else if (s->height <= 800)
@@ -930,16 +932,17 @@ static void encode_picture(MpegEncContext *s, int picture_number)
         
     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;
+        /* TODO: Put all this stuff in a separate generic function */
+        if (s->rtp_mode) {
+            if (!mb_y) {
+                s->ptr_lastgob = s->pb.buf;
+                s->ptr_last_mb_line = s->pb.buf;
+            } else if (s->out_format == FMT_H263 && !s->h263_pred && !s->h263_msmpeg4 && !(mb_y % s->gob_index)) {
+                last_gob = h263_encode_gob_header(s, mb_y);
+                if (last_gob) {
+                    s->first_gob_line = 1;
+                }
+            }
         }
         for(mb_x=0; mb_x < s->mb_width; mb_x++) {
 
@@ -1046,14 +1049,18 @@ 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;
+        /* Obtain average GOB size for RTP */
+        if (s->rtp_mode) {
+            if (!mb_y)
+                s->mb_line_avgsize = s->pb.buf_ptr - s->ptr_last_mb_line;
+            else if (!(mb_y % s->gob_index)) {    
+                s->mb_line_avgsize = (s->mb_line_avgsize + s->pb.buf_ptr - s->ptr_last_mb_line) >> 1;
+                s->ptr_last_mb_line = s->pb.buf_ptr;
+            }
+            //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->first_gob_line = 0;
+        }
     }
     
     if (s->h263_msmpeg4) 
@@ -1061,6 +1068,18 @@ static void encode_picture(MpegEncContext *s, int picture_number)
 
     //if (s->gob_number)
     //    fprintf(stderr,"\nNumber of GOB: %d", s->gob_number);
+    
+    /* Send the last GOB if RTP */    
+    if (s->rtp_mode) {
+        flush_put_bits(&s->pb);
+        pdif = s->pb.buf_ptr - s->ptr_lastgob;
+        /* Call the RTP callback to send the last GOB */
+        if (s->rtp_callback)
+            s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number);
+        s->ptr_lastgob = s->pb.buf_ptr;
+        //fprintf(stderr,"\nGOB: %2d size: %d (last)", s->gob_number, pdif);
+    }
+
 }
 
 static int dct_quantize_c(MpegEncContext *s, 
index 6cf4688..a12f198 100644 (file)
@@ -201,8 +201,10 @@ typedef struct MpegEncContext {
     int first_slice;
     
     /* RTP specific */
+    /* These are explained on avcodec.h */
     int rtp_mode;
     int rtp_payload_size;
+    void (*rtp_callback)(void *data, int size, int packet_number);
     UINT8 *ptr_lastgob;
     UINT8 *ptr_last_mb_line;
     UINT32 mb_line_avgsize;