Click here to Skip to main content
15,891,253 members
Articles / Desktop Programming / XAML

Play AVI files in Silverlight 5 using MediaElement and MediaStreamSource - P/Invoke

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
14 Sep 2011CPOL5 min read 40.4K   1.7K   5  
This code demostrates how to use Silverlight 5 with OOB+elevated trust to play a local video (.avi). Uses P/Invoke support for native code
Imports System.Windows.Media.Imaging
Imports System.ComponentModel
Imports System.IO

Partial Public Class MainPage
    Inherits UserControl

#Region "local Variable"

    ' Instantiate our derived MediaStreamSource class
    Dim _mediaSource As MyDerivedMediaStreamSource

    '<summary>
    '    Flag to indicate if our media has been opened or not
    '</summary>
    Dim mediaOpen As Boolean = False

    Dim _filename As String = "Video_File_Full_Path_Here.avi"

    ' <summary>
    '     Byte Array for a single frame (RGBA format)
    ' </summary>
    Private RGBA_Sample() As Byte '= New Byte(_count)

    ' <summary>
    '     Stream to contain a Sample
    ' </summary>
    Private _stream As New MemoryStream() '= New MemoryStream(_frameStreamSize)

    Private bw As BackgroundWorker '= New BackgroundWorker()

    Private b As WriteableBitmap

    Private avi As New cAVI()

    Private videoPlayBackSpeed As Int16

#End Region


    Public Sub New()

        InitializeComponent()

    End Sub

#Region "Play AVI using MediaStreamSource"

    Private Sub OpenStream_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles OpenStream.Click

        ' initialize our media stream object
        _mediaSource = New MyDerivedMediaStreamSource()

        ' check if we secceeded opening the AVI
        If _mediaSource.startVideo(_filename) Then

            ' set flag to true - media has been opened
            mediaOpen = True

            ' set the source of our media stream to the MediaElement
            mediaPlayer.SetSource(_mediaSource)

        End If


    End Sub

    Private Sub CloseStream_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles CloseStream.Click

        If mediaOpen Then ' check if we still have the media open


            _mediaSource.closeStream()

            _mediaSource = Nothing


            mediaPlayer.Source = Nothing

            mediaPlayer.Stop()

            mediaOpen = False

            MessageBox.Show("MediaElement Stopped")

        End If
    End Sub

#End Region

#Region "Play AVI using WriteableBitmap"


    Private Sub OpenStreamWB_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles OpenStreamWB.Click

        If avi.IsAVIOpen() Then
            'Throw an Exception
            Exit Sub
        End If

        avi.openVideo(_filename)

        ' Resize our final modified sample in Bytes
        ReDim RGBA_Sample(avi.frameSize - 1)


        b = New WriteableBitmap(avi.frameWidth, avi.frameHeight)


        '---------------------------------------------------------------------------

        bw = New BackgroundWorker()

        bw.RunWorkerAsync()

        bw.WorkerReportsProgress = True
        bw.WorkerSupportsCancellation = True

        AddHandler bw.DoWork, AddressOf bw_DoWork
        AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged
        AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted

        If Not bw.IsBusy = True Then
            bw.RunWorkerAsync()
        End If


        '---------------------------------------------------------------------------


        Slider1.IsEnabled = True

    End Sub

    Private Sub CloseStreamWB_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles CloseStreamWB.Click

        If avi.IsAVIOpen() Then
            If bw.WorkerSupportsCancellation = True Then
                bw.CancelAsync()

            End If

            avi.closeStream()
        End If
    End Sub

    Private Sub bw_DoWork(sender As Object, e As DoWorkEventArgs)
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)

        Do
            If worker.CancellationPending = True Then
                e.Cancel = True
                Exit Do
            End If

            ' retrieve a Video Sample
            avi.returnFrameBytes(RGBA_Sample)

            ' go back to the beginning of the stream
            _stream.Seek(0, SeekOrigin.Begin)

            ' write the retrieved Sample into the stream
            _stream.Write(RGBA_Sample, 0, avi.frameSize)

            System.Threading.Thread.Sleep(33)
            bw.ReportProgress(10)

        Loop

        bw = Nothing

    End Sub

    Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        If e.Cancelled = True Then
            MessageBox.Show("WriteableBitmap Stopped")
        End If
    End Sub


    Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)


        ' Generate the Sample into the WriteableBitmap
        ' I dont know if there is an easier and faster way to do it in Memory
        For i As Integer = 0 To RGBA_Sample.Length - 1 Step 4 ' step 4 bytes per pixel

            ' ---A---- ---R---- ---G---- ---B----
            ' 00000000 00000000 00000000 00000000 => makes 1 ARGB pixel
            ' 00000000 11111111 00000000 00000000 <= VAR << 16 for Red
            ' 00000000 00000000 11111111 00000000 <= VAR << 8 for Green
            ' 00000000 00000000 00000000 11111111 <= VAR for Red
            b.Pixels(i / 4) = _
                CType(RGBA_Sample(i + 2), Int32) << 16 Or _
                CType(RGBA_Sample(i + 1), Int32) << 8 Or _
                CType(RGBA_Sample(i + 0), Int32)


            ' You can try:
            ' Only RED
            'b.Pixels(i / 4) = CType(RGBA_Sample(i), Int32) << 16


            ' Only GREEN
            'b.Pixels(i / 4) = CType(RGBA_Sample(i), Int32) << 8


            ' Only BLUE
            'b.Pixels(i / 4) = CType(RGBA_Sample(i), Int32)

        Next

        'b.Invalidate()


        ' Assign the WriteableBitmap as the source for the Image
        MyBitmap.Source = b

        ' The Thumbnail sized Images.
        MyBitmap1.Source = b
        MyBitmap2.Source = b
        MyBitmap3.Source = b


    End Sub

#End Region

    Private Sub Slider1_ValueChanged(sender As System.Object, e As System.Windows.RoutedPropertyChangedEventArgs(Of System.Double)) Handles Slider1.ValueChanged
        avi.playSpeed = CType(sender, Slider).Value ' Adjust the playback speed on the video displayed on WriteableBitmap
    End Sub

End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Other Norconsult Telematics, KSA
Canada Canada
I have been a Developer for many years. I have worked as Senior Developer in Kenya, Canada and Saudi Arabia. I enjoy coding and I am looking forward to more challenges with new Technologies

I am currently IT Manager at Norconsult Telematics, Saudi Arabia.

Comments and Discussions