@@ -274,17 +274,17 @@ protected virtual async partial ValueTask PlatformUpdateSource()
274274 {
275275 // Create a custom URL scheme for the stream
276276 var streamUrl = new NSUrl ( "stream://media" ) ;
277-
277+
278278 // Create an AVURLAsset with the custom scheme
279279 var urlAsset = new AVUrlAsset ( streamUrl ) ;
280-
280+
281281 // Create and set up the resource loader
282282 streamResourceLoader ? . Dispose ( ) ;
283283 streamResourceLoader = new StreamAssetResourceLoader ( streamMediaSource . Stream , GetStreamContentType ( streamMediaSource . Stream ) ) ;
284-
284+
285285 // Assign the resource loader delegate
286286 urlAsset . ResourceLoader . SetDelegate ( streamResourceLoader , DispatchQueue . MainQueue ) ;
287-
287+
288288 asset = urlAsset ;
289289 }
290290 }
@@ -491,12 +491,44 @@ protected virtual void Dispose(bool disposing)
491491
492492 static string GetStreamContentType ( Stream stream )
493493 {
494- // Default to a generic media type
495- // In a more sophisticated implementation, you could:
496- // 1. Read magic bytes from the stream to detect type
497- // 2. Accept content type as a parameter on StreamMediaSource
498- // 3. Use file extension if available
499- return "video/mp4" ; // Default assumption
494+ // Try to detect content type from magic bytes
495+ if ( stream . CanSeek && stream . Length > 12 )
496+ {
497+ var originalPosition = stream . Position ;
498+ try
499+ {
500+ stream . Position = 0 ;
501+ var buffer = new byte [ 12 ] ;
502+ var bytesRead = stream . Read ( buffer , 0 , 12 ) ;
503+
504+ if ( bytesRead >= 12 )
505+ {
506+ // Check for MP4/M4V/MOV signature (ftyp box at offset 4)
507+ if ( buffer [ 4 ] == 0x66 && buffer [ 5 ] == 0x74 && buffer [ 6 ] == 0x79 && buffer [ 7 ] == 0x70 )
508+ {
509+ // Check specific brand
510+ var brand = System . Text . Encoding . ASCII . GetString ( buffer , 8 , 4 ) ;
511+
512+ // Most iOS videos will be either mp4, m4v, or qt (QuickTime)
513+ // For AVFoundation, we should use UTI: "public.mpeg-4" or "com.apple.quicktime-movie"
514+ if ( brand . StartsWith ( "qt" , StringComparison . Ordinal ) )
515+ {
516+ return "com.apple.quicktime-movie" ;
517+ }
518+
519+ return "public.mpeg-4" ;
520+ }
521+ }
522+ }
523+ finally
524+ {
525+ stream . Position = originalPosition ;
526+ }
527+ }
528+
529+ // Default to MPEG-4 (MP4) - covers most cases
530+ // Using UTI format for iOS/macOS
531+ return "public.mpeg-4" ;
500532 }
501533
502534 static TimeSpan ConvertTime ( CMTime cmTime ) => TimeSpan . FromSeconds ( double . IsNaN ( cmTime . Seconds ) ? 0 : cmTime . Seconds ) ;
@@ -763,4 +795,4 @@ void RateChanged(object? sender, NSNotificationEventArgs args)
763795 }
764796 }
765797 }
766- }
798+ }
0 commit comments