changeset 1160:9a5c29575902 libavcodec

mpeg1 slice encoding support
author michaelni
date Sun, 30 Mar 2003 19:26:01 +0000
parents 13ea348d4cf2
children 556b5d0b5228
files mpeg12.c mpegvideo.c mpegvideo.h
diffstat 3 files changed, 60 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/mpeg12.c	Sun Mar 30 16:22:08 2003 +0000
+++ b/mpeg12.c	Sun Mar 30 19:26:01 2003 +0000
@@ -275,12 +275,18 @@
         }
 }
 
+static inline void encode_mb_skip_run(MpegEncContext *s, int run){
+    while (run >= 33) {
+        put_bits(&s->pb, 11, 0x008);
+        run -= 33;
+    }
+    put_bits(&s->pb, mbAddrIncrTable[run][1], 
+             mbAddrIncrTable[run][0]);
+}
 
 /* insert a fake P picture */
 static void mpeg1_skip_picture(MpegEncContext *s, int pict_num)
 {
-    unsigned int mb_incr;
-
     /* mpeg1 picture header */
     put_header(s, PICTURE_START_CODE);
     /* temporal reference */
@@ -299,9 +305,7 @@
     put_bits(&s->pb, 5, 1); /* quantizer scale */
     put_bits(&s->pb, 1, 0); /* slice extra information */
     
-    mb_incr = 1;
-    put_bits(&s->pb, mbAddrIncrTable[mb_incr - 1][1], 
-             mbAddrIncrTable[mb_incr - 1][0]);
+    encode_mb_skip_run(s, 0);
     
     /* empty macroblock */
     put_bits(&s->pb, 3, 1); /* motion only */
@@ -311,13 +315,7 @@
     put_bits(&s->pb, 1, 1); 
 
     /* output a number of empty slice */
-    mb_incr = s->mb_width * s->mb_height - 1;
-    while (mb_incr > 33) {
-        put_bits(&s->pb, 11, 0x008);
-        mb_incr -= 33;
-    }
-    put_bits(&s->pb, mbAddrIncrTable[mb_incr - 1][1], 
-             mbAddrIncrTable[mb_incr - 1][0]);
+    encode_mb_skip_run(s, s->mb_width * s->mb_height - 2);
     
     /* empty macroblock */
     put_bits(&s->pb, 3, 1); /* motion only */
@@ -334,6 +332,20 @@
 }
 
 #ifdef CONFIG_ENCODERS
+
+void ff_mpeg1_encode_slice_header(MpegEncContext *s){
+    put_header(s, SLICE_MIN_START_CODE + s->mb_y);
+    put_bits(&s->pb, 5, s->qscale); /* quantizer scale */
+    put_bits(&s->pb, 1, 0); /* slice extra information */
+}
+
+void ff_mpeg1_clean_buffers(MpegEncContext *s){
+    s->last_dc[0] = 1 << (7 + s->intra_dc_precision);
+    s->last_dc[1] = s->last_dc[0];
+    s->last_dc[2] = s->last_dc[0];
+    memset(s->last_mv, 0, sizeof(s->last_mv));
+}
+
 void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
 {
     mpeg1_encode_sequence_header(s);
@@ -364,20 +376,18 @@
 
     put_bits(&s->pb, 1, 0); /* extra bit picture */
     
-    /* only one slice */
-    put_header(s, SLICE_MIN_START_CODE);
-    put_bits(&s->pb, 5, s->qscale); /* quantizer scale */
-    put_bits(&s->pb, 1, 0); /* slice extra information */
+    s->mb_y=0;
+    ff_mpeg1_encode_slice_header(s);
 }
 
 void mpeg1_encode_mb(MpegEncContext *s,
                      DCTELEM block[6][64],
                      int motion_x, int motion_y)
 {
-    int mb_incr, i, cbp, mb_x, mb_y;
-
-    mb_x = s->mb_x;
-    mb_y = s->mb_y;
+    int i, cbp;
+    const int mb_x = s->mb_x;
+    const int mb_y = s->mb_y;
+    const int first_mb= mb_x == s->resync_mb_x && mb_y == s->resync_mb_y;
 
     /* compute cbp */
     cbp = 0;
@@ -386,26 +396,22 @@
             cbp |= 1 << (5 - i);
     }
 
-    // RAL: Skipped macroblocks for B frames...
-    if (cbp == 0 && (!((mb_x | mb_y) == 0 || (mb_x == s->mb_width - 1 && mb_y == s->mb_height - 1))) && 
+    if (cbp == 0 && !first_mb && (mb_x != s->mb_width - 1 || mb_y != s->mb_height - 1) && 
         ((s->pict_type == P_TYPE && (motion_x | motion_y) == 0) ||
         (s->pict_type == B_TYPE && s->mv_dir == s->last_mv_dir && (((s->mv_dir & MV_DIR_FORWARD) ? ((s->mv[0][0][0] - s->last_mv[0][0][0])|(s->mv[0][0][1] - s->last_mv[0][0][1])) : 0) |
         ((s->mv_dir & MV_DIR_BACKWARD) ? ((s->mv[1][0][0] - s->last_mv[1][0][0])|(s->mv[1][0][1] - s->last_mv[1][0][1])) : 0)) == 0))) {
-        s->mb_incr++;
+        s->mb_skip_run++;
         s->qscale -= s->dquant;
         s->skip_count++;
         s->misc_bits++;
         s->last_bits++;
     } else {
-        /* output mb incr */
-        mb_incr = s->mb_incr;
-
-        while (mb_incr > 33) {
-            put_bits(&s->pb, 11, 0x008);
-            mb_incr -= 33;
+        if(first_mb){
+            assert(s->mb_skip_run == 0);
+            encode_mb_skip_run(s, s->mb_x);
+        }else{
+            encode_mb_skip_run(s, s->mb_skip_run);
         }
-        put_bits(&s->pb, mbAddrIncrTable[mb_incr - 1][1], 
-                 mbAddrIncrTable[mb_incr - 1][0]);
         
         if (s->pict_type == I_TYPE) {
             if(s->dquant && cbp){
@@ -553,7 +559,7 @@
                 mpeg1_encode_block(s, block[i], i);
             }
         }
-        s->mb_incr = 1;
+        s->mb_skip_run = 0;
         if(s->mb_intra)
             s->i_tex_bits+= get_bits_diff(s);
         else
@@ -888,7 +894,7 @@
 
     assert(s->mb_skiped==0);
 
-    if (--s->mb_incr != 0) {
+    if (s->mb_skip_run-- != 0) {
         /* skip mb */
         s->mb_intra = 0;
         for(i=0;i<6;i++)
@@ -1795,10 +1801,8 @@
         fprintf(stderr, "slice below image (%d >= %d)\n", start_code, s->mb_height);
         return DECODE_SLICE_ERROR;
     }
-    s->last_dc[0] = 1 << (7 + s->intra_dc_precision);
-    s->last_dc[1] = s->last_dc[0];
-    s->last_dc[2] = s->last_dc[0];
-    memset(s->last_mv, 0, sizeof(s->last_mv));
+    
+    ff_mpeg1_clean_buffers(s);
         
     /* start frame decoding */
     if (s->first_slice) {
@@ -1863,8 +1867,9 @@
             break;
         }
     }
+    
     s->mb_y = start_code;
-    s->mb_incr= 1;
+    s->mb_skip_run= 0;
 
     for(;;) {
 	s->dsp.clear_blocks(s->block[0]);
@@ -1892,20 +1897,20 @@
         PRINT_QP("%2d", s->qscale);
 
         /* skip mb handling */
-        if (s->mb_incr == 0) {
+        if (s->mb_skip_run == -1) {
             /* read again increment */
-            s->mb_incr = 1;
+            s->mb_skip_run = 0;
             for(;;) {
                 int code = get_vlc2(&s->gb, mbincr_vlc.table, MBINCR_VLC_BITS, 2);
                 if (code < 0)
                     goto eos; /* error = end of slice */
                 if (code >= 33) {
                     if (code == 33) {
-                        s->mb_incr += 33;
+                        s->mb_skip_run += 33;
                     }
                     /* otherwise, stuffing, nothing to do */
                 } else {
-                    s->mb_incr += code;
+                    s->mb_skip_run += code;
                     break;
                 }
             }
--- a/mpegvideo.c	Sun Mar 30 16:22:08 2003 +0000
+++ b/mpegvideo.c	Sun Mar 30 19:26:01 2003 +0000
@@ -2684,7 +2684,7 @@
     memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster then a loop?
 
     /* mpeg1 */
-    d->mb_incr= s->mb_incr;
+    d->mb_skip_run= s->mb_skip_run;
     for(i=0; i<3; i++)
         d->last_dc[i]= s->last_dc[i];
     
@@ -2710,7 +2710,7 @@
     memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster then a loop?
     
     /* mpeg1 */
-    d->mb_incr= s->mb_incr;
+    d->mb_skip_run= s->mb_skip_run;
     for(i=0; i<3; i++)
         d->last_dc[i]= s->last_dc[i];
     
@@ -3023,7 +3023,7 @@
         
         s->current_picture_ptr->error[i] = 0;
     }
-    s->mb_incr = 1;
+    s->mb_skip_run = 0;
     s->last_mv[0][0][0] = 0;
     s->last_mv[0][0][1] = 0;
     s->last_mv[1][0][0] = 0;
@@ -3094,6 +3094,13 @@
                         ff_mpeg4_clean_buffers(s);
                         is_gob_start=1;
                     }
+                }else if(s->codec_id==CODEC_ID_MPEG1VIDEO){
+                    if(   current_packet_size >= s->rtp_payload_size 
+                       && s->mb_y + s->mb_x>0 && s->mb_skip_run==0){
+                        ff_mpeg1_encode_slice_header(s);
+                        ff_mpeg1_clean_buffers(s);
+                        is_gob_start=1;
+                    }
                 }else{
                     if(current_packet_size >= s->rtp_payload_size
                        && s->mb_x==0 && s->mb_y>0 && s->mb_y%s->gob_index==0){
--- a/mpegvideo.h	Sun Mar 30 16:22:08 2003 +0000
+++ b/mpegvideo.h	Sun Mar 30 19:26:01 2003 +0000
@@ -338,7 +338,7 @@
                         
     /* macroblock layer */
     int mb_x, mb_y;
-    int mb_incr;
+    int mb_skip_run;
     int mb_intra;
     uint8_t *mb_type;       ///< Table for MB type 
 #define MB_TYPE_INTRA    0x01
@@ -685,6 +685,8 @@
                      DCTELEM block[6][64],
                      int motion_x, int motion_y);
 void ff_mpeg1_encode_init(MpegEncContext *s);
+void ff_mpeg1_encode_slice_header(MpegEncContext *s);
+void ff_mpeg1_clean_buffers(MpegEncContext *s);
 
 
 /** RLTable. */