Search code examples
androidiosxamarinwindows-phonemjpeg

Xamarin multiplatform - Video from jpeg sequence


I want to know how I can display video from jpegs in Xamarin (all platforms).

My jpegs are being streamed from a http client stream sent by a popular video surveillance management software.

My jpegs are in the form of byte[] and I get about 10 jpegs/second. This format is imposed.

I tried rapidly changing the Source on a Image but it results in severe fliquering on Android. This seems to work on Windows phone but not so good performance.

How can I create a videoplayer for each one? Unless I am wrond, the existing components cannot do this.

Best,


Solution

  • Thank you Jason! Works great, very fluid rendering!!

    Simply add the SkiaSharp.Views.Forms with NuGet to the project and voila!

    Here is what that would look like in code (shared project):

    // Content page initialization
    private void InitUI() {
    
        Title = "Xamavideo";
    
        var button = new Button
        {
            Text = "Connect!"
        };
        Label label = new Label
        {
            Text = ""
        };
    
        var scroll = new ScrollView();
        scroll.BackgroundColor = Color.Black;
        Content = scroll;
        var stack = new StackLayout
        {
            Padding = 40,
            Spacing = 10
        };
    
        //Add a SKCanvasView item to the stack
        var videoCanvas = new SKCanvasView
        {                
            HeightRequest = 400,
            WidthRequest = 600,                
        };
        videoCanvas.PaintSurface += OnCanvasViewPaintSurface;
        stack.Children.Add(videoCanvas);
    }
    
    //Create the event handler
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;            
    
        // using (var stream = new SKManagedStream(fileStream))
        if (lastFrame == null) return;
        using (var canvas = surface.Canvas)
        // use KBitmap.Decode to decode the byte[] in jpeg format 
        using (var bitmap = SKBitmap.Decode(lastFrame))
        using (var paint = new SKPaint())
        {
            // clear the canvas / fill with black
            canvas.DrawColor(SKColors.Black);
            canvas.DrawBitmap(bitmap, SKRect.Create(640, 480), paint);
        }
    }
    
    void UpdateFrame(VideoClient client){
    
       //Use this to update the canvas:
       byte[] lastFrame = client.imageBytes;
       videoCanvas.InvalidateSurface();                                   
    }