wpf 推送h264、h265视频,并显示视频
时间: 2023-08-15 15:48:20 浏览: 252
在 WPF 中推送 H264 或 H265 视频并显示,你可以使用 MediaElement 控件和 FFmpeg 库。
具体步骤如下:
1. 下载 FFmpeg 库。你可以从官网(https://ffmpeg.org/download.html)下载最新版本的 FFmpeg 库。
2. 将 FFmpeg 库中的 `ffmpeg.dll`、`avcodec-XX.dll`、`avformat-XX.dll`、`avutil-XX.dll`、`swscale-XX.dll` 文件复制到你的项目中,并设置这些文件的“复制到输出目录”属性为“始终复制”。
3. 在代码中使用 FFmpeg 库来读取 H264 或 H265 视频文件,并将视频帧渲染到 WPF 界面中的 Image 控件中。
以下是示例代码:
```xaml
<Grid>
<Image x:Name="image" Width="640" Height="480" />
</Grid>
```
```csharp
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using FFmpeg.AutoGen;
namespace WpfApp
{
public partial class MainWindow : Window
{
private AVFormatContext* _formatContext;
private AVCodecContext* _codecContext;
private AVFrame* _frame;
private AVFrame* _frameRgb;
private SwsContext* _imgConvertContext;
private IntPtr _buffer;
private Bitmap _bitmap;
private readonly object _lock = new object();
private bool _isPlaying;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ffmpeg.av_register_all();
ffmpeg.avcodec_register_all();
string path = @"C:\path\to\your\h264\video.mp4";
AVDictionary* options = null;
ffmpeg.av_dict_set(&options, "rtsp_transport", "tcp", 0);
ffmpeg.av_dict_set(&options, "stimeout", "5000000", 0);
int errorCode = ffmpeg.avformat_open_input(&_formatContext, path, null, &options);
if (errorCode < 0)
{
MessageBox.Show($"Could not open input file: {errorCode}");
return;
}
errorCode = ffmpeg.avformat_find_stream_info(_formatContext, null);
if (errorCode < 0)
{
MessageBox.Show($"Could not find stream information: {errorCode}");
return;
}
AVCodec* codec = null;
int streamIndex = ffmpeg.av_find_best_stream(_formatContext, AVMediaType.AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);
if (streamIndex < 0)
{
MessageBox.Show($"Could not find video stream: {streamIndex}");
return;
}
_codecContext = ffmpeg.avcodec_alloc_context3(codec);
if (_codecContext == null)
{
MessageBox.Show("Could not allocate codec context");
return;
}
errorCode = ffmpeg.avcodec_parameters_to_context(_codecContext, _formatContext->streams[streamIndex]->codecpar);
if (errorCode < 0)
{
MessageBox.Show($"Could not copy codec parameters: {errorCode}");
return;
}
errorCode = ffmpeg.avcodec_open2(_codecContext, codec, null);
if (errorCode < 0)
{
MessageBox.Show($"Could not open codec: {errorCode}");
return;
}
_frame = ffmpeg.av_frame_alloc();
_frameRgb = ffmpeg.av_frame_alloc();
int bufferLength = ffmpeg.av_image_get_buffer_size(AVPixelFormat.AV_PIX_FMT_BGR24, _codecContext->width, _codecContext->height, 1);
_buffer = Marshal.AllocHGlobal(bufferLength);
ffmpeg.av_image_fill_arrays(_frameRgb->data, _frameRgb->linesize, (byte*)_buffer, AVPixelFormat.AV_PIX_FMT_BGR24, _codecContext->width, _codecContext->height, 1);
_imgConvertContext = ffmpeg.sws_getContext(_codecContext->width, _codecContext->height, _codecContext->pix_fmt, _codecContext->width, _codecContext->height, AVPixelFormat.AV_PIX_FMT_BGR24, ffmpeg.SWS_BICUBIC, null, null, null);
_bitmap = new Bitmap(_codecContext->width, _codecContext->height, _frameRgb->linesize[0], System.Drawing.Imaging.PixelFormat.Format24bppRgb, _buffer);
_isPlaying = true;
_ = ReadFramesAsync();
}
private async Task ReadFramesAsync()
{
AVPacket packet;
ffmpeg.av_init_packet(&packet);
while (_isPlaying && ffmpeg.av_read_frame(_formatContext, &packet) == 0)
{
if (packet.stream_index == _codecContext->stream_index)
{
int errorCode = ffmpeg.avcodec_send_packet(_codecContext, &packet);
if (errorCode < 0)
{
MessageBox.Show($"Error sending packet to decoder: {errorCode}");
break;
}
while (true)
{
errorCode = ffmpeg.avcodec_receive_frame(_codecContext, _frame);
if (errorCode == ffmpeg.AVERROR(ffmpeg.EAGAIN) || errorCode == ffmpeg.AVERROR_EOF)
{
break;
}
else if (errorCode < 0)
{
MessageBox.Show($"Error receiving frame from decoder: {errorCode}");
return;
}
ffmpeg.sws_scale(_imgConvertContext, _frame->data, _frame->linesize, 0, _codecContext->height, _frameRgb->data, _frameRgb->linesize);
lock (_lock)
{
_bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(_bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
image.Source = bitmapSource;
}
await Task.Delay(1);
}
}
ffmpeg.av_packet_unref(&packet);
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
_isPlaying = false;
Marshal.FreeHGlobal(_buffer);
ffmpeg.sws_freeContext(_imgConvertContext);
ffmpeg.av_frame_free(&_frame);
ffmpeg.av_frame_free(&_frameRgb);
ffmpeg.avcodec_close(_codecContext);
ffmpeg.avcodec_free_context(&_codecContext);
ffmpeg.avformat_close_input(&_formatContext);
ffmpeg.avformat_free_context(_formatContext);
}
}
}
```
请注意,这只是一个简单的示例,实际应用中可能需要根据视频文件的具体情况进行更复杂的处理。
阅读全文