vf_split: support user-specifiable number of outputs.
This commit is contained in:
		
							parent
							
								
									dce415e7f1
								
							
						
					
					
						commit
						fd18ee0ff6
					
				| @ -1666,6 +1666,19 @@ not specified it will use the default value of 16. | ||||
| Adding this in the beginning of filter chains should make filtering | ||||
| faster due to better use of the memory cache. | ||||
| 
 | ||||
| @section split | ||||
| 
 | ||||
| Split input video into several identical outputs. | ||||
| 
 | ||||
| The filter accepts a single parameter which specifies the number of outputs. If | ||||
| unspecified, it defaults to 2. | ||||
| 
 | ||||
| For example | ||||
| @example | ||||
| avconv -i INPUT -filter_complex split=5 OUTPUT | ||||
| @end example | ||||
| will create 5 copies of the input video. | ||||
| 
 | ||||
| @section transpose | ||||
| 
 | ||||
| Transpose rows with columns in the input video and optionally flip it. | ||||
|  | ||||
| @ -25,24 +25,67 @@ | ||||
| 
 | ||||
| #include "avfilter.h" | ||||
| 
 | ||||
| static int split_init(AVFilterContext *ctx, const char *args, void *opaque) | ||||
| { | ||||
|     int i, nb_outputs = 2; | ||||
| 
 | ||||
|     if (args) { | ||||
|         nb_outputs = strtol(args, NULL, 0); | ||||
|         if (nb_outputs <= 0) { | ||||
|             av_log(ctx, AV_LOG_ERROR, "Invalid number of outputs specified: %d.\n", | ||||
|                    nb_outputs); | ||||
|             return AVERROR(EINVAL); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < nb_outputs; i++) { | ||||
|         char name[32]; | ||||
|         AVFilterPad pad = { 0 }; | ||||
| 
 | ||||
|         snprintf(name, sizeof(name), "output%d", i); | ||||
|         pad.type = AVMEDIA_TYPE_VIDEO; | ||||
|         pad.name = av_strdup(name); | ||||
| 
 | ||||
|         avfilter_insert_outpad(ctx, i, &pad); | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void split_uninit(AVFilterContext *ctx) | ||||
| { | ||||
|     int i; | ||||
| 
 | ||||
|     for (i = 0; i < ctx->output_count; i++) | ||||
|         av_freep(&ctx->output_pads[i].name); | ||||
| } | ||||
| 
 | ||||
| static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) | ||||
| { | ||||
|     avfilter_start_frame(inlink->dst->outputs[0], | ||||
|                          avfilter_ref_buffer(picref, ~AV_PERM_WRITE)); | ||||
|     avfilter_start_frame(inlink->dst->outputs[1], | ||||
|                          avfilter_ref_buffer(picref, ~AV_PERM_WRITE)); | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     int i; | ||||
| 
 | ||||
|     for (i = 0; i < ctx->output_count; i++) | ||||
|         avfilter_start_frame(ctx->outputs[i], | ||||
|                              avfilter_ref_buffer(picref, ~AV_PERM_WRITE)); | ||||
| } | ||||
| 
 | ||||
| static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | ||||
| { | ||||
|     avfilter_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); | ||||
|     avfilter_draw_slice(inlink->dst->outputs[1], y, h, slice_dir); | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     int i; | ||||
| 
 | ||||
|     for (i = 0; i < ctx->output_count; i++) | ||||
|         avfilter_draw_slice(ctx->outputs[i], y, h, slice_dir); | ||||
| } | ||||
| 
 | ||||
| static void end_frame(AVFilterLink *inlink) | ||||
| { | ||||
|     avfilter_end_frame(inlink->dst->outputs[0]); | ||||
|     avfilter_end_frame(inlink->dst->outputs[1]); | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     int i; | ||||
| 
 | ||||
|     for (i = 0; i < ctx->output_count; i++) | ||||
|         avfilter_end_frame(ctx->outputs[i]); | ||||
| 
 | ||||
|     avfilter_unref_buffer(inlink->cur_buf); | ||||
| } | ||||
| @ -51,6 +94,9 @@ AVFilter avfilter_vf_split = { | ||||
|     .name      = "split", | ||||
|     .description = NULL_IF_CONFIG_SMALL("Pass on the input to two outputs."), | ||||
| 
 | ||||
|     .init   = split_init, | ||||
|     .uninit = split_uninit, | ||||
| 
 | ||||
|     .inputs    = (AVFilterPad[]) {{ .name            = "default", | ||||
|                                     .type            = AVMEDIA_TYPE_VIDEO, | ||||
|                                     .get_video_buffer= avfilter_null_get_video_buffer, | ||||
| @ -58,9 +104,5 @@ AVFilter avfilter_vf_split = { | ||||
|                                     .draw_slice      = draw_slice, | ||||
|                                     .end_frame       = end_frame, }, | ||||
|                                   { .name = NULL}}, | ||||
|     .outputs   = (AVFilterPad[]) {{ .name            = "output1", | ||||
|                                     .type            = AVMEDIA_TYPE_VIDEO, }, | ||||
|                                   { .name            = "output2", | ||||
|                                     .type            = AVMEDIA_TYPE_VIDEO, }, | ||||
|                                   { .name = NULL}}, | ||||
|     .outputs   = (AVFilterPad[]) {{ .name = NULL}}, | ||||
| }; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user