motion vector vissualization improvements patch by (Wolfgang Hesseler <qv at multimed...
authorWolfgang Hesseler <qv@multimediaware.com>
Tue, 30 Dec 2003 02:12:12 +0000 (02:12 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 30 Dec 2003 02:12:12 +0000 (02:12 +0000)
Originally committed as revision 2636 to svn://svn.ffmpeg.org/ffmpeg/trunk

ffmpeg.c
ffplay.c
libavcodec/avcodec.h
libavcodec/h263dec.c
libavcodec/h264.c
libavcodec/mpeg12.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h
libavcodec/rv10.c

index ff782d2..0724984 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -131,6 +131,7 @@ static int packet_size = 0;
 static int error_rate = 0;
 static int strict = 0;
 static int debug = 0;
+static int debug_mv = 0;
 extern int loop_input; /* currently a hack */
 
 static int gop_size = 12;
@@ -1672,6 +1673,11 @@ static void opt_debug(const char *arg)
     debug = atoi(arg);
 }
 
+static void opt_vismv(const char *arg)
+{
+    debug_mv = atoi(arg);
+}
+    
 static void opt_verbose(const char *arg)
 {
     verbose = atoi(arg);
@@ -2171,8 +2177,9 @@ static void opt_input_file(const char *filename)
             enc->workaround_bugs = workaround_bugs;
             enc->error_resilience = error_resilience; 
             enc->error_concealment = error_concealment; 
-            enc->idct_algo= idct_algo;
-            enc->debug= debug;
+            enc->idct_algo = idct_algo;
+            enc->debug = debug;
+            enc->debug_mv = debug_mv;            
             if(bitexact)
                 enc->flags|= CODEC_FLAG_BITEXACT;
 
@@ -2382,8 +2389,8 @@ static void opt_output_file(const char *filename)
                 video_enc->qblur = video_qblur;
                 video_enc->qcompress = video_qcomp;
                 video_enc->rc_eq = video_rc_eq;
-                video_enc->debug= debug;
-                
+                video_enc->debug = debug;
+                video_enc->debug_mv = debug_mv;                
                 p= video_rc_override_string;
                 for(i=0; p; i++){
                     int start, end, q;
@@ -2913,6 +2920,7 @@ const OptionDef options[] = {
     { "copyright", HAS_ARG | OPT_STRING, {(void*)&str_copyright}, "set the copyright", "string" },
     { "comment", HAS_ARG | OPT_STRING, {(void*)&str_comment}, "set the comment", "string" },
     { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
+    { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
     { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark}, 
       "add timings for benchmarking" },
     { "dump", OPT_BOOL | OPT_EXPERT, {(void*)&do_pkt_dump}, 
index 8f06f8f..c5c2ca1 100644 (file)
--- a/ffplay.c
+++ b/ffplay.c
@@ -166,6 +166,7 @@ static int show_status;
 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
 static int64_t start_time = AV_NOPTS_VALUE;
 static int debug = 0;
+static int debug_mv = 0;
 static int step = 0;
 
 /* current context */
@@ -1196,7 +1197,8 @@ static int stream_component_open(VideoState *is, int stream_index)
 
         packet_queue_init(&is->videoq);
         is->video_tid = SDL_CreateThread(video_thread, is);
-        enc->debug= debug;
+        enc->debug = debug;
+        enc->debug_mv = debug_mv;
         break;
     default:
         break;
@@ -1784,6 +1786,11 @@ static void opt_debug(const char *arg)
     debug = atoi(arg);
 }
     
+static void opt_vismv(const char *arg)
+{
+    debug_mv = atoi(arg);
+}
+    
 const OptionDef options[] = {
     { "h", 0, {(void*)show_help}, "show help" },    
     { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
@@ -1800,6 +1807,7 @@ const OptionDef options[] = {
     { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
     { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
     { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
+    { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
 #ifdef CONFIG_NETWORK
     { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
 #endif
index 39a7166..ef9950b 100644 (file)
@@ -1133,7 +1133,7 @@ typedef struct AVCodecContext {
 #define FF_DEBUG_MB_TYPE   8
 #define FF_DEBUG_QP        16
 #define FF_DEBUG_MV        32
-#define FF_DEBUG_VIS_MV    0x00000040
+//#define FF_DEBUG_VIS_MV    0x00000040
 #define FF_DEBUG_SKIP      0x00000080
 #define FF_DEBUG_STARTCODE 0x00000100
 #define FF_DEBUG_PTS       0x00000200
@@ -1144,6 +1144,16 @@ typedef struct AVCodecContext {
 #define FF_DEBUG_VIS_MB_TYPE 0x00004000
     
     /**
+     * debug.
+     * - encoding: set by user.
+     * - decoding: set by user.
+     */
+    int debug_mv;
+#define FF_DEBUG_VIS_MV_P_FOR  0x00000001 //visualize forward predicted MVs of P frames
+#define FF_DEBUG_VIS_MV_B_FOR  0x00000002 //visualize forward predicted MVs of B frames
+#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames
+
+    /**
      * error.
      * - encoding: set by lavc if flags&CODEC_FLAG_PSNR
      * - decoding: unused
index 1372e4a..fd02268 100644 (file)
@@ -703,10 +703,10 @@ assert(s->current_picture.pict_type == s->current_picture_ptr->pict_type);
 assert(s->current_picture.pict_type == s->pict_type);
     if(s->pict_type==B_TYPE || s->low_delay){
         *pict= *(AVFrame*)&s->current_picture;
-        ff_print_debug_info(s, s->current_picture_ptr);
+        ff_print_debug_info(s, pict);
     } else {
         *pict= *(AVFrame*)&s->last_picture;
-        ff_print_debug_info(s, s->last_picture_ptr);
+        ff_print_debug_info(s, pict);
     }
 
     /* Return the Picture timestamp as the frame number */
index 0742277..0de3827 100644 (file)
@@ -4172,7 +4172,7 @@ static int decode_frame(AVCodecContext *avctx,
     }
 
     *pict= *(AVFrame*)&s->current_picture; //FIXME 
-    ff_print_debug_info(s, s->current_picture_ptr);
+    ff_print_debug_info(s, pict);
     assert(pict->data[0]);
 //printf("out %d\n", (int)pict->data[0]);
 #if 0 //?
index 8a240da..4cc164d 100644 (file)
@@ -2305,14 +2305,14 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict)
 
         if (s->pict_type == B_TYPE || s->low_delay) {
             *pict= *(AVFrame*)s->current_picture_ptr;
-            ff_print_debug_info(s, s->current_picture_ptr);
+            ff_print_debug_info(s, pict);
         } else {
             s->picture_number++;
             /* latency of 1 frame for I and P frames */
             /* XXX: use another variable than picture_number */
             if (s->last_picture_ptr != NULL) {
                 *pict= *(AVFrame*)s->last_picture_ptr;
-                 ff_print_debug_info(s, s->last_picture_ptr);
+                 ff_print_debug_info(s, pict);
             }
         }
 
index dae3cd4..fce7135 100644 (file)
@@ -337,7 +337,7 @@ static int alloc_picture(MpegEncContext *s, Picture *pic, int shared){
                 CHECKED_ALLOCZ(pic->ref_index[i] , b8_array_size * sizeof(uint8_t))
             }
             pic->motion_subsample_log2= 2;
-        }else if(s->out_format == FMT_H263 || s->encoding || (s->avctx->debug&(FF_DEBUG_VIS_MV|FF_DEBUG_MV))){
+        }else if(s->out_format == FMT_H263 || s->encoding || (s->avctx->debug&FF_DEBUG_MV) || (s->avctx->debug_mv)){
             for(i=0; i<2; i++){
                 CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b8_array_size+1) * sizeof(uint16_t)*2) //FIXME
                 pic->motion_val[i]= pic->motion_val_base[i]+1;
@@ -564,6 +564,11 @@ int MPV_common_init(MpegEncContext *s)
     }
 
     s->parse_context.state= -1;
+    if((s->avctx->debug&(FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) || (s->avctx->debug_mv)){
+       s->visualization_buffer[0] = av_malloc((s->mb_width*16 + 2*EDGE_WIDTH) * s->mb_height*16 + 2*EDGE_WIDTH);
+       s->visualization_buffer[1] = av_malloc((s->mb_width*8 + EDGE_WIDTH) * s->mb_height*8 + EDGE_WIDTH);
+       s->visualization_buffer[2] = av_malloc((s->mb_width*8 + EDGE_WIDTH) * s->mb_height*8 + EDGE_WIDTH);
+    }
 
     s->context_initialized = 1;
     return 0;
@@ -641,6 +646,9 @@ void MPV_common_end(MpegEncContext *s)
     s->last_picture_ptr=
     s->next_picture_ptr=
     s->current_picture_ptr= NULL;
+    for(i=0; i<3; i++)
+        if (s->visualization_buffer[i])
+            av_free(s->visualization_buffer[i]);
 }
 
 #ifdef CONFIG_ENCODERS
@@ -1361,13 +1369,22 @@ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int
 /**
  * prints debuging info for the given picture.
  */
-void ff_print_debug_info(MpegEncContext *s, Picture *pict){
+void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
 
     if(!pict || !pict->mb_type) return;
 
     if(s->avctx->debug&(FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)){
         int x,y;
-
+        
+        av_log(s->avctx,AV_LOG_DEBUG,"New frame, type: ");
+        switch (pict->pict_type) {
+            case FF_I_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"I\n"); break;
+            case FF_P_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"P\n"); break;
+            case FF_B_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"B\n"); break;
+            case FF_S_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"S\n"); break;
+            case FF_SI_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"SI\n"); break;
+            case FF_SP_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"SP\n"); break;            
+        }
         for(y=0; y<s->mb_height; y++){
             for(x=0; x<s->mb_width; x++){
                 if(s->avctx->debug&FF_DEBUG_SKIP){
@@ -1380,7 +1397,6 @@ void ff_print_debug_info(MpegEncContext *s, Picture *pict){
                 }
                 if(s->avctx->debug&FF_DEBUG_MB_TYPE){
                     int mb_type= pict->mb_type[x + y*s->mb_stride];
-                    
                     //Type & MV direction
                     if(IS_PCM(mb_type))
                         av_log(s->avctx, AV_LOG_DEBUG, "P");
@@ -1433,45 +1449,71 @@ void ff_print_debug_info(MpegEncContext *s, Picture *pict){
         }
     }
 
-    if(s->avctx->debug&(FF_DEBUG_VIS_MV|FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)){
+    if((s->avctx->debug&(FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) || (s->avctx->debug_mv)){
         const int shift= 1 + s->quarter_sample;
         int mb_y;
-        uint8_t *ptr= pict->data[0];
+        uint8_t *ptr;
         s->low_delay=0; //needed to see the vectors without trashing the buffers
+        int i;
+
+        for(i=0; i<3; i++){
+            memcpy(s->visualization_buffer[i], pict->data[i], (i==0) ? pict->linesize[i]*s->height:pict->linesize[i]*s->height/2);
+            pict->data[i]= s->visualization_buffer[i];
+        }
+        pict->type= FF_BUFFER_TYPE_COPY;
+        ptr= pict->data[0];
 
         for(mb_y=0; mb_y<s->mb_height; mb_y++){
             int mb_x;
             for(mb_x=0; mb_x<s->mb_width; mb_x++){
                 const int mb_index= mb_x + mb_y*s->mb_stride;
-                if((s->avctx->debug&FF_DEBUG_VIS_MV) && pict->motion_val){
-                  if(IS_8X8(pict->mb_type[mb_index])){
-                    int i;
-                    for(i=0; i<4; i++){
+                if((s->avctx->debug_mv) && pict->motion_val){
+                  int type;
+                  for(type=0; type<3; type++){
+                    int direction;
+                    switch (type) {
+                      case 0: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_P_FOR)) || (pict->pict_type!=FF_P_TYPE))
+                                continue;
+                              direction = 0;
+                              break;
+                      case 1: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_FOR)) || (pict->pict_type!=FF_B_TYPE))
+                                continue;
+                              direction = 0;
+                              break;
+                      case 2: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_BACK)) || (pict->pict_type!=FF_B_TYPE))
+                                continue;
+                              direction = 1;
+                              break;
+                    }
+                    if(IS_8X8(pict->mb_type[mb_index])){
+                      int i;
+                      for(i=0; i<4; i++){
                         int sx= mb_x*16 + 4 + 8*(i&1);
                         int sy= mb_y*16 + 4 + 8*(i>>1);
                         int xy= 1 + mb_x*2 + (i&1) + (mb_y*2 + 1 + (i>>1))*(s->mb_width*2 + 2);
-                        int mx= (pict->motion_val[0][xy][0]>>shift) + sx;
-                        int my= (pict->motion_val[0][xy][1]>>shift) + sy;
+                        int mx= (pict->motion_val[direction][xy][0]>>shift) + sx;
+                        int my= (pict->motion_val[direction][xy][1]>>shift) + sy;
                         draw_arrow(ptr, sx, sy, mx, my, s->width, s->height, s->linesize, 100);
-                    }
-                  }else if(IS_16X8(pict->mb_type[mb_index])){
-                    int i;
-                    for(i=0; i<2; i++){
+                      }
+                    }else if(IS_16X8(pict->mb_type[mb_index])){
+                      int i;
+                      for(i=0; i<2; i++){
                         int sx=mb_x*16 + 8;
                         int sy=mb_y*16 + 4 + 8*i;
                         int xy=1 + mb_x*2 + (mb_y*2 + 1 + i)*(s->mb_width*2 + 2);
-                        int mx=(pict->motion_val[0][xy][0]>>shift) + sx;
-                        int my=(pict->motion_val[0][xy][1]>>shift) + sy;
+                        int mx=(pict->motion_val[direction][xy][0]>>shift) + sx;
+                        int my=(pict->motion_val[direction][xy][1]>>shift) + sy;
                         draw_arrow(ptr, sx, sy, mx, my, s->width, s->height, s->linesize, 100);
+                      }
+                    }else{
+                      int sx= mb_x*16 + 8;
+                      int sy= mb_y*16 + 8;
+                      int xy= 1 + mb_x*2 + (mb_y*2 + 1)*(s->mb_width*2 + 2);
+                      int mx= (pict->motion_val[direction][xy][0]>>shift) + sx;
+                      int my= (pict->motion_val[direction][xy][1]>>shift) + sy;
+                      draw_arrow(ptr, sx, sy, mx, my, s->width, s->height, s->linesize, 100);
                     }
-                  }else{
-                    int sx= mb_x*16 + 8;
-                    int sy= mb_y*16 + 8;
-                    int xy= 1 + mb_x*2 + (mb_y*2 + 1)*(s->mb_width*2 + 2);
-                    int mx= (pict->motion_val[0][xy][0]>>shift) + sx;
-                    int my= (pict->motion_val[0][xy][1]>>shift) + sy;
-                    draw_arrow(ptr, sx, sy, mx, my, s->width, s->height, s->linesize, 100);
-                  }
+                  }                  
                 }
                 if((s->avctx->debug&FF_DEBUG_VIS_QP) && pict->motion_val){
                     uint64_t c= (pict->qscale_table[mb_index]*128/31) * 0x0101010101010101ULL;
index 39461f7..cf2b5cf 100644 (file)
@@ -304,6 +304,7 @@ typedef struct MpegEncContext {
     Picture *last_picture_ptr;     ///< pointer to the previous picture.
     Picture *next_picture_ptr;     ///< pointer to the next picture (for bidir pred) 
     Picture *current_picture_ptr;  ///< pointer to the current picture
+    uint8_t *visualization_buffer[3]; //< temporary buffer vor MV visualization
     int last_dc[3];                ///< last DC values for MPEG1 
     int16_t *dc_val[3];            ///< used for mpeg4 DC prediction, all 3 arrays must be continuous 
     int16_t dc_cache[4*5];
@@ -705,7 +706,7 @@ void ff_emulated_edge_mc(uint8_t *buf, uint8_t *src, int linesize, int block_w,
 #define END_NOT_FOUND -100
 int ff_combine_frame( MpegEncContext *s, int next, uint8_t **buf, int *buf_size);
 void ff_mpeg_flush(AVCodecContext *avctx);
-void ff_print_debug_info(MpegEncContext *s, Picture *pict);
+void ff_print_debug_info(MpegEncContext *s, AVFrame *pict);
 void ff_write_quant_matrix(PutBitContext *pb, int16_t *matrix);
 int ff_find_unused_picture(MpegEncContext *s, int shared);
 void ff_denoise_dct(MpegEncContext *s, DCTELEM *block);
index 01623c7..832e5e1 100644 (file)
@@ -662,10 +662,10 @@ static int rv10_decode_frame(AVCodecContext *avctx,
     
         if(s->pict_type==B_TYPE || s->low_delay){
             *pict= *(AVFrame*)&s->current_picture;
-            ff_print_debug_info(s, s->current_picture_ptr);
+            ff_print_debug_info(s, pict);
         } else {
             *pict= *(AVFrame*)&s->last_picture;
-            ff_print_debug_info(s, s->last_picture_ptr);
+            ff_print_debug_info(s, pict);
         }
         
         *data_size = sizeof(AVFrame);