@@ -50,69 +50,89 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
5050 ITrack rtspVideoTrack = null ;
5151 ITrack rtspAudioTrack = null ;
5252
53- // frag_bunny.mp4 audio is not playable in VLC on Windows 11 (works on MacOS)
54- using ( Stream fs = new BufferedStream ( new FileStream ( fileName , FileMode . Open , FileAccess . Read , FileShare . Read ) ) )
53+ if ( Path . GetExtension ( fileName ) == ".mp4" )
5554 {
56- using ( var fmp4 = await FragmentedMp4 . ParseAsync ( fs ) )
55+ // frag_bunny.mp4 audio is not playable in VLC on Windows 11 (works on MacOS)
56+ using ( Stream fs = new BufferedStream ( new FileStream ( fileName , FileMode . Open , FileAccess . Read , FileShare . Read ) ) )
5757 {
58- videoTrackBox = fmp4 . FindVideoTracks ( ) . FirstOrDefault ( ) ;
59- audioTrackBox = fmp4 . FindAudioTracks ( ) . FirstOrDefault ( ) ;
60-
61- parsedMDAT = await fmp4 . ParseMdatAsync ( ) ;
62-
63- if ( videoTrackBox != null )
58+ using ( var fmp4 = await FragmentedMp4 . ParseAsync ( fs ) )
6459 {
65- videoTrackId = fmp4 . FindVideoTrackID ( ) . First ( ) ;
66- videoFrameRate = fmp4 . CalculateFrameRate ( videoTrackBox ) ;
60+ videoTrackBox = fmp4 . FindVideoTracks ( ) . FirstOrDefault ( ) ;
61+ audioTrackBox = fmp4 . FindAudioTracks ( ) . FirstOrDefault ( ) ;
6762
68- var h264VisualSample = videoTrackBox . GetMdia ( ) . GetMinf ( ) . GetStbl ( ) . GetStsd ( ) . Children . FirstOrDefault ( x => x . Type == VisualSampleEntryBox . TYPE3 || x . Type == VisualSampleEntryBox . TYPE4 ) as VisualSampleEntryBox ;
69- if ( h264VisualSample != null )
70- {
71- var avcC = ( h264VisualSample . Children . First ( x => x . Type == AvcConfigurationBox . TYPE ) as AvcConfigurationBox ) . AvcDecoderConfigurationRecord ;
72- rtspVideoTrack = new SharpRTSPServer . H264Track ( avcC . AvcProfileIndication , 0 , avcC . AvcLevelIndication ) ;
73- _server . AddVideoTrack ( rtspVideoTrack ) ;
74- }
75- else
63+ parsedMDAT = await fmp4 . ParseMdatAsync ( ) ;
64+
65+ if ( videoTrackBox != null )
7666 {
77- var h265VisualSample = videoTrackBox . GetMdia ( ) . GetMinf ( ) . GetStbl ( ) . GetStsd ( ) . Children . FirstOrDefault ( x => x . Type == VisualSampleEntryBox . TYPE6 || x . Type == VisualSampleEntryBox . TYPE7 ) as VisualSampleEntryBox ;
78- if ( h265VisualSample != null )
67+ videoTrackId = fmp4 . FindVideoTrackID ( ) . First ( ) ;
68+ videoFrameRate = fmp4 . CalculateFrameRate ( videoTrackBox ) ;
69+
70+ var h264VisualSample = videoTrackBox . GetMdia ( ) . GetMinf ( ) . GetStbl ( ) . GetStsd ( ) . Children . FirstOrDefault ( x => x . Type == VisualSampleEntryBox . TYPE3 || x . Type == VisualSampleEntryBox . TYPE4 ) as VisualSampleEntryBox ;
71+ if ( h264VisualSample != null )
7972 {
80- rtspVideoTrack = new SharpRTSPServer . H265Track ( ) ;
73+ var avcC = ( h264VisualSample . Children . First ( x => x . Type == AvcConfigurationBox . TYPE ) as AvcConfigurationBox ) . AvcDecoderConfigurationRecord ;
74+ rtspVideoTrack = new SharpRTSPServer . H264Track ( avcC . AvcProfileIndication , 0 , avcC . AvcLevelIndication ) ;
8175 _server . AddVideoTrack ( rtspVideoTrack ) ;
8276 }
8377 else
8478 {
85- throw new NotSupportedException ( "No supported video found!" ) ;
79+ var h265VisualSample = videoTrackBox . GetMdia ( ) . GetMinf ( ) . GetStbl ( ) . GetStsd ( ) . Children . FirstOrDefault ( x => x . Type == VisualSampleEntryBox . TYPE6 || x . Type == VisualSampleEntryBox . TYPE7 ) as VisualSampleEntryBox ;
80+ if ( h265VisualSample != null )
81+ {
82+ rtspVideoTrack = new SharpRTSPServer . H265Track ( ) ;
83+ _server . AddVideoTrack ( rtspVideoTrack ) ;
84+ }
85+ else
86+ {
87+ throw new NotSupportedException ( "No supported video found!" ) ;
88+ }
8689 }
8790 }
88- }
89-
90- if ( audioTrackBox != null )
91- {
92- audioTrackId = fmp4 . FindAudioTrackID ( ) . First ( ) ;
9391
94- var audioSampleEntry = audioTrackBox . GetAudioSampleEntryBox ( ) ;
95- if ( audioSampleEntry . Type == AudioSampleEntryBox . TYPE3 ) // AAC
92+ if ( audioTrackBox != null )
9693 {
97- var audioConfigDescriptor = audioSampleEntry . GetAudioSpecificConfigDescriptor ( ) ;
98- int audioSamplingRate = audioConfigDescriptor . GetSamplingFrequency ( ) ;
99- rtspAudioTrack = new SharpRTSPServer . AACTrack ( await audioConfigDescriptor . ToBytes ( ) , audioSamplingRate , audioConfigDescriptor . ChannelConfiguration ) ;
100- _server . AddAudioTrack ( rtspAudioTrack ) ;
101- }
102- else
103- {
104- // unsupported audio
94+ audioTrackId = fmp4 . FindAudioTrackID ( ) . First ( ) ;
95+
96+ var audioSampleEntry = audioTrackBox . GetAudioSampleEntryBox ( ) ;
97+ if ( audioSampleEntry . Type == AudioSampleEntryBox . TYPE3 ) // AAC
98+ {
99+ var audioConfigDescriptor = audioSampleEntry . GetAudioSpecificConfigDescriptor ( ) ;
100+ int audioSamplingRate = audioConfigDescriptor . GetSamplingFrequency ( ) ;
101+ rtspAudioTrack = new SharpRTSPServer . AACTrack ( await audioConfigDescriptor . ToBytes ( ) , audioSamplingRate , audioConfigDescriptor . ChannelConfiguration ) ;
102+ _server . AddAudioTrack ( rtspAudioTrack ) ;
103+ }
104+ else
105+ {
106+ // unsupported audio
107+ }
105108 }
106109 }
107110 }
108111 }
112+ else
113+ {
114+ parsedMDAT = new Dictionary < uint , IList < IList < byte [ ] > > > ( ) ;
115+ parsedMDAT . Add ( videoTrackId , new List < IList < byte [ ] > > ( ) ) ;
116+
117+ var jpgFiles = Directory . GetFiles ( fileName , "*.jpg" ) ;
118+ for ( int i = 0 ; i < jpgFiles . Length ; i ++ )
119+ {
120+ parsedMDAT [ videoTrackId ] . Add ( new List < byte [ ] > ( ) ) ;
121+ parsedMDAT [ videoTrackId ] [ i ] . Add ( File . ReadAllBytes ( jpgFiles [ i ] ) ) ;
122+ }
123+
124+ rtspVideoTrack = new SharpRTSPServer . MJpegTrack ( ) { Width = 1160 , Height = 768 } ;
125+ _server . AddVideoTrack ( rtspVideoTrack ) ;
126+
127+ videoFrameRate = 1 ;
128+ }
109129
110130 int videoIndex = 0 ;
111131 int audioIndex = 0 ;
112132 Timer audioTimer = null ;
113133 Timer videoTimer = null ;
114134
115- if ( videoTrackBox != null )
135+ if ( rtspVideoTrack != null )
116136 {
117137 var videoSamplingRate = SharpRTSPServer . H264Track . DEFAULT_CLOCK ;
118138 var videoSampleDuration = videoSamplingRate / videoFrameRate ;
@@ -125,12 +145,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
125145 if ( rtspVideoTrack is SharpRTSPServer . H264Track h264VideoTrack )
126146 {
127147 h264VideoTrack . SetParameterSets ( videoTrack [ 0 ] [ 0 ] , videoTrack [ 0 ] [ 1 ] ) ;
148+ videoIndex ++ ;
128149 }
129150 else if ( rtspVideoTrack is SharpRTSPServer . H265Track h265VideoTrack )
130151 {
131152 h265VideoTrack . SetParameterSets ( videoTrack [ 0 ] [ 0 ] , videoTrack [ 0 ] [ 1 ] , videoTrack [ 0 ] [ 2 ] ) ;
153+ videoIndex ++ ;
132154 }
133- videoIndex ++ ;
134155 }
135156
136157 rtspVideoTrack . FeedInRawSamples ( ( uint ) ( videoIndex * videoSampleDuration ) , ( List < byte [ ] > ) videoTrack [ videoIndex ++ % videoTrack . Count ] ) ;
@@ -142,7 +163,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
142163 } ;
143164 }
144165
145- if ( audioTrackBox != null )
166+ if ( rtspAudioTrack != null )
146167 {
147168 var audioSampleDuration = SharpMp4 . AACTrack . AAC_SAMPLE_SIZE ;
148169 var audioTrack = parsedMDAT [ audioTrackId ] ;
0 commit comments