@@ -3,7 +3,7 @@ use std::{sync::Arc, time::Duration};
33use cap_media:: data:: { AudioInfo , FromSampleBytes } ;
44use cap_media:: feeds:: { AudioPlaybackBuffer , AudioSegment , AudioSegmentTrack } ;
55use cap_media:: MediaError ;
6- use cap_project:: { AudioConfiguration , ProjectConfiguration , XY } ;
6+ use cap_project:: { AudioConfiguration , ProjectConfiguration , TimelineSegment , XY } ;
77use cap_rendering:: { ProjectUniforms , RenderVideoConstants } ;
88use cpal:: {
99 traits:: { DeviceTrait , HostTrait , StreamTrait } ,
@@ -68,46 +68,117 @@ impl Playback {
6868 }
6969 . spawn ( ) ;
7070
71+ let mut current_segment_index: Option < usize > = None ;
72+ let mut segment_start_time = 0.0 ;
73+ let mut segment_elapsed = 0.0 ;
74+ let mut segment_timescale = 1.0 ;
75+
7176 loop {
72- let time =
73- ( self . start_frame_number as f64 / fps as f64 ) + start. elapsed ( ) . as_secs_f64 ( ) ;
74- let frame_number = ( time * fps as f64 ) . floor ( ) as u32 ;
77+ let elapsed = start. elapsed ( ) . as_secs_f64 ( ) ;
78+ let playhead_time = ( self . start_frame_number as f64 / fps as f64 ) + elapsed;
79+
80+ let project = self . project . borrow ( ) . clone ( ) ;
81+ let mut time_in_timeline = 0.0 ;
82+ let mut segment_found = false ;
83+
84+ if let Some ( timeline) = & project. timeline {
85+ for ( i, segment) in timeline. segments . iter ( ) . enumerate ( ) {
86+ let segment_duration = ( segment. end - segment. start ) / segment. timescale ;
87+
88+ if playhead_time >= time_in_timeline
89+ && playhead_time < time_in_timeline + segment_duration
90+ {
91+ if current_segment_index != Some ( i) {
92+ current_segment_index = Some ( i) ;
93+ segment_start_time = time_in_timeline;
94+ segment_elapsed = playhead_time - time_in_timeline;
95+ segment_timescale = segment. timescale ;
96+ } else {
97+ segment_elapsed = playhead_time - segment_start_time;
98+ }
99+ segment_found = true ;
100+ break ;
101+ }
102+
103+ time_in_timeline += segment_duration;
104+ }
105+ }
106+
107+ if !segment_found {
108+ if playhead_time >= duration {
109+ break ;
110+ }
111+ current_segment_index = Some ( 0 ) ;
112+ segment_start_time = 0.0 ;
113+ segment_elapsed = playhead_time;
114+ segment_timescale = 1.0 ;
115+ }
116+
117+ let frame_number = ( playhead_time * fps as f64 ) . floor ( ) as u32 ;
75118
76119 if frame_number as f64 >= fps as f64 * duration {
77120 break ;
78121 } ;
79122
80- let project = self . project . borrow ( ) . clone ( ) ;
123+ let segment_time = if let Some ( segment_idx) = current_segment_index {
124+ if let Some ( timeline) = & project. timeline {
125+ if segment_idx < timeline. segments . len ( ) {
126+ let segment = & timeline. segments [ segment_idx] ;
127+ segment. start + segment_elapsed * segment_timescale
128+ } else {
129+ elapsed
130+ }
131+ } else {
132+ elapsed
133+ }
134+ } else {
135+ elapsed
136+ } ;
81137
82- if let Some ( ( segment_time, segment_i) ) = project. get_segment_time ( time) {
83- let segment = & self . segments [ segment_i as usize ] ;
84-
85- let data = tokio:: select! {
86- _ = stop_rx. changed( ) => { break ; } ,
87- data = segment. decoders. get_frames( segment_time as f32 , !project. camera. hide) => { data }
88- } ;
89-
90- if let Some ( segment_frames) = data {
91- let uniforms = ProjectUniforms :: new (
92- & self . render_constants ,
93- & project,
94- frame_number,
95- fps,
96- resolution_base,
97- ) ;
98-
99- self . renderer
100- . render_frame ( segment_frames, uniforms, segment. cursor . clone ( ) )
101- . await ;
138+ if let Some ( segment_i) = current_segment_index {
139+ if segment_i < self . segments . len ( ) {
140+ let segment = & self . segments [ segment_i] ;
141+
142+ let data = tokio:: select! {
143+ _ = stop_rx. changed( ) => { break ; } ,
144+ data = segment. decoders. get_frames( segment_time as f32 , !project. camera. hide) => { data }
145+ } ;
146+
147+ if let Some ( segment_frames) = data {
148+ let uniforms = ProjectUniforms :: new (
149+ & self . render_constants ,
150+ & project,
151+ frame_number,
152+ fps,
153+ resolution_base,
154+ ) ;
155+
156+ self . renderer
157+ . render_frame ( segment_frames, uniforms, segment. cursor . clone ( ) )
158+ . await ;
159+ }
102160 }
103161 }
104162
105- tokio:: time:: sleep_until (
106- start
107- + ( frame_number - self . start_frame_number )
108- * Duration :: from_secs_f32 ( 1.0 / fps as f32 ) ,
109- )
110- . await ;
163+ let next_frame = ( frame_number + 1 ) as f64 / fps as f64 ;
164+ let time_to_wait = if let Some ( segment_idx) = current_segment_index {
165+ if let Some ( timeline) = & project. timeline {
166+ if segment_idx < timeline. segments . len ( ) {
167+ let segment = & timeline. segments [ segment_idx] ;
168+ Duration :: from_secs_f64 (
169+ ( next_frame - playhead_time) * segment. timescale ,
170+ )
171+ } else {
172+ Duration :: from_secs_f64 ( next_frame - playhead_time)
173+ }
174+ } else {
175+ Duration :: from_secs_f64 ( next_frame - playhead_time)
176+ }
177+ } else {
178+ Duration :: from_secs_f64 ( next_frame - playhead_time)
179+ } ;
180+
181+ tokio:: time:: sleep ( time_to_wait) . await ;
111182
112183 event_tx. send ( PlaybackEvent :: Frame ( frame_number) ) . ok ( ) ;
113184 }
0 commit comments