大家下午好。我正在尝试从 WPF 控件渲染的图像实现 rtsp 广播。我能够将图像保存在文件夹中,因此它们是正确的。我使用 VLC 进行流媒体播放。 我制作了自己的 Stream 实现,其中使用 BlockingCollection 来存储帧。调用 Read 方法时,我从集合中取出一帧并将其复制到缓冲区。 当我尝试通过 VLC 播放器连接到广播时,收到错误“此源未打开” 我真的不明白问题出在哪里。我希望得到你的帮助。 预先感谢)
主课
using LibVLCSharp.Shared;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using MediaPlayer = LibVLCSharp.Shared.MediaPlayer;
namespace Presenter.Infrastructure.Services
{
public class LANViewerService : IViewerService
{
private static LANViewerService instance;
Task produceTask;
private bool play;
private MediaPlayer player;
public Visual? PresentationField { get; set; }
public event EventHandler PresentationEnded;
public event EventHandler PresentationStarted;
private LANViewerService() { }
public static IViewerService GetViewerService() => instance ??= new LANViewerService();
public void EndPresentation()
{
play = false;
player.Stop();
PresentationEnded?.Invoke(this, EventArgs.Empty);
}
public void StartPresentation()
{
Core.Initialize();
var libvlc = new LibVLC();
libvlc.Log += Libvlc_Log;
player = new MediaPlayer(libvlc);
player.Play();
PresentationStarted?.Invoke(this, EventArgs.Empty);
VideoStream videoStream = new VideoStream();
var media = new Media(libvlc, new StreamMediaInput(videoStream));
media.AddOption(":no-audio");
media.AddOption(":sout=#transcode{vcodec=h264,fps=10,vb=1024,acodec=none}");
media.AddOption(":sout=#rtp{sdp=rtsp://127.0.0.1:8008/test}");
media.AddOption(":sout-keep");
player.Media = media;
player.Play();
produceTask = new Task(() =>
{
while (play)
{
if (PresentationField == null)
continue;
RenderTargetBitmap bitmap = null;
Application.Current.Dispatcher.Invoke(() =>
{
JpegBitmapEncoder encoder = new();
bitmap = ConvertToBitmapSource(PresentationField);
encoder.Frames.Add(BitmapFrame.Create(bitmap));
MemoryStream stream = new MemoryStream();
encoder.Save(stream);
videoStream.Write(stream.ToArray());
});
Thread.Sleep(30);
}
});
play = true;
produceTask.Start();
}
private void Libvlc_Log(object? sender, LogEventArgs e)
{
Debug.WriteLine(e.Module + " " + e.Message);
}
public RenderTargetBitmap ConvertToBitmapSource(Visual element)
{
var target = new RenderTargetBitmap(1920, 1080, 96, 96, PixelFormats.Default);
target.Render(element);
return target;
}
直播课程
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
namespace Presenter.Infrastructure
{
public class VideoStream : Stream, IDisposable
{
BlockingCollection<byte[]> frames;
IEnumerator<byte[]> enumerator;
private bool _disposed;
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => true;
public override long Length => int.MaxValue;
public override long Position { get; set; } = 0;
public VideoStream()
{
frames = new();
enumerator = frames.GetConsumingEnumerable().GetEnumerator();
}
public override int Read(byte[] buffer, int offset, int count)
{
byte[] frame = frames.Take();
int readed = frame.Length < count ? frame.Length : count;
Array.Copy(frame, 0, buffer, offset, readed);
return readed;
}
public override int Read(Span<byte> buffer)
{
byte[] frame = frames.Take();
frame.CopyTo(buffer);
return frame.Length;
}
public void Write(byte[] frame)
{
frames.Add(frame);
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new InvalidOperationException();
}
public override void SetLength(long value)
{
throw new InvalidOperationException();
}
public override void Write(byte[] buffer, int offset, int count)
{
}
public override void Flush()
{
throw new InvalidOperationException();
}
void IDisposable.Dispose()
{
if (_disposed)
return;
enumerator.Dispose();
_disposed = true;
}
}
}
调试日志
main creating audio output
mmdevice cannot initialize COM (error 0x80010106)
main looking for audio output module matching "any": 6 candidates
main revision 3.0.18-0-ge9eceaed4d
main configured with /builds/videolan/vlc/extras/package/win32/../../../configure '--enable-update-check' '--enable-lua' '--enable-faad' '--enable-flac' '--enable-theora' '--enable-avcodec' '--enable-merge-ffmpeg' '--enable-dca' '--enable-mpc' '--enable-libass' '--enable-schroedinger' '--enable-realrtsp' '--enable-live555' '--enable-shout' '--enable-goom' '--enable-sse' '--enable-mmx' '--enable-libcddb' '--enable-zvbi' '--disable-telx' '--enable-nls' '--host=x86_64-w64-mingw32' '--with-contrib=../contrib/x86_64-w64-mingw32' '--with-breakpad=https://win.crashes.videolan.org' '--enable-qt' '--enable-skins2' '--enable-dvdread' '--enable-caca' 'host_alias=x86_64-w64-mingw32' 'CFLAGS= ' 'CXXFLAGS= ' 'PKG_CONFIG=pkg-config' 'PKG_CONFIG_LIBDIR=/usr/x86_64-w64-mingw32/lib/pkgconfig:/usr/lib/x86_64-w64-mingw32/pkgconfig'
main using audio output module "directsound"
directsound found 3 devices
main keeping audio output
main Copyright © 1996-2022 the VideoLAN team
main VLC media player - 3.0.18 Vetinari
main Creating an input for 'imem://'
main using sout chain=`rtp{sdp=rtsp://127.0.0.1:8008/test}'
main looking for sout stream module matching "rtp": 23 candidates
main set config option: sout-rtp-sdp to rtsp://127.0.0.1:8008/test
stream_out_rtp Consider passing --rtsp-host=IP on the command line instead.
main using timeshift granularity of 50 MiB
main `imem://' gives access `imem' demux `any' path `'
stream_out_rtp RTSP stream at /test
main net: listening to 127.0.0.1 port 8008
main no access_demux modules matched
main looking for access_demux module matching "imem": 15 candidates
prefetch using 16777216 bytes buffer, 16777216 bytes read
main using stream_filter module "prefetch"
main creating access: imem://
main using access module "imem_access"
main using timeshift path: C:\Users\Konstant\AppData\Local\Temp
main using sout stream module "stream_out_rtp"
main creating demux: access='imem' demux='any' location='' file='(null)'
main stream=`rtp'
stream_out_rtp "127.0.0.1" RTSP host might be ignored in multiple-host configurations, use at your own risks.
main looking for access module matching "imem": 27 candidates
imem Invalid get/release function pointers
main looking for stream_filter module matching "prefetch,cache_read": 24 candidates
main looking for stream_filter module matching "any": 24 candidates
304219
lua Trying Lua scripts in C:\Users\Konstant\AppData\Roaming\vlc\lua\playlist
lua Trying Lua scripts in C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\anevia_streams.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\anevia_xml.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\appletrailers.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\bbc_co_uk.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\cue.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\dailymotion.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\jamendo.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\koreus.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\liveleak.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\newgrounds.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\rockbox_fm_presets.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\soundcloud.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\twitch.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\vimeo.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\vocaroo.luac
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\playlist\youtube.luac
main no stream_filter modules matched
main creating demux: access='imem' demux='any' location='' file='(null)'
main looking for demux module matching "any": 55 candidates
main using xml reader module "xml"
main using packetizer module "copy"
main using demux module "image"
main looking for meta reader module matching "any": 2 candidates
lua Trying Lua scripts in C:\Users\Konstant\AppData\Roaming\vlc\lua\meta\reader
lua Trying Lua scripts in C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\meta\reader
lua Trying Lua playlist script C:\Users\Konstant\Documents\Projects\Presenter\Presenter\bin\Debug\net6.0-windows\libvlc\win-x64\lua\meta\reader\filename.luac
main no meta reader modules matched
main `imem://' successfully opened
main EOF reached
main killing decoder fourcc `jpeg'
main removing module "copy"
main removing module "image"
main removing module "record"
main removing module "prefetch"
main starting in async mode
main selecting program id=0
main looking for packetizer module matching "any": 25 candidates
webvtt subtitle demux discarded
image Failed to load the image
image image too large (2147483647 > 134217728), rejected
image Detected image: JPEG
main using stream_filter module "record"
main no stream_directory modules matched
main looking for xml reader module matching "any": 1 candidates
main looking for stream_directory module matching "any": 1 candidates
main looking for stream_filter module matching "record": 24 candidates
main attachment of directory-extractor failed for imem://
304219
prefetch end of stream
The thread 0x2180 has exited with code 0 (0x0).
main removing module "imem_access"
main Program doesn't contain anymore ES
附注我提前为我的英语感到抱歉。