Когда мы соединяем модули воспроизведения RTMP и RTSP на платформе Windows, некоторым разработчикам необходимо вызывать их под WPF. Если вы хотите использовать их под WPF, вам нужно только обратиться к демонстрации стыковки C#. Единственная разница заключается в том, что. данные видеопотока отображаются либо через режим управления, либо вы можете позволить модулям воспроизведения RTMP и RTSP вызывать данные RGB и рисовать их непосредственно в wpf.
В этой статье в качестве примера используется платформа Windows SmartPlayer из Daniu Live SDK. Режим данных обратного вызова не будет объяснен, пока обрабатываются входящие данные:
Перед воспроизведением установите обратный вызов и выберите NT_SP_E_VIDEO_FRAME_FORMAT_RGB32:
video_frame_call_back_ = new SP_SDKVideoFrameCallBack(SetVideoFrameCallBack);
NTSmartPlayerSDK.NT_SP_SetVideoFrameCallBack(player_handle_, (Int32)NT.NTSmartPlayerDefine.NT_SP_E_VIDEO_FRAME_FORMAT.NT_SP_E_VIDEO_FRAME_FORMAT_RGB32, IntPtr.Zero, video_frame_call_back_);
Обработка обратного вызова данных RGB:
/*
* nt_player_wrapper.cs
* Author: daniusdk.com
*/
public void SetVideoFrameCallBack(IntPtr handle, IntPtr userData, UInt32 status, IntPtr frame)
{
if (frame == IntPtr.Zero)
{
return;
}
//Если вам нужно обработать данные RGB напрямую, обратитесь к следующему процессу
NT_SP_VideoFrame video_frame = (NT_SP_VideoFrame)Marshal.PtrToStructure(frame, typeof(NT_SP_VideoFrame));
if (video_frame.format_ != (Int32)NT.NTSmartPlayerDefine.NT_SP_E_VIDEO_FRAME_FORMAT.NT_SP_E_VIDEO_FRAME_FORMAT_RGB32)
return;
NT_SP_VideoFrame pVideoFrame = new NT_SP_VideoFrame();
pVideoFrame.format_ = video_frame.format_;
pVideoFrame.width_ = video_frame.width_;
pVideoFrame.height_ = video_frame.height_;
pVideoFrame.timestamp_ = video_frame.timestamp_;
pVideoFrame.stride0_ = video_frame.stride0_;
pVideoFrame.stride1_ = video_frame.stride1_;
pVideoFrame.stride2_ = video_frame.stride2_;
pVideoFrame.stride3_ = video_frame.stride3_;
Int32 argb_size = video_frame.stride0_ * video_frame.height_;
pVideoFrame.plane0_ = Marshal.AllocHGlobal(argb_size);
CopyMemory(pVideoFrame.plane0_, video_frame.plane0_, (UInt32)argb_size);
}
Другой способ — использовать PictureBox и выполнить следующие настройки в MainWindow.xaml:
<WindowsFormsHost HorizontalAlignment="Left" Height="338" Margin="10,10,0,0" VerticalAlignment="Top" Width="480" Background="Black">
<wf:PictureBox x:Name="RealPlayWnd"></wf:PictureBox>
</WindowsFormsHost>
Чтобы облегчить интеграцию нескольких экземпляров, в качестве примера возьмем 2 канала воспроизведения (один канал 2560*1440, один канал 1920*1080):
Конкретная реализация выглядит следующим образом:
/*
* MainWindow.xaml.cs
* Author: daniusdk.com
*/
public MainWindow()
{
InitializeComponent();
if (!InitSDK())
return;
UIDispatcher = Dispatcher.CurrentDispatcher;
player1_ = new nt_player_wrapper(RealPlayWnd, UIDispatcher);
player1_.EventGetPlayerEventMsg += new DelGetPlayerEventMsg(GetPlayerEventMsgInfo);
player1_.EventGetVideoSize += new DelGetVideoSize(GetVideoSize);
player2_ = new nt_player_wrapper(RealPlayWnd1, UIDispatcher);
player2_.EventGetPlayerEventMsg += new DelGetPlayerEventMsg(GetPlayerEventMsgInfo);
player2_.EventGetVideoSize += new DelGetVideoSize(GetVideoSize);
}
private void GetPlayerEventMsgInfo(IntPtr handle, String msg)
{
this.Dispatcher.Invoke((Action)delegate()
{
event_label.Content = msg;
});
}
private void GetVideoSize(IntPtr handle, String size)
{
this.Dispatcher.Invoke((Action)delegate()
{
video_size.Content = size;
});
}
private bool InitSDK()
{
if (!is_player_sdk_init_)
{
UInt32 isPlayerInited = NT.NTSmartPlayerSDK.NT_SP_Init(0, IntPtr.Zero);
if (isPlayerInited != 0)
{
MessageBox.Show("Ошибка вызова NT_SP_Init..");
return false;
}
is_player_sdk_init_ = true;
}
return true;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (!player1_.IsPlaying())
{
player1_.SetBuffer(0);
bool is_mute = true;
if (!player1_.StartPlay("rtsp://admin:daniulive12345@192.168.0.120:554/h264/ch1/main/av_stream", false, is_mute))
return;
btn_playback1.Content = «Хватит играть»;
}
else
{
player1_.StopPlay();
btn_playback1.Content = «Начать играть»;
}
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
if (!player2_.IsPlaying())
{
player2_.SetBuffer(0);
bool is_mute = true;
if (!player2_.StartPlay("rtsp://admin:admin123456@192.168.0.121:554/cam/realmonitor?channel=1&subtype=0", false, is_mute))
return;
btn_playback2.Content = «Хватит играть»;
}
else
{
player2_.StopPlay();
btn_playback2.Content = «Начать играть»;
}
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (MessageBox.Show("Вы уверены, что хотите закрыть окно?", "подтверждать", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
{
// Если пользователь выбирает «Нет», отмените закрытие
e.Cancel = true;
}
if (player1_.IsPlaying())
{
player1_.StopPlay();
}
player1_.Dispose();
if (player2_.IsPlaying())
{
player2_.StopPlay();
}
player2_.Dispose();
if (is_player_sdk_init_)
{
NTSmartPlayerSDK.NT_SP_UnInit();
is_player_sdk_init_ = false;
}
base.OnClosing(e);
}
Задержка по-прежнему находится на уровне миллисекунд, а загрузка ЦП следующая. Если вы используете жесткое декодирование, качество будет лучше:
В качестве примера SmartPlayer использует кроссплатформенный RTSP-плеер. Мы реализуем следующие функции. Если не указано иное, они поддерживаются всеми платформами Windows, Linux, Android и iOS:
Если вам нужно воспроизведение WPF на платформе Windows и вам нужно быть более гибким, вы можете использовать режим данных обратного вызова RGB. Верхний уровень рисует напрямую и воспроизводит изображение с низкой задержкой. Вы также можете использовать вышеуказанный режим управления. Помимо WPF мы предоставляем C++ и C#. Заинтересованные разработчики могут попробовать интерфейс и демо. Если у вас есть вопросы, вы можете связаться со мной индивидуально.