@@ -661,6 +661,67 @@ TEST_CASE( "GetMaxFrame and GetMaxTime", "[libopenshot][timeline]" )
661661 CHECK (t.GetMaxTime () == Approx (20.0 ).margin (0.001 ));
662662}
663663
664+ TEST_CASE ( " GetMinFrame and GetMinTime" , " [libopenshot][timeline]" )
665+ {
666+ // Create a timeline
667+ Timeline t (640 , 480 , Fraction (30 , 1 ), 44100 , 2 , LAYOUT_STEREO);
668+
669+ std::stringstream path1;
670+ path1 << TEST_MEDIA_PATH << " interlaced.png" ;
671+ Clip clip1 (path1.str ());
672+ clip1.Id (" C1" );
673+ clip1.Layer (1 );
674+ clip1.Position (50 ); // Start at 50 seconds
675+ clip1.End (45 ); // Ends at 95 seconds
676+ t.AddClip (&clip1);
677+
678+ CHECK (t.GetMinTime () == Approx (50.0 ).margin (0.001 ));
679+ CHECK (t.GetMinFrame () == 50 * 30 );
680+
681+ Clip clip2 (path1.str ());
682+ clip2.Id (" C2" );
683+ clip2.Layer (2 );
684+ clip2.Position (0 ); // Start at 0 seconds
685+ clip2.End (55 ); // Ends at 55 seconds
686+ t.AddClip (&clip2);
687+
688+ CHECK (t.GetMinTime () == Approx (0.0 ).margin (0.001 ));
689+ CHECK (t.GetMinFrame () == 0 );
690+
691+ clip1.Position (80 ); // Move clip1 to start at 80 seconds
692+ clip2.Position (100 ); // Move clip2 to start at 100 seconds
693+ CHECK (t.GetMinTime () == Approx (80.0 ).margin (0.001 ));
694+ CHECK (t.GetMinFrame () == 80 * 30 );
695+
696+ clip2.Position (20 ); // Adjust clip2 to start at 20 seconds
697+ CHECK (t.GetMinTime () == Approx (20.0 ).margin (0.001 ));
698+ CHECK (t.GetMinFrame () == 20 * 30 );
699+
700+ clip2.End (35 ); // Adjust clip2 to end at 35 seconds
701+ CHECK (t.GetMinTime () == Approx (20.0 ).margin (0.001 ));
702+ CHECK (t.GetMinFrame () == 20 * 30 );
703+
704+ t.RemoveClip (&clip1);
705+ CHECK (t.GetMinTime () == Approx (20.0 ).margin (0.001 ));
706+ CHECK (t.GetMinFrame () == 20 * 30 );
707+
708+ // Update Clip's basic properties with JSON Diff
709+ std::stringstream json_change1;
710+ json_change1 << " [{\" type\" :\" update\" ,\" key\" :[\" clips\" ,{\" id\" :\" C2\" }],\" value\" :{\" id\" :\" C2\" ,\" layer\" :4000000,\" position\" :5.0,\" start\" :0,\" end\" :10},\" partial\" :false}]" ;
711+ t.ApplyJsonDiff (json_change1.str ());
712+
713+ CHECK (t.GetMinTime () == Approx (5.0 ).margin (0.001 ));
714+ CHECK (t.GetMinFrame () == 5 * 30 );
715+
716+ // Insert NEW Clip with JSON Diff
717+ std::stringstream json_change2;
718+ json_change2 << " [{\" type\" :\" insert\" ,\" key\" :[\" clips\" ],\" value\" :{\" id\" :\" C3\" ,\" layer\" :4000000,\" position\" :10.0,\" start\" :0,\" end\" :10,\" reader\" :{\" acodec\" :\"\" ,\" audio_bit_rate\" :0,\" audio_stream_index\" :-1,\" audio_timebase\" :{\" den\" :1,\" num\" :1},\" channel_layout\" :4,\" channels\" :0,\" display_ratio\" :{\" den\" :1,\" num\" :1},\" duration\" :3600.0,\" file_size\" :\" 160000\" ,\" fps\" :{\" den\" :1,\" num\" :30},\" has_audio\" :false,\" has_single_image\" :true,\" has_video\" :true,\" height\" :200,\" interlaced_frame\" :false,\" metadata\" :{},\" path\" :\" " << path1.str () << " \" ,\" pixel_format\" :-1,\" pixel_ratio\" :{\" den\" :1,\" num\" :1},\" sample_rate\" :0,\" top_field_first\" :true,\" type\" :\" QtImageReader\" ,\" vcodec\" :\"\" ,\" video_bit_rate\" :0,\" video_length\" :\" 108000\" ,\" video_stream_index\" :-1,\" video_timebase\" :{\" den\" :30,\" num\" :1},\" width\" :200}},\" partial\" :false}]" ;
719+ t.ApplyJsonDiff (json_change2.str ());
720+
721+ CHECK (t.GetMinTime () == Approx (5.0 ).margin (0.001 ));
722+ CHECK (t.GetMinFrame () == 5 * 30 );
723+ }
724+
664725TEST_CASE ( " Multi-threaded Timeline GetFrame" , " [libopenshot][timeline]" )
665726{
666727 Timeline *t = new Timeline (1280 , 720 , Fraction (24 , 1 ), 48000 , 2 , LAYOUT_STEREO);
0 commit comments