@@ -17,7 +17,7 @@ use rustysynth::{MidiFile, MidiFileSequencer, SoundFont, Synthesizer, Synthesize
1717use midly:: { Smf , TrackEventKind , MetaMessage , MidiMessage } ;
1818
1919use crate :: state:: AppState ;
20- use crossbeam_channel:: { bounded, Sender , Receiver } ;
20+ use crossbeam_channel:: { bounded, unbounded , Sender , Receiver } ;
2121
2222#[ allow( dead_code) ]
2323pub enum PlaybackHandle {
@@ -979,18 +979,14 @@ impl AudioSource for FfmpegSource {
979979 fn get_position_seconds ( & mut self ) -> f64 { self . current_time }
980980
981981 fn set_position_seconds ( & mut self , pos : f64 ) {
982- if let Some ( stream) = self . ictx . stream ( self . stream_index ) {
983- let tb = stream. time_base ( ) ;
984- let pts = ( pos / ( tb. numerator ( ) as f64 / tb. denominator ( ) as f64 ) ) as i64 ;
985-
986- unsafe {
987- ffmpeg_next:: ffi:: av_seek_frame (
988- self . ictx . as_mut_ptr ( ) ,
989- self . stream_index as i32 ,
990- pts,
991- ffmpeg_next:: ffi:: AVSEEK_FLAG_BACKWARD
992- ) ;
993- }
982+ let pts = ( pos * ffmpeg_next:: ffi:: AV_TIME_BASE as f64 ) as i64 ;
983+ unsafe {
984+ ffmpeg_next:: ffi:: av_seek_frame (
985+ self . ictx . as_mut_ptr ( ) ,
986+ -1 ,
987+ pts,
988+ ffmpeg_next:: ffi:: AVSEEK_FLAG_BACKWARD
989+ ) ;
994990 }
995991 self . decoder . flush ( ) ;
996992 self . buf_pos = self . sample_buf . len ( ) ;
@@ -1098,17 +1094,14 @@ impl AudioSource for VideoOnlySource {
10981094 fn get_position_seconds ( & mut self ) -> f64 { self . current_time }
10991095
11001096 fn set_position_seconds ( & mut self , pos : f64 ) {
1101- if let Some ( stream) = self . ictx . stream ( self . video_stream_index ) {
1102- let tb = stream. time_base ( ) ;
1103- let pts = ( pos / ( tb. numerator ( ) as f64 / tb. denominator ( ) as f64 ) ) as i64 ;
1104- unsafe {
1105- ffmpeg_next:: ffi:: av_seek_frame (
1106- self . ictx . as_mut_ptr ( ) ,
1107- self . video_stream_index as i32 ,
1108- pts,
1109- ffmpeg_next:: ffi:: AVSEEK_FLAG_BACKWARD
1110- ) ;
1111- }
1097+ let pts = ( pos * ffmpeg_next:: ffi:: AV_TIME_BASE as f64 ) as i64 ;
1098+ unsafe {
1099+ ffmpeg_next:: ffi:: av_seek_frame (
1100+ self . ictx . as_mut_ptr ( ) ,
1101+ -1 ,
1102+ pts,
1103+ ffmpeg_next:: ffi:: AVSEEK_FLAG_BACKWARD
1104+ ) ;
11121105 }
11131106 self . current_time = pos;
11141107 self . video_epoch += 1 ;
@@ -1665,15 +1658,15 @@ where
16651658 let chunk_frames = 1024 ;
16661659 let pool_size = 64 ;
16671660
1668- let ( ready_tx, ready_rx) = crossbeam_channel :: bounded :: < AudioChunk > ( pool_size) ;
1669- let ( free_tx, free_rx) = crossbeam_channel :: bounded :: < AudioChunk > ( pool_size ) ;
1661+ let ( ready_tx, ready_rx) = bounded :: < AudioChunk > ( pool_size) ;
1662+ let ( free_tx, free_rx) = unbounded :: < AudioChunk > ( ) ;
16701663
1671- let ( video_packet_tx, video_packet_rx) = crossbeam_channel :: bounded :: < ( u64 , ffmpeg_next:: Packet ) > ( 4096 ) ;
1664+ let ( video_packet_tx, video_packet_rx) = bounded :: < ( u64 , ffmpeg_next:: Packet ) > ( 4096 ) ;
16721665 audio_source. attach_video_queue ( video_packet_tx) ;
16731666
16741667 if let Some ( ( params, time_base) ) = audio_source. take_video_parameters ( ) {
1675- let ( video_frame_tx, video_frame_rx) = crossbeam_channel :: bounded :: < crate :: state:: VideoFrame > ( 16 ) ;
1676- let ( free_video_frame_tx, free_video_frame_rx) = crossbeam_channel :: bounded :: < crate :: state:: VideoFrame > ( 16 ) ;
1668+ let ( video_frame_tx, video_frame_rx) = bounded :: < crate :: state:: VideoFrame > ( 16 ) ;
1669+ let ( free_video_frame_tx, free_video_frame_rx) = unbounded :: < crate :: state:: VideoFrame > ( ) ;
16771670
16781671 for _ in 0 ..16 {
16791672 let _ = free_video_frame_tx. try_send ( crate :: state:: VideoFrame {
@@ -1706,23 +1699,22 @@ where
17061699 let tb = time_base. numerator ( ) as f64 / time_base. denominator ( ) as f64 ;
17071700 let mut local_epoch = 0 ;
17081701 let mut fallback_pts_seconds = 0.0 ;
1702+ let mut is_first_frame_after_seek = false ;
17091703
17101704 while let Ok ( ( packet_epoch, packet) ) = video_packet_rx_for_video. recv ( ) {
1711- let mut track_ended = {
1705+ {
17121706 let state = state_for_video. lock ( ) . unwrap ( ) ;
17131707 if state. seek_epoch > local_epoch {
17141708 decoder. flush ( ) ;
17151709 local_epoch = state. seek_epoch ;
1710+ is_first_frame_after_seek = true ;
17161711 }
1717- state. track_ended
1718- } ;
1712+ }
17191713
17201714 if packet_epoch < local_epoch {
17211715 continue ;
17221716 }
17231717
1724- if track_ended { return ; }
1725-
17261718 if decoder. send_packet ( & packet) . is_ok ( ) {
17271719 let mut decoded = ffmpeg_next:: frame:: Video :: empty ( ) ;
17281720 while decoder. receive_frame ( & mut decoded) . is_ok ( ) {
@@ -1738,34 +1730,74 @@ where
17381730 }
17391731
17401732 let mut skip_push = false ;
1733+ if is_first_frame_after_seek {
1734+ is_first_frame_after_seek = false ;
1735+ } else {
1736+ let sync_start = std:: time:: Instant :: now ( ) ;
1737+ loop {
1738+ let ( cached_seconds, current_epoch, is_paused, track_ended) = {
1739+ let state = state_for_video. lock ( ) . unwrap ( ) ;
1740+ ( state. current_seconds , state. seek_epoch , state. is_paused , state. track_ended )
1741+ } ;
1742+
1743+ if track_ended || current_epoch > local_epoch {
1744+ skip_push = true ;
1745+ break ;
1746+ }
1747+
1748+ if pts < cached_seconds - 0.05 {
1749+ skip_push = true ;
1750+ break ;
1751+ }
1752+
1753+ if pts <= cached_seconds + 0.05 {
1754+ break ;
1755+ }
1756+
1757+ if sync_start. elapsed ( ) > std:: time:: Duration :: from_millis ( 500 ) {
1758+ skip_push = true ;
1759+ break ;
1760+ }
1761+
1762+ let sleep_dur = if is_paused { 50 } else { 5 } ;
1763+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( sleep_dur) ) ;
1764+ }
1765+ }
1766+
1767+ if skip_push {
1768+ continue ;
1769+ }
1770+
1771+ let mut frame_opt = None ;
17411772 loop {
1742- let ( cached_seconds , current_epoch ) = {
1773+ let ( current_epoch , is_paused , track_ended ) = {
17431774 let state = state_for_video. lock ( ) . unwrap ( ) ;
1744- track_ended = state. track_ended ;
1745- ( state. current_seconds , state. seek_epoch )
1775+ ( state. seek_epoch , state. is_paused , state. track_ended )
17461776 } ;
1747-
17481777 if track_ended || current_epoch > local_epoch {
17491778 skip_push = true ;
17501779 break ;
17511780 }
1752-
1753- if pts < cached_seconds - 0.05 {
1754- skip_push = true ;
1755- break ;
1756- }
1757-
1758- if pts <= cached_seconds + 0.05 {
1759- break ;
1781+ match free_video_frame_rx. recv_timeout ( std:: time:: Duration :: from_millis ( 10 ) ) {
1782+ Ok ( f) => {
1783+ frame_opt = Some ( f) ;
1784+ break ;
1785+ }
1786+ Err ( crossbeam_channel:: RecvTimeoutError :: Timeout ) => {
1787+ let sleep_dur = if is_paused { 50 } else { 5 } ;
1788+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( sleep_dur) ) ;
1789+ }
1790+ Err ( crossbeam_channel:: RecvTimeoutError :: Disconnected ) => {
1791+ return ;
1792+ }
17601793 }
1761- std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 2 ) ) ;
17621794 }
17631795
17641796 if skip_push {
17651797 continue ;
17661798 }
17671799
1768- if let Ok ( mut frame) = free_video_frame_rx . recv ( ) {
1800+ if let Some ( mut frame) = frame_opt {
17691801 frame. pts = pts;
17701802 frame. width = decoded. width ( ) ;
17711803 frame. height = decoded. height ( ) ;
@@ -1841,20 +1873,23 @@ where
18411873
18421874 std:: thread:: spawn ( move || {
18431875 loop {
1844- if let Ok ( mut state) = state_for_decoder. try_lock ( ) {
1845- if let Some ( pos) = state. seek_request . take ( ) {
1846- audio_source. set_position_seconds ( pos) ;
1847- state. current_seconds = pos;
1848- state. seek_epoch += 1 ;
1849- while let Ok ( chunk) = ready_rx_for_decoder. try_recv ( ) {
1850- let _ = free_tx_for_decoder. try_send ( chunk) ;
1876+ let mut chunk = loop {
1877+ if let Ok ( mut state) = state_for_decoder. try_lock ( ) {
1878+ if let Some ( pos) = state. seek_request . take ( ) {
1879+ audio_source. set_position_seconds ( pos) ;
1880+ state. current_seconds = pos;
1881+ state. seek_epoch += 1 ;
1882+ while let Ok ( c) = ready_rx_for_decoder. try_recv ( ) {
1883+ let _ = free_tx_for_decoder. try_send ( c) ;
1884+ }
1885+ while let Ok ( _) = video_rx_for_decoder. try_recv ( ) { }
18511886 }
18521887 }
1853- }
1854-
1855- let mut chunk = match free_rx . recv ( ) {
1856- Ok ( c ) => c ,
1857- Err ( _ ) => break , // CPAL died
1888+ match free_rx . recv_timeout ( std :: time :: Duration :: from_millis ( 10 ) ) {
1889+ Ok ( c ) => break c ,
1890+ Err ( crossbeam_channel :: RecvTimeoutError :: Timeout ) => continue ,
1891+ Err ( crossbeam_channel :: RecvTimeoutError :: Disconnected ) => return ,
1892+ }
18581893 } ;
18591894
18601895 let decode_start = Instant :: now ( ) ;
@@ -1929,8 +1964,34 @@ where
19291964 state. stats . clipping_events += clips;
19301965 }
19311966
1932- if ready_tx. send ( chunk) . is_err ( ) {
1933- break ;
1967+ let mut chunk_to_send = chunk;
1968+ loop {
1969+ let mut seeked = false ;
1970+ if let Ok ( mut state) = state_for_decoder. try_lock ( ) {
1971+ if let Some ( pos) = state. seek_request . take ( ) {
1972+ audio_source. set_position_seconds ( pos) ;
1973+ state. current_seconds = pos;
1974+ state. seek_epoch += 1 ;
1975+ while let Ok ( c) = ready_rx_for_decoder. try_recv ( ) {
1976+ let _ = free_tx_for_decoder. try_send ( c) ;
1977+ }
1978+ while let Ok ( _) = video_rx_for_decoder. try_recv ( ) { }
1979+ seeked = true ;
1980+ }
1981+ }
1982+ if seeked {
1983+ let _ = free_tx_for_decoder. try_send ( chunk_to_send) ;
1984+ break ;
1985+ }
1986+ match ready_tx. send_timeout ( chunk_to_send, std:: time:: Duration :: from_millis ( 10 ) ) {
1987+ Ok ( _) => break ,
1988+ Err ( crossbeam_channel:: SendTimeoutError :: Timeout ( c) ) => {
1989+ chunk_to_send = c;
1990+ }
1991+ Err ( crossbeam_channel:: SendTimeoutError :: Disconnected ( _) ) => {
1992+ return ;
1993+ }
1994+ }
19341995 }
19351996
19361997 if frames_read == 0 {
0 commit comments