Transmisi media

Artikel ini menunjukkan kepada Anda cara mentransmisian media ke perangkat jarak jauh dari aplikasi Universal Windows.

Transmisi media bawaan dengan MediaPlayerElement

Cara paling sederhana untuk mentransmisikan media dari aplikasi Universal Windows adalah dengan menggunakan kemampuan transmisi bawaan kontrol MediaPlayerElement .

Untuk mengizinkan pengguna membuka file video untuk diputar di kontrol MediaPlayerElement , tambahkan namespace berikut ke proyek Anda.

using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.Media.Core;

Dalam file XAML aplikasi Anda, tambahkan MediaPlayerElement dan atur AreTransportControlsEnabled ke true.

<MediaPlayerElement Name="mediaPlayerElement"  MinHeight="100" MaxWidth="600" HorizontalAlignment="Stretch" AreTransportControlsEnabled="True"/>

Tambahkan tombol untuk memungkinkan pengguna memulai memilih file.

<Button x:Name="openButton" Click="openButton_Click" Content="Open"/>

Di tombol Klik penanganan aktivitas untuk tombol, buat instans baru FileOpenPicker, tambahkan jenis file video ke koleksi FileTypeFilter , dan atur lokasi awal ke pustaka video pengguna.

Panggil PickSingleFileAsync untuk meluncurkan dialog pemilih file. Ketika metode ini kembali, hasilnya adalah objek StorageFile yang mewakili file video. Periksa untuk memastikan file tidak null, yang akan menjadi jika pengguna membatalkan operasi pemilihan. Panggil metode OpenAsync file untuk mendapatkan IRandomAccessStream untuk file tersebut. Terakhir, buat objek MediaSource baru dari file yang dipilih dengan memanggil CreateFromStorageFile dan tetapkan ke properti Sumber objek MediaPlayerElement untuk menjadikan file video sebagai sumber video untuk kontrol.

private async void openButton_Click(object sender, RoutedEventArgs e)
{
    //Create a new picker
    FileOpenPicker filePicker = new FileOpenPicker();

    //Add filetype filters.  In this case wmv and mp4.
    filePicker.FileTypeFilter.Add(".wmv");
    filePicker.FileTypeFilter.Add(".mp4");

    //Set picker start location to the video library
    filePicker.SuggestedStartLocation = PickerLocationId.VideosLibrary;

    //Retrieve file from picker
    StorageFile file = await filePicker.PickSingleFileAsync();

    //If we got a file, load it into the media lement
    if (file != null)
    {
        mediaPlayerElement.Source = MediaSource.CreateFromStorageFile(file);
        mediaPlayerElement.MediaPlayer.Play();
    }
}

Setelah video dimuat di MediaPlayerElement, pengguna cukup menekan tombol transmisi pada kontrol transportasi untuk meluncurkan dialog bawaan yang memungkinkan mereka memilih perangkat tempat media yang dimuat akan dilemparkan.

tombol transmisi mediaelement

Catatan

Dimulai dengan Windows 10, versi 1607, disarankan agar Anda menggunakan kelas MediaPlayer untuk memutar item media. MediaPlayerElement adalah kontrol XAML ringan yang digunakan untuk merender konten MediaPlayer di halaman XAML. Kontrol MediaElement terus didukung untuk kompatibilitas mundur. Untuk informasi selengkapnya tentang menggunakan MediaPlayer dan MediaPlayerElement untuk memutar konten media, lihat Memutar audio dan video dengan MediaPlayer. Untuk informasi tentang menggunakan MediaSource dan API terkait untuk bekerja dengan konten media, lihat Item media, daftar putar, dan trek.

Transmisi media dengan CastingDevicePicker

Cara kedua untuk mentransmisian media ke perangkat adalah dengan menggunakan CastingDevicePicker. Untuk menggunakan kelas ini, sertakan namespace Windows.Media.Casting dalam proyek Anda.

using Windows.Media.Casting;

Nyatakan variabel anggota untuk objek CastingDevicePicker .

CastingDevicePicker castingPicker;

Saat halaman Anda diinisialisasi, buat instans baru pemilih transmisi dan atur properti Filter ke SupportsVideo untuk menunjukkan bahwa perangkat transmisi yang tercantum oleh pemilih harus mendukung video. Daftarkan handler untuk peristiwa CastingDeviceSelected , yang dinaikkan saat pengguna memilih perangkat untuk transmisi.

//Initialize our picker object
castingPicker = new CastingDevicePicker();

//Set the picker to filter to video capable casting devices
castingPicker.Filter.SupportsVideo = true;

//Hook up device selected event
castingPicker.CastingDeviceSelected += CastingPicker_CastingDeviceSelected;

Di file XAML Anda, tambahkan tombol untuk memungkinkan pengguna meluncurkan pemilih.

<Button x:Name="castPickerButton" Content="Cast Button" Click="castPickerButton_Click"/>

Di tombol Klik penanganan aktivitas untuk, panggil TransformToVisual untuk mendapatkan transformasi elemen UI yang relatif terhadap elemen lain. Dalam contoh ini, transformasi adalah posisi tombol pemilih cast relatif terhadap akar visual jendela aplikasi. Panggil metode Tampilkan objek CastingDevicePicker untuk meluncurkan dialog pemilih transmisi. Tentukan lokasi dan dimensi tombol pemilih cast sehingga sistem dapat membuat dialog terbang keluar dari tombol yang ditekan pengguna.

private void castPickerButton_Click(object sender, RoutedEventArgs e)
{
    //Retrieve the location of the casting button
    GeneralTransform transform = castPickerButton.TransformToVisual(Window.Current.Content as UIElement);
    Point pt = transform.TransformPoint(new Point(0, 0));

    //Show the picker above our casting button
    castingPicker.Show(new Rect(pt.X, pt.Y, castPickerButton.ActualWidth, castPickerButton.ActualHeight),
        Windows.UI.Popups.Placement.Above);
}

Di penanganan aktivitas CastingDeviceSelected , panggil metode CreateCastingConnection dari properti SelectedCastingDevice dari args peristiwa, yang mewakili perangkat transmisi yang dipilih oleh pengguna. Daftarkan handler untuk peristiwa ErrorOccurred dan StateChanged . Terakhir, panggil RequestStartCastingAsync untuk mulai mentransmisikan, meneruskan hasil ke metode GetAsCastingSource objek MediaPlayerElement kontrol MediaPlayer untuk menentukan bahwa media yang akan ditransmisikan adalah konten MediaPlayer yang terkait dengan MediaPlayerElement.

Catatan

Koneksi transmisi harus dimulai pada utas UI. Karena CastingDeviceSelected tidak dipanggil pada utas UI, Anda harus melakukan panggilan ini di dalam panggilan ke CoreDispatcher.RunAsync yang menyebabkan mereka dipanggil pada utas UI.

private async void CastingPicker_CastingDeviceSelected(CastingDevicePicker sender, CastingDeviceSelectedEventArgs args)
{
    //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
    {
        //Create a casting conneciton from our selected casting device
        CastingConnection connection = args.SelectedCastingDevice.CreateCastingConnection();

        //Hook up the casting events
        connection.ErrorOccurred += Connection_ErrorOccurred;
        connection.StateChanged += Connection_StateChanged;

        //Cast the content loaded in the media element to the selected casting device
        await connection.RequestStartCastingAsync(mediaPlayerElement.MediaPlayer.GetAsCastingSource());
    });
}

Dalam penanganan aktivitas ErrorOccurred dan StateChanged , Anda harus memperbarui UI Anda untuk memberi tahu pengguna tentang status transmisi saat ini. Peristiwa ini dibahas secara rinci di bagian berikut tentang membuat pemilih perangkat transmisi kustom.

private async void Connection_StateChanged(CastingConnection sender, object args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        ShowMessageToUser("Casting Connection State Changed: " + sender.State);
    });
}

private async void Connection_ErrorOccurred(CastingConnection sender, CastingConnectionErrorOccurredEventArgs args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        ShowMessageToUser("Casting Connection State Changed: " + sender.State);
    });
}

Transmisi media dengan pemilih perangkat kustom

Bagian berikut menjelaskan cara membuat UI pemilih perangkat transmisi Anda sendiri dengan menghitung perangkat transmisi dan memulai koneksi dari kode Anda.

Untuk menghitung perangkat transmisi yang tersedia, sertakan namespace Layanan Windows.Devices.Enumeration dalam proyek Anda.

using Windows.Devices.Enumeration;

Tambahkan kontrol berikut ke halaman XAML Anda untuk mengimplementasikan UI yang belum biasa untuk contoh ini:

  • Tombol untuk memulai pengamat perangkat yang mencari perangkat transmisi yang tersedia.
  • Kontrol ProgressRing untuk memberikan umpan balik kepada pengguna bahwa enumerasi transmisi sedang berlangsung.
  • ListBox untuk mencantumkan perangkat transmisi yang ditemukan. Tentukan ItemTemplate untuk kontrol sehingga kita dapat menetapkan objek perangkat transmisi langsung ke kontrol dan masih menampilkan properti FriendlyName .
  • Tombol untuk memungkinkan pengguna memutuskan sambungan perangkat transmisi.
<Button x:Name="startWatcherButton" Content="Watcher Button" Click="startWatcherButton_Click"/>
<ProgressRing x:Name="watcherProgressRing" IsActive="False"/>
<ListBox x:Name="castingDevicesListBox" MaxWidth="300" HorizontalAlignment="Left" SelectionChanged="castingDevicesListBox_SelectionChanged">
    <!--Listbox content is bound to the FriendlyName field of our casting devices-->
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=FriendlyName}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<Button x:Name="disconnectButton" Content="Disconnect" Click="disconnectButton_Click" Visibility="Collapsed"/>

Dalam kode Anda di belakang, deklarasikan variabel anggota untuk DeviceWatcher dan CastingConnection.

DeviceWatcher deviceWatcher;
CastingConnection castingConnection;

Di handler Klik untuk startWatcherButton, pertama-tama perbarui UI dengan menonaktifkan tombol dan membuat cincin kemajuan aktif saat enumerasi perangkat sedang berlangsung. Kosongkan kotak daftar perangkat transmisi.

Selanjutnya, buat pengamat perangkat dengan memanggil DeviceInformation.CreateWatcher. Metode ini dapat digunakan untuk watch untuk berbagai jenis perangkat. Tentukan bahwa Anda ingin watch untuk perangkat yang mendukung transmisi video dengan menggunakan string pemilih perangkat yang dikembalikan oleh CastingDevice.GetDeviceSelector.

Terakhir, daftarkan penanganan aktivitas untuk peristiwa Ditambahkan, Dihapus, EnumerasiKomleted, dan Dihentikan .

private void startWatcherButton_Click(object sender, RoutedEventArgs e)
{
    startWatcherButton.IsEnabled = false;
    watcherProgressRing.IsActive = true;

    castingDevicesListBox.Items.Clear();

    //Create our watcher and have it find casting devices capable of video casting
    deviceWatcher = DeviceInformation.CreateWatcher(CastingDevice.GetDeviceSelector(CastingPlaybackTypes.Video));

    //Register for watcher events
    deviceWatcher.Added += DeviceWatcher_Added;
    deviceWatcher.Removed += DeviceWatcher_Removed;
    deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
    deviceWatcher.Stopped += DeviceWatcher_Stopped;

    //Start the watcher
    deviceWatcher.Start();
}

Peristiwa Ditambahkan dinaikkan saat perangkat baru ditemukan oleh pengamat. Dalam handler untuk peristiwa ini, buat objek CastingDevice baru dengan memanggil CastingDevice.FromIdAsync dan meneruskan ID perangkat casting yang ditemukan, yang terkandung dalam objek DeviceInformation yang diteruskan ke handler.

Tambahkan CastingDevice ke ListBox perangkat transmisi sehingga pengguna dapat memilihnya. Karena ItemTemplate yang ditentukan dalam XAML, properti FriendlyName akan digunakan sebagai teks item untuk dalam kotak daftar. Karena penanganan aktivitas ini tidak dipanggil pada utas UI, Anda harus memperbarui UI dari dalam panggilan ke CoreDispatcher.RunAsync.

private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
    {
        //Add each discovered device to our listbox
        CastingDevice addedDevice = await CastingDevice.FromIdAsync(args.Id);
        castingDevicesListBox.Items.Add(addedDevice);
    });
}

Peristiwa Dihapus dinaikkan saat pengamat mendeteksi bahwa perangkat transmisi tidak lagi ada. Bandingkan properti ID dari objek Ditambahkan yang diteruskan ke handler dengan ID setiap Ditambahkan dalam kumpulan Item kotak daftar. Jika ID cocok, hapus objek tersebut dari koleksi. Sekali lagi, karena UI sedang diperbarui, panggilan ini harus dilakukan dari dalam panggilan RunAsync .

private async void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        foreach (CastingDevice currentDevice in castingDevicesListBox.Items)
        {
            if (currentDevice.Id == args.Id)
            {
                castingDevicesListBox.Items.Remove(currentDevice);
            }
        }
    });
}

Peristiwa EnumerationCompleted dinaikkan ketika pengamat selesai mendeteksi perangkat. Di handler untuk peristiwa ini, perbarui UI untuk memberi tahu pengguna bahwa enumerasi perangkat telah selesai dan hentikan pengamat perangkat dengan memanggil Hentikan.

private async void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        //If enumeration completes, update UI and transition watcher to the stopped state
        ShowMessageToUser("Watcher completed enumeration of devices");
        deviceWatcher.Stop();
    });
}

Peristiwa Dihentikan dinaikkan ketika pengamat perangkat selesai berhenti. Di handler untuk peristiwa ini, hentikan kontrol ProgressRing dan aktifkan kembali startWatcherButton sehingga pengguna dapat memulai ulang proses enumerasi perangkat.

private async void DeviceWatcher_Stopped(DeviceWatcher sender, object args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        //Update UX when the watcher stops
        startWatcherButton.IsEnabled = true;
        watcherProgressRing.IsActive = false;
    });
}

Saat pengguna memilih salah satu perangkat transmisi dari kotak daftar, peristiwa SelectionChanged dinaikkan . Dalam handler inilah koneksi transmisi akan dibuat dan transmisi akan dimulai.

Pertama, pastikan pengamat perangkat dihentikan sehingga enumerasi perangkat tidak mengganggu transmisi media. Buat koneksi transmisi dengan memanggil CreateCastingConnection pada objek CastingDevice yang dipilih oleh pengguna. Tambahkan penanganan aktivitas untuk peristiwa StateChanged dan ErrorOccurred .

Mulai transmisi media dengan memanggil RequestStartCastingAsync, melewati sumber transmisi yang dikembalikan dengan memanggil metode MediaPlayerGetAsCastingSource. Terakhir, buat tombol putuskan sambungan terlihat untuk memungkinkan pengguna menghentikan transmisi media.

private async void castingDevicesListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (castingDevicesListBox.SelectedItem != null)
    {
        //When a device is selected, first thing we do is stop the watcher so it's search doesn't conflict with streaming
        if (deviceWatcher.Status != DeviceWatcherStatus.Stopped)
        {
            deviceWatcher.Stop();
        }

        //Create a new casting connection to the device that's been selected
        castingConnection = ((CastingDevice)castingDevicesListBox.SelectedItem).CreateCastingConnection();

        //Register for events
        castingConnection.ErrorOccurred += Connection_ErrorOccurred;
        castingConnection.StateChanged += Connection_StateChanged;

        //Cast the loaded video to the selected casting device.
        await castingConnection.RequestStartCastingAsync(mediaPlayerElement.MediaPlayer.GetAsCastingSource());
        disconnectButton.Visibility = Visibility.Visible;
    }
}

Dalam penangan yang diubah status, tindakan yang Anda ambil tergantung pada status baru koneksi transmisi:

  • Jika status Tersambung atau Penyajian, pastikan kontrol ProgressRing tidak aktif dan tombol putuskan sambungan terlihat.
  • Jika status Terputus, batal pilih perangkat transmisi saat ini dalam kotak daftar, buat kontrol ProgressRing tidak aktif, dan sembunyikan tombol putuskan sambungan.
  • Jika statusnya Tersambung, buat kontrol ProgressRing aktif dan sembunyikan tombol putuskan sambungan.
  • Jika status Terputus, buat kontrol ProgressRing aktif dan sembunyikan tombol putuskan sambungan.
private async void Connection_StateChanged(CastingConnection sender, object args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        //Update the UX based on the casting state
        if (sender.State == CastingConnectionState.Connected || sender.State == CastingConnectionState.Rendering)
        {
            disconnectButton.Visibility = Visibility.Visible;
            watcherProgressRing.IsActive = false;
        }
        else if (sender.State == CastingConnectionState.Disconnected)
        {
            disconnectButton.Visibility = Visibility.Collapsed;
            castingDevicesListBox.SelectedItem = null;
            watcherProgressRing.IsActive = false;
        }
        else if (sender.State == CastingConnectionState.Connecting)
        {
            disconnectButton.Visibility = Visibility.Collapsed;
            ShowMessageToUser("Connecting");
            watcherProgressRing.IsActive = true;
        }
        else
        {
            //Disconnecting is the remaining state
            disconnectButton.Visibility = Visibility.Collapsed;
            watcherProgressRing.IsActive = true;
        }
    });
}

Di handler untuk peristiwa ErrorOccurred , perbarui UI Anda untuk memberi tahu pengguna bahwa kesalahan transmisi terjadi dan batal pilih objek CastingDevice saat ini di kotak daftar.

private async void Connection_ErrorOccurred(CastingConnection sender, CastingConnectionErrorOccurredEventArgs args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        //Clear the selection in the listbox on an error
        ShowMessageToUser("Casting Error: " + args.Message);
        castingDevicesListBox.SelectedItem = null;
    });
}

Terakhir, terapkan handler untuk tombol putuskan sambungan. Hentikan transmisi media dan putuskan sambungan dari perangkat transmisi dengan memanggil metode DisconnectAsync objek CastingConnection. Panggilan ini harus dikirim ke utas UI dengan memanggil CoreDispatcher.RunAsync.

private async void disconnectButton_Click(object sender, RoutedEventArgs e)
{
    if (castingConnection != null)
    {
        //When disconnect is clicked, the casting conneciton is disconnected.  The video should return locally to the media element.
        await castingConnection.DisconnectAsync();
    }
}