0

Good afternoon, everyone. I am trying to implement rtsp broadcasting from images that I render from a WPF control. I was able to save the images in a folder, so they turn out to be correct. I use VLC for streaming. I made my own implementation of Stream, in which I used BlockingCollection to store frames. When calling the Read method, I take one frame from the collection and copy it to the buffer. When I try to connect to the broadcast via VLC Player, I get the error "This source does not open" I really don't understand what the problem could be. I hope for your help. Thanks in advance)

Main class

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;
        }

Stream class

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;
        }
    }
}

Debug log

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

P.S. I'm sorry in advance for my English.

  • I tried to start the stream, having previously uploaded 30,000 copies of the image to the collection. It didn't help. The stream ended anyway, due to "EOF reached" and the "EndReached" event handler was called. What is the trigger for VLC to consider that the end of the file has been reached – Константин Ермаков Jul 30 '23 at 22:56
  • Be careful, you may have read incomplete images in your Read method, but the next time, you Take() another picture, so that would never make a full picture – cube45 Aug 13 '23 at 07:34

0 Answers0