You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	vf_codecview: added new options
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
		
				
					committed by
					
						 Michael Niedermayer
						Michael Niedermayer
					
				
			
			
				
	
			
			
			
						parent
						
							2234566cfb
						
					
				
				
					commit
					7a2b9dd060
				
			| @@ -4790,16 +4790,48 @@ backward predicted MVs of B-frames | ||||
| @end table | ||||
|  | ||||
| @item qp | ||||
| Display quantization parameters using the chroma planes | ||||
| Display quantization parameters using the chroma planes. | ||||
|  | ||||
| @item mv_type, mvt | ||||
| Set motion vectors type to visualize. Includes MVs from all frames unless specified by @var{frame_type} option. | ||||
|  | ||||
| Available flags for @var{mv_type} are: | ||||
|  | ||||
| @table @samp | ||||
| @item fp | ||||
| forward predicted MVs | ||||
| @item bp | ||||
| backward predicted MVs | ||||
| @end table | ||||
|  | ||||
| @item frame_type, ft | ||||
| Set frame type to visualize motion vectors of. | ||||
|  | ||||
| Available flags for @var{frame_type} are: | ||||
|  | ||||
| @table @samp | ||||
| @item if | ||||
| intra-coded frames (I-frames) | ||||
| @item pf | ||||
| predicted frames (P-frames) | ||||
| @item bf | ||||
| bi-directionally predicted frames (B-frames) | ||||
| @end table | ||||
| @end table | ||||
|  | ||||
| @subsection Examples | ||||
|  | ||||
| @itemize | ||||
| @item | ||||
| Visualizes multi-directionals MVs from P and B-Frames using @command{ffplay}: | ||||
| Visualize forward predicted MVs of all frames using @command{ffplay}: | ||||
| @example | ||||
| ffplay -flags2 +export_mvs input.mpg -vf codecview=mv=pf+bf+bb | ||||
| ffplay -flags2 +export_mvs input.mp4 -vf codecview=mv_type=fp | ||||
| @end example | ||||
|  | ||||
| @item | ||||
| Visualize multi-directionals MVs of P and B-Frames using @command{ffplay}: | ||||
| @example | ||||
| ffplay -flags2 +export_mvs input.mp4 -vf codecview=mv=pf+bf+bb | ||||
| @end example | ||||
| @end itemize | ||||
|  | ||||
|   | ||||
| @@ -38,22 +38,40 @@ | ||||
| #define MV_P_FOR  (1<<0) | ||||
| #define MV_B_FOR  (1<<1) | ||||
| #define MV_B_BACK (1<<2) | ||||
| #define MV_TYPE_FOR  (1<<0) | ||||
| #define MV_TYPE_BACK (1<<1) | ||||
| #define FRAME_TYPE_I (1<<0) | ||||
| #define FRAME_TYPE_P (1<<1) | ||||
| #define FRAME_TYPE_B (1<<2) | ||||
|  | ||||
| typedef struct { | ||||
|     const AVClass *class; | ||||
|     unsigned mv; | ||||
|     unsigned frame_type; | ||||
|     unsigned mv_type; | ||||
|     int hsub, vsub; | ||||
|     int qp; | ||||
| } CodecViewContext; | ||||
|  | ||||
| #define OFFSET(x) offsetof(CodecViewContext, x) | ||||
| #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM | ||||
| #define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, 0, 0, FLAGS, unit } | ||||
|  | ||||
| static const AVOption codecview_options[] = { | ||||
|     { "mv", "set motion vectors to visualize", OFFSET(mv), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "mv" }, | ||||
|         {"pf", "forward predicted MVs of P-frames",  0, AV_OPT_TYPE_CONST, {.i64 = MV_P_FOR },  INT_MIN, INT_MAX, FLAGS, "mv"}, | ||||
|         {"bf", "forward predicted MVs of B-frames",  0, AV_OPT_TYPE_CONST, {.i64 = MV_B_FOR },  INT_MIN, INT_MAX, FLAGS, "mv"}, | ||||
|         {"bb", "backward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = MV_B_BACK }, INT_MIN, INT_MAX, FLAGS, "mv"}, | ||||
|         CONST("pf", "forward predicted MVs of P-frames",  MV_P_FOR,  "mv"), | ||||
|         CONST("bf", "forward predicted MVs of B-frames",  MV_B_FOR,  "mv"), | ||||
|         CONST("bb", "backward predicted MVs of B-frames", MV_B_BACK, "mv"), | ||||
|     { "qp", NULL, OFFSET(qp), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS }, | ||||
|     { "mv_type", "set motion vectors type", OFFSET(mv_type), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "mv_type" }, | ||||
|     { "mvt",     "set motion vectors type", OFFSET(mv_type), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "mv_type" }, | ||||
|         CONST("fp", "forward predicted MVs",  MV_TYPE_FOR,  "mv_type"), | ||||
|         CONST("bp", "backward predicted MVs", MV_TYPE_BACK, "mv_type"), | ||||
|     { "frame_type", "set frame types to visualize motion vectors of", OFFSET(frame_type), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "frame_type" }, | ||||
|     { "ft",         "set frame types to visualize motion vectors of", OFFSET(frame_type), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "frame_type" }, | ||||
|         CONST("if", "I-frames", FRAME_TYPE_I, "frame_type"), | ||||
|         CONST("pf", "P-frames", FRAME_TYPE_P, "frame_type"), | ||||
|         CONST("bf", "B-frames", FRAME_TYPE_B, "frame_type"), | ||||
|     { NULL } | ||||
| }; | ||||
|  | ||||
| @@ -224,20 +242,37 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (s->mv) { | ||||
|     if (s->mv || s->mv_type) { | ||||
|         AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MOTION_VECTORS); | ||||
|         if (sd) { | ||||
|             int i; | ||||
|             const AVMotionVector *mvs = (const AVMotionVector *)sd->data; | ||||
|             const int is_iframe = (s->frame_type & FRAME_TYPE_I) && frame->pict_type == AV_PICTURE_TYPE_I; | ||||
|             const int is_pframe = (s->frame_type & FRAME_TYPE_P) && frame->pict_type == AV_PICTURE_TYPE_P; | ||||
|             const int is_bframe = (s->frame_type & FRAME_TYPE_B) && frame->pict_type == AV_PICTURE_TYPE_B; | ||||
|  | ||||
|             for (i = 0; i < sd->size / sizeof(*mvs); i++) { | ||||
|                 const AVMotionVector *mv = &mvs[i]; | ||||
|                 const int direction = mv->source > 0; | ||||
|                 if ((direction == 0 && (s->mv & MV_P_FOR)  && frame->pict_type == AV_PICTURE_TYPE_P) || | ||||
|                     (direction == 0 && (s->mv & MV_B_FOR)  && frame->pict_type == AV_PICTURE_TYPE_B) || | ||||
|                     (direction == 1 && (s->mv & MV_B_BACK) && frame->pict_type == AV_PICTURE_TYPE_B)) | ||||
|                     draw_arrow(frame->data[0], mv->dst_x, mv->dst_y, mv->src_x, mv->src_y, | ||||
|                                frame->width, frame->height, frame->linesize[0], | ||||
|                                100, 0, mv->source > 0); | ||||
|  | ||||
|                 if (s->mv_type) { | ||||
|                     const int is_fp = direction == 0 && (s->mv_type & MV_TYPE_FOR); | ||||
|                     const int is_bp = direction == 1 && (s->mv_type & MV_TYPE_BACK); | ||||
|  | ||||
|                     if ((!s->frame_type && (is_fp || is_bp)) || | ||||
|                         is_iframe && is_fp || is_iframe && is_bp || | ||||
|                         is_pframe && is_fp || | ||||
|                         is_bframe && is_fp || is_bframe && is_bp) | ||||
|                         draw_arrow(frame->data[0], mv->dst_x, mv->dst_y, mv->src_x, mv->src_y, | ||||
|                                    frame->width, frame->height, frame->linesize[0], | ||||
|                                    100, 0, direction); | ||||
|                 } else if (s->mv) | ||||
|                     if ((direction == 0 && (s->mv & MV_P_FOR)  && frame->pict_type == AV_PICTURE_TYPE_P) || | ||||
|                         (direction == 0 && (s->mv & MV_B_FOR)  && frame->pict_type == AV_PICTURE_TYPE_B) || | ||||
|                         (direction == 1 && (s->mv & MV_B_BACK) && frame->pict_type == AV_PICTURE_TYPE_B)) | ||||
|                         draw_arrow(frame->data[0], mv->dst_x, mv->dst_y, mv->src_x, mv->src_y, | ||||
|                                    frame->width, frame->height, frame->linesize[0], | ||||
|                                    100, 0, direction); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user