I'm struggling with the following issue, on a Windows system:
- I get a live stream from an SDK; I get chunks of bytes via a callback; the container is MPEG-PS
- I have to display this live stream to the end-user using VLC. But VLC cannot play this stream I receive
- My solution was to use ffmpeg to convert this to MPEG-TS (or something else) that can be played by VLC
I tried different possible solutions, like making a TCP server which exposes this stream, instructing ffmpeg to read the input from there. But ffmpeg is complaining that it cannot detect the container type. If I save to disk the bytes that I receive via that callback, I can see that the first bytes are ‘IMKH’, indicating a MPEG-PS container. If I then use ffmpeg to transcode it to MP4 (as a file), that works. But I need to do this ‘dynamically’, so a live transcoding of the stream that I receive.
Last thing that I have tried was to create a named pipe and write the received bytes in it, then used the following command to create the live stream: ffmpeg -i \.\pipe\testpipe -f mpegts -c copy -listen 1 "http://127.0.0.1:5002” and then play the URL “http://127.0.0.1:5002” in VLC.
Something strange is happening, because only when I close the pipe, the ffmpeg start to output (in console) the found streams and VLC can connect to its http server and starts playing correctly. I flush the pipe after writing each chunk of bytes.
I would expect ffmpeg to start processing the pipe input as it is received, and immediately output the result for VLC. I found something similar in the following post, but without an answer: https://ffmpeg.org/pipermail/ffmpeg-user/2016-December/034639.html
Why is ffmpeg waiting to close the pipe to start processing? Can it be configured to start a live transcoding of the received stream?
EDIT - MORE DETAILS ====================================
I cannot make available the source stream (it is isolated in an intranet), but as I mentioned I use a 3rd party C# SDK to access it (actually this is the only way to access it). That SDK provides me access to that stream via a simple callback which looks like this: callback(byte[] data). So using this callback I receive all the stream bytes. I saved these bytes to a file on disk. The received stream is MPEG-PS. If I try to convert this file to another file format (like avi) that works: ffmpeg.exe -i input.mpeg out.avi and VLC can play this out.avi. So I know that the callback data that I get is correct, so input.mpeg is a correct file, ffmpeg can deal with it.
For my testing I also use this input.mpeg file, I created a simple C# server which reads it, and exposes it in chunks via a named pipe using this code:
_pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.Out);
_pipeServer.WaitForConnection(); // wait for ffmpeg to connect
byte[] allBytes = System.IO.File.ReadAllBytes(“input.mpeg”);
using (BinaryWriter bw = new BinaryWriter(_pipeServer))
{
int index = 0;
for(;;)
{
bw.Write(allBytes, idx, 100);
index += 100;
// added some delay to emulate a live stream
System.Threading.Thread.Sleep(100);
if (idx >= allBytes.Length) break;
}
}
This is the exact description of the flow:
- I start the C# pipe server as above
- I start ffmpeg with the command line: ffmpeg -i \.\pipe\testpipe -f mpegts –c copy -listen 1 http://127.0.0.1:5002
- Then I start VLC with URL http://127.0.0.1:5002.
But nothing happens; only when the C# server completes sending (so the BinaryWriter object is disposed, so ffmpeg detects the end of input stream) VLC starts playing. It seems that ffmpeg accumulates the received stream and only provides the output when the input completes.
I made also the following test:
- I converted input.mpeg which has MPEG_PS format to MPEG-TS format using: ffmpeg.exe -i input.mpeg input.ts
- then I feed input.ts in the named pipe “testpipe” and start ffmpeg with the same args: ffmpeg -i \.\pipe\testpipe -f mpegts –c copy -listen 1 http://127.0.0.1:5002
- I start VLC with http://127.0.0.1:5002 and it starts immediately.
So I think this proves is not a pipe issue, but a format/container issue. When the pipe is fed with MPEG-PS, ffmpeg waits for EOF; but when is fed with MPEG-TS, ffmpeg starts producing output immediately (and this is what I want to achieve, live streaming).
BTW: if I kill the C# server above when it gets to the middle of the input.mpeg, the effect is the same, VLC starts playing the available stream. So I don’t think ffmpeg really needs the entire stream to be downloaded in order to start forwarding it to output.
Do you know how can I convince ffmpeg to start producing output immediately? Probably is some parameter for ffmpeg, but I could not find it … I have placed the input.mpeg file here:
https://www.dropbox.com/s/zsdktikfq4yuak0/input.mpeg?dl=0
Thank you!
