@@ -332,6 +332,127 @@ struct mp_filter *mp_autorotate_create(struct mp_filter *parent)
332332 return f ;
333333}
334334
335+ struct vflip_priv {
336+ struct mp_subfilter sub ;
337+ int prev_vflip ;
338+ int prev_imgfmt ;
339+ int target_vflip ;
340+ };
341+
342+ static void vflip_process (struct mp_filter * f )
343+ {
344+ struct vflip_priv * p = f -> priv ;
345+
346+ if (!mp_subfilter_read (& p -> sub ))
347+ return ;
348+
349+ struct mp_frame frame = p -> sub .frame ;
350+
351+ if (mp_frame_is_signaling (frame )) {
352+ mp_subfilter_continue (& p -> sub );
353+ return ;
354+ }
355+
356+ if (frame .type != MP_FRAME_VIDEO ) {
357+ MP_ERR (f , "video input required!\n" );
358+ return ;
359+ }
360+
361+ struct mp_image * img = frame .data ;
362+
363+ if (img -> params .vflip == p -> prev_vflip &&
364+ img -> imgfmt == p -> prev_imgfmt )
365+ {
366+ img -> params .vflip = p -> target_vflip ;
367+ mp_subfilter_continue (& p -> sub );
368+ return ;
369+ }
370+
371+ if (!mp_subfilter_drain_destroy (& p -> sub ))
372+ return ;
373+
374+ mp_assert (!p -> sub .filter );
375+
376+ int vflip = p -> prev_vflip = img -> params .vflip ;
377+ p -> target_vflip = vflip ;
378+ p -> prev_imgfmt = img -> imgfmt ;
379+
380+ struct mp_stream_info * info = mp_filter_find_stream_info (f );
381+ if (!vflip || (info && info -> vflip )) {
382+ mp_subfilter_continue (& p -> sub );
383+ return ;
384+ }
385+
386+ if (!mp_sws_supports_input (img -> imgfmt )) {
387+ MP_ERR (f , "Video vflip with this format not supported\n" );
388+ mp_subfilter_continue (& p -> sub );
389+ return ;
390+ }
391+
392+ char * args [] = {NULL };
393+
394+ p -> sub .filter = mp_create_user_filter (f , MP_OUTPUT_CHAIN_VIDEO , "vflip" , args );
395+
396+ if (p -> sub .filter ) {
397+ MP_INFO (f , "Inserting vflip filter.\n" );
398+ p -> target_vflip = 0 ;
399+ } else {
400+ MP_ERR (f , "could not create vflip filter\n" );
401+ }
402+
403+ mp_subfilter_continue (& p -> sub );
404+ }
405+
406+ static void vflip_reset (struct mp_filter * f )
407+ {
408+ struct vflip_priv * p = f -> priv ;
409+
410+ mp_subfilter_reset (& p -> sub );
411+ }
412+
413+ static void vflip_destroy (struct mp_filter * f )
414+ {
415+ struct vflip_priv * p = f -> priv ;
416+
417+ mp_subfilter_reset (& p -> sub );
418+ TA_FREEP (& p -> sub .filter );
419+ }
420+
421+ static bool vflip_command (struct mp_filter * f , struct mp_filter_command * cmd )
422+ {
423+ struct vflip_priv * p = f -> priv ;
424+
425+ if (cmd -> type == MP_FILTER_COMMAND_IS_ACTIVE ) {
426+ cmd -> is_active = !!p -> sub .filter ;
427+ return true;
428+ }
429+ return false;
430+ }
431+
432+ static const struct mp_filter_info vflip_filter = {
433+ .name = "autovflip" ,
434+ .priv_size = sizeof (struct vflip_priv ),
435+ .command = vflip_command ,
436+ .process = vflip_process ,
437+ .reset = vflip_reset ,
438+ .destroy = vflip_destroy ,
439+ };
440+
441+ struct mp_filter * mp_autovflip_create (struct mp_filter * parent )
442+ {
443+ struct mp_filter * f = mp_filter_create (parent , & vflip_filter );
444+ if (!f )
445+ return NULL ;
446+
447+ struct vflip_priv * p = f -> priv ;
448+ p -> prev_vflip = -1 ;
449+
450+ p -> sub .in = mp_filter_add_pin (f , MP_PIN_IN , "in" );
451+ p -> sub .out = mp_filter_add_pin (f , MP_PIN_OUT , "out" );
452+
453+ return f ;
454+ }
455+
335456struct aspeed_priv {
336457 struct mp_subfilter sub ;
337458 double cur_speed , cur_speed_drop ;
0 commit comments