Saner RV1/2 initialisation and RV2 header parsing.
authorKostya Shishkov <kostya.shishkov@gmail.com>
Thu, 4 Aug 2011 19:00:12 +0000 (21:00 +0200)
committerRonald S. Bultje <rsbultje@gmail.com>
Tue, 9 Aug 2011 00:23:07 +0000 (17:23 -0700)
Old version was based on lots of guesswork which had different hacks based on
32-bit version field instead of splitting it into major/minor/micro version.
RV2 picture header parser also had a few places where it deviated from binary
decoder.

Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>
libavcodec/rv10.c

index 9a1fda1..3939984 100644 (file)
 
 //#define DEBUG
 
 
 //#define DEBUG
 
+#define RV_GET_MAJOR_VER(x)  ((x) >> 28)
+#define RV_GET_MINOR_VER(x) (((x) >> 20) & 0xFF)
+#define RV_GET_MICRO_VER(x) (((x) >> 12) & 0xFF)
+
 #define DC_VLC_BITS 14 //FIXME find a better solution
 
 static const uint16_t rv_lum_code[256] =
 #define DC_VLC_BITS 14 //FIXME find a better solution
 
 static const uint16_t rv_lum_code[256] =
@@ -292,13 +296,7 @@ static int rv10_decode_picture_header(MpegEncContext *s)
 static int rv20_decode_picture_header(MpegEncContext *s)
 {
     int seq, mb_pos, i;
 static int rv20_decode_picture_header(MpegEncContext *s)
 {
     int seq, mb_pos, i;
-
-    if(s->avctx->sub_id == 0x30202002 || s->avctx->sub_id == 0x30203002){
-        if (get_bits(&s->gb, 3)){
-            av_log(s->avctx, AV_LOG_ERROR, "unknown triplet set\n");
-            return -1;
-        }
-    }
+    int rpr_bits;
 
     i= get_bits(&s->gb, 2);
     switch(i){
 
     i= get_bits(&s->gb, 2);
     switch(i){
@@ -317,7 +315,7 @@ static int rv20_decode_picture_header(MpegEncContext *s)
     }
 
     if (get_bits1(&s->gb)){
     }
 
     if (get_bits1(&s->gb)){
-        av_log(s->avctx, AV_LOG_ERROR, "unknown bit set\n");
+        av_log(s->avctx, AV_LOG_ERROR, "reserved bit set\n");
         return -1;
     }
 
         return -1;
     }
 
@@ -326,23 +324,21 @@ static int rv20_decode_picture_header(MpegEncContext *s)
         av_log(s->avctx, AV_LOG_ERROR, "error, qscale:0\n");
         return -1;
     }
         av_log(s->avctx, AV_LOG_ERROR, "error, qscale:0\n");
         return -1;
     }
-    if(s->avctx->sub_id == 0x30203002){
-        if (get_bits1(&s->gb)){
-            av_log(s->avctx, AV_LOG_ERROR, "unknown bit2 set\n");
-            return -1;
-        }
-    }
 
 
-    if(s->avctx->has_b_frames){
-        int f, new_w, new_h;
-        int v= s->avctx->extradata_size >= 4 ? 7&((uint8_t*)s->avctx->extradata)[1] : 0;
+    if(RV_GET_MINOR_VER(s->avctx->sub_id) >= 2)
+        s->loop_filter = get_bits1(&s->gb);
 
 
-        if (get_bits1(&s->gb)){
-            av_log(s->avctx, AV_LOG_ERROR, "unknown bit3 set\n");
-        }
-        seq= get_bits(&s->gb, 13)<<2;
+    if(RV_GET_MINOR_VER(s->avctx->sub_id) <= 1)
+        seq = get_bits(&s->gb, 8) << 7;
+    else
+        seq = get_bits(&s->gb, 13) << 2;
+
+    rpr_bits = s->avctx->extradata[1] & 7;
+    if(rpr_bits){
+        int f, new_w, new_h;
+        rpr_bits = FFMIN((rpr_bits >> 1) + 1, 3);
 
 
-        f= get_bits(&s->gb, av_log2(v)+1);
+        f = get_bits(&s->gb, rpr_bits);
 
         if(f){
             new_w= 4*((uint8_t*)s->avctx->extradata)[6+2*f];
 
         if(f){
             new_w= 4*((uint8_t*)s->avctx->extradata)[6+2*f];
@@ -364,19 +360,12 @@ static int rv20_decode_picture_header(MpegEncContext *s)
         }
 
         if(s->avctx->debug & FF_DEBUG_PICT_INFO){
         }
 
         if(s->avctx->debug & FF_DEBUG_PICT_INFO){
-            av_log(s->avctx, AV_LOG_DEBUG, "F %d/%d\n", f, v);
+            av_log(s->avctx, AV_LOG_DEBUG, "F %d/%d\n", f, rpr_bits);
         }
         }
-    }else{
-        seq= get_bits(&s->gb, 8)*128;
     }
 
     }
 
-//     if(s->avctx->sub_id <= 0x20201002){ //0x20201002 definitely needs this
-    mb_pos= ff_h263_decode_mba(s);
-/*    }else{
-        mb_pos= get_bits(&s->gb, av_log2(s->mb_num-1)+1);
-        s->mb_x= mb_pos % s->mb_width;
-        s->mb_y= mb_pos / s->mb_width;
-    }*/
+    mb_pos = ff_h263_decode_mba(s);
+
 //av_log(s->avctx, AV_LOG_DEBUG, "%d\n", seq);
     seq |= s->time &~0x7FFF;
     if(seq - s->time >  0x4000) seq -= 0x8000;
 //av_log(s->avctx, AV_LOG_DEBUG, "%d\n", seq);
     seq |= s->time &~0x7FFF;
     if(seq - s->time >  0x4000) seq -= 0x8000;
@@ -403,6 +392,9 @@ static int rv20_decode_picture_header(MpegEncContext *s)
 av_log(s->avctx, AV_LOG_DEBUG, "\n");*/
     s->no_rounding= get_bits1(&s->gb);
 
 av_log(s->avctx, AV_LOG_DEBUG, "\n");*/
     s->no_rounding= get_bits1(&s->gb);
 
+    if(RV_GET_MINOR_VER(s->avctx->sub_id) <= 1 && s->pict_type == AV_PICTURE_TYPE_B)
+        skip_bits(&s->gb, 5); // binary decoder reads 3+2 bits here but they don't seem to be used
+
     s->f_code = 1;
     s->unrestricted_mv = 1;
     s->h263_aic= s->pict_type == AV_PICTURE_TYPE_I;
     s->f_code = 1;
     s->unrestricted_mv = 1;
     s->h263_aic= s->pict_type == AV_PICTURE_TYPE_I;
@@ -427,6 +419,7 @@ static av_cold int rv10_decode_init(AVCodecContext *avctx)
 {
     MpegEncContext *s = avctx->priv_data;
     static int done=0;
 {
     MpegEncContext *s = avctx->priv_data;
     static int done=0;
+    int major_ver, minor_ver, micro_ver;
 
     if (avctx->extradata_size < 8) {
         av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n");
 
     if (avctx->extradata_size < 8) {
         av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n");
@@ -445,32 +438,27 @@ static av_cold int rv10_decode_init(AVCodecContext *avctx)
     s->h263_long_vectors= ((uint8_t*)avctx->extradata)[3] & 1;
     avctx->sub_id= AV_RB32((uint8_t*)avctx->extradata + 4);
 
     s->h263_long_vectors= ((uint8_t*)avctx->extradata)[3] & 1;
     avctx->sub_id= AV_RB32((uint8_t*)avctx->extradata + 4);
 
-    if (avctx->sub_id == 0x10000000) {
-        s->rv10_version= 0;
-        s->low_delay=1;
-    } else if (avctx->sub_id == 0x10001000) {
-        s->rv10_version= 3;
-        s->low_delay=1;
-    } else if (avctx->sub_id == 0x10002000) {
-        s->rv10_version= 3;
-        s->low_delay=1;
-        s->obmc=1;
-    } else if (avctx->sub_id == 0x10003000) {
-        s->rv10_version= 3;
-        s->low_delay=1;
-    } else if (avctx->sub_id == 0x10003001) {
-        s->rv10_version= 3;
-        s->low_delay=1;
-    } else if (    avctx->sub_id == 0x20001000
-               || (avctx->sub_id >= 0x20100000 && avctx->sub_id < 0x201a0000)) {
-        s->low_delay=1;
-    } else if (    avctx->sub_id == 0x30202002
-               ||  avctx->sub_id == 0x30203002
-               || (avctx->sub_id >= 0x20200002 && avctx->sub_id < 0x20300000)) {
-        s->low_delay=0;
-        s->avctx->has_b_frames=1;
-    } else
+    major_ver = RV_GET_MAJOR_VER(avctx->sub_id);
+    minor_ver = RV_GET_MINOR_VER(avctx->sub_id);
+    micro_ver = RV_GET_MICRO_VER(avctx->sub_id);
+
+    s->low_delay = 1;
+    switch (major_ver) {
+    case 1:
+        s->rv10_version = micro_ver ? 3 : 1;
+        s->obmc = micro_ver == 2;
+        break;
+    case 2:
+        if (minor_ver >= 2) {
+            s->low_delay = 0;
+            s->avctx->has_b_frames = 1;
+        }
+        break;
+    default:
         av_log(s->avctx, AV_LOG_ERROR, "unknown header %X\n", avctx->sub_id);
         av_log(s->avctx, AV_LOG_ERROR, "unknown header %X\n", avctx->sub_id);
+        av_log_missing_feature(avctx, "RV1/2 version", 1);
+        return AVERROR_PATCHWELCOME;
+    }
 
     if(avctx->debug & FF_DEBUG_PICT_INFO){
         av_log(avctx, AV_LOG_DEBUG, "ver:%X ver0:%X\n", avctx->sub_id, avctx->extradata_size >= 4 ? ((uint32_t*)avctx->extradata)[0] : -1);
 
     if(avctx->debug & FF_DEBUG_PICT_INFO){
         av_log(avctx, AV_LOG_DEBUG, "ver:%X ver0:%X\n", avctx->sub_id, avctx->extradata_size >= 4 ? ((uint32_t*)avctx->extradata)[0] : -1);