]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/rv10.c
mpegvideo: claim ownership of referenced pictures
[ffmpeg] / libavcodec / rv10.c
index 4af1fd057408f38c7f7a29e7289b3799ab8198a5..1d78c92c469e84871d1f2d8719e5aeb920617237 100644 (file)
 
 //#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] =
@@ -235,14 +239,14 @@ int rv_decode_dc(MpegEncContext *s, int n)
 /* read RV 1.0 compatible frame header */
 static int rv10_decode_picture_header(MpegEncContext *s)
 {
-    int mb_count, pb_frame, marker, unk, mb_xy;
+    int mb_count, pb_frame, marker, mb_xy;
 
     marker = get_bits1(&s->gb);
 
     if (get_bits1(&s->gb))
-        s->pict_type = FF_P_TYPE;
+        s->pict_type = AV_PICTURE_TYPE_P;
     else
-        s->pict_type = FF_I_TYPE;
+        s->pict_type = AV_PICTURE_TYPE_I;
     if(!marker) av_log(s->avctx, AV_LOG_ERROR, "marker missing\n");
     pb_frame = get_bits1(&s->gb);
 
@@ -259,7 +263,7 @@ static int rv10_decode_picture_header(MpegEncContext *s)
         return -1;
     }
 
-    if (s->pict_type == FF_I_TYPE) {
+    if (s->pict_type == AV_PICTURE_TYPE_I) {
         if (s->rv10_version == 3) {
             /* specific MPEG like DC coding not used */
             s->last_dc[0] = get_bits(&s->gb, 8);
@@ -282,7 +286,7 @@ static int rv10_decode_picture_header(MpegEncContext *s)
         s->mb_y = 0;
         mb_count = s->mb_width * s->mb_height;
     }
-    unk= get_bits(&s->gb, 3);   /* ignored */
+    skip_bits(&s->gb, 3);   /* ignored */
     s->f_code = 1;
     s->unrestricted_mv = 1;
 
@@ -292,32 +296,26 @@ static int rv10_decode_picture_header(MpegEncContext *s)
 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){
-    case 0: s->pict_type= FF_I_TYPE; break;
-    case 1: s->pict_type= FF_I_TYPE; break; //hmm ...
-    case 2: s->pict_type= FF_P_TYPE; break;
-    case 3: s->pict_type= FF_B_TYPE; break;
+    case 0: s->pict_type= AV_PICTURE_TYPE_I; break;
+    case 1: s->pict_type= AV_PICTURE_TYPE_I; break; //hmm ...
+    case 2: s->pict_type= AV_PICTURE_TYPE_P; break;
+    case 3: s->pict_type= AV_PICTURE_TYPE_B; break;
     default:
         av_log(s->avctx, AV_LOG_ERROR, "unknown frame type\n");
         return -1;
     }
 
-    if(s->last_picture_ptr==NULL && s->pict_type==FF_B_TYPE){
+    if(s->last_picture_ptr==NULL && s->pict_type==AV_PICTURE_TYPE_B){
         av_log(s->avctx, AV_LOG_ERROR, "early B pix\n");
         return -1;
     }
 
     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;
     }
 
@@ -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;
     }
-    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;
 
-        f= get_bits(&s->gb, av_log2(v)+1);
+    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, rpr_bits);
 
         if(f){
             new_w= 4*((uint8_t*)s->avctx->extradata)[6+2*f];
@@ -364,25 +360,18 @@ static int rv20_decode_picture_header(MpegEncContext *s)
         }
 
         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;
     if(seq - s->time < -0x4000) seq += 0x8000;
     if(seq != s->time){
-        if(s->pict_type!=FF_B_TYPE){
+        if(s->pict_type!=AV_PICTURE_TYPE_B){
             s->time= seq;
             s->pp_time= s->time - s->last_non_b_time;
             s->last_non_b_time= s->time;
@@ -403,9 +392,12 @@ static int rv20_decode_picture_header(MpegEncContext *s)
 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 == FF_I_TYPE;
+    s->h263_aic= s->pict_type == AV_PICTURE_TYPE_I;
 //    s->alt_inter_vlc=1;
 //    s->obmc=1;
 //    s->umvplus=1;
@@ -418,7 +410,7 @@ av_log(s->avctx, AV_LOG_DEBUG, "\n");*/
                    seq, s->mb_x, s->mb_y, s->pict_type, s->qscale, s->no_rounding);
     }
 
-    assert(s->pict_type != FF_B_TYPE || !s->low_delay);
+    assert(s->pict_type != AV_PICTURE_TYPE_B || !s->low_delay);
 
     return s->mb_width*s->mb_height - mb_pos;
 }
@@ -427,6 +419,7 @@ static av_cold int rv10_decode_init(AVCodecContext *avctx)
 {
     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");
@@ -438,6 +431,7 @@ static av_cold int rv10_decode_init(AVCodecContext *avctx)
     s->avctx= avctx;
     s->out_format = FMT_H263;
     s->codec_id= avctx->codec_id;
+    avctx->flags |= CODEC_FLAG_EMU_EDGE;
 
     s->orig_width = s->width  = avctx->coded_width;
     s->orig_height= s->height = avctx->coded_height;
@@ -445,32 +439,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);
 
-    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_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);
@@ -542,6 +531,11 @@ static int rv10_decode_packet(AVCodecContext *avctx,
         if(MPV_frame_start(s, avctx) < 0)
             return -1;
         ff_er_frame_start(s);
+    } else {
+        if (s->current_picture_ptr->f.pict_type != s->pict_type) {
+            av_log(s->avctx, AV_LOG_ERROR, "Slice type mismatch\n");
+            return -1;
+        }
     }
 
     av_dlog(avctx, "qscale=%d\n", s->qscale);
@@ -599,7 +593,7 @@ static int rv10_decode_packet(AVCodecContext *avctx,
             av_log(s->avctx, AV_LOG_ERROR, "ERROR at MB %d %d\n", s->mb_x, s->mb_y);
             return -1;
         }
-        if(s->pict_type != FF_B_TYPE)
+        if(s->pict_type != AV_PICTURE_TYPE_B)
             ff_h263_update_motion_val(s);
         MPV_decode_mb(s, s->block);
         if(s->loop_filter)
@@ -615,7 +609,7 @@ static int rv10_decode_packet(AVCodecContext *avctx,
         if(ret == SLICE_END) break;
     }
 
-    ff_er_add_slice(s, start_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END);
+    ff_er_add_slice(s, start_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_END);
 
     return s->gb.size_in_bits;
 }
@@ -674,7 +668,7 @@ static int rv10_decode_frame(AVCodecContext *avctx,
         ff_er_frame_end(s);
         MPV_frame_end(s);
 
-        if (s->pict_type == FF_B_TYPE || s->low_delay) {
+        if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
             *pict= *(AVFrame*)s->current_picture_ptr;
         } else if (s->last_picture_ptr != NULL) {
             *pict= *(AVFrame*)s->last_picture_ptr;
@@ -691,30 +685,28 @@ static int rv10_decode_frame(AVCodecContext *avctx,
 }
 
 AVCodec ff_rv10_decoder = {
-    "rv10",
-    AVMEDIA_TYPE_VIDEO,
-    CODEC_ID_RV10,
-    sizeof(MpegEncContext),
-    rv10_decode_init,
-    NULL,
-    rv10_decode_end,
-    rv10_decode_frame,
-    CODEC_CAP_DR1,
+    .name           = "rv10",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = CODEC_ID_RV10,
+    .priv_data_size = sizeof(MpegEncContext),
+    .init           = rv10_decode_init,
+    .close          = rv10_decode_end,
+    .decode         = rv10_decode_frame,
+    .capabilities   = CODEC_CAP_DR1,
     .max_lowres = 3,
     .long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"),
     .pix_fmts= ff_pixfmt_list_420,
 };
 
 AVCodec ff_rv20_decoder = {
-    "rv20",
-    AVMEDIA_TYPE_VIDEO,
-    CODEC_ID_RV20,
-    sizeof(MpegEncContext),
-    rv10_decode_init,
-    NULL,
-    rv10_decode_end,
-    rv10_decode_frame,
-    CODEC_CAP_DR1 | CODEC_CAP_DELAY,
+    .name           = "rv20",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = CODEC_ID_RV20,
+    .priv_data_size = sizeof(MpegEncContext),
+    .init           = rv10_decode_init,
+    .close          = rv10_decode_end,
+    .decode         = rv10_decode_frame,
+    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
     .flush= ff_mpeg_flush,
     .max_lowres = 3,
     .long_name = NULL_IF_CONFIG_SMALL("RealVideo 2.0"),