0

I am writing code that reads h264 data from socket, passes it to h264dec.exe (openh264 decoder) and then pases YUV data to YUV-RGB decoder. My issue is that openh264dec works like "h264dec video.h264 out.yuv".

And I don't really know how to handle arguments in code to serve them as streams. For training purposes i've tried h264dec video.h264 \\.\pipe\h264input but it doesn't work, the code is as below:

NamedPipeServerStream pipeServ = new NamedPipeServerStream(Utility.DecoderOutputPipeName, PipeDirection.InOut);

Openh264.Openh264 openh264 = new Openh264.Openh264();
openh264.Start();
pipeServ.WaitForConnection();
Openh264.YUVDecoder decoder = new Openh264.YUVDecoder(pipeServ, 640, 480);
decoder.NewFrame += Decoder_NewFrame;
decoder.Start();

The process is:

public Openh264()
{
    string args;
    //args = @" \\.\pipe\" + Utility.DecoderInputPipeName;
    args = @"C:\test\vid.h264";
    args += @" \\.\pipe\" + Utility.DecoderOutputPipeName;
    openh264 = new Process();
    openh264.StartInfo.CreateNoWindow = true;
    openh264.StartInfo.UseShellExecute = false;
    openh264.StartInfo.FileName = "h264dec.exe";
    openh264.StartInfo.Arguments = args;
}

The YUV decoder takes as an input Stream object, width and height. The program hangs on WaitForConnection() and without that function, YUV decoder throws an exception while reading from the stream.

Is it even possible to make it work like this? Substitute arguments with pipes?

Ghasem
  • 14,455
  • 21
  • 138
  • 171
CoreMeltdown
  • 194
  • 1
  • 11

1 Answers1

0

I have read the Openh264 source code and from what I understand in this particular situation it is not possible to substitute file argument with pipe, because it tries to load whole file into memory for processing:

if (fread (pBuf, 1, iFileSize, pH264File) != (uint32_t)iFileSize) {
    fprintf (stderr, "Unable to read whole file\n");
    goto label_exit;
  }

So I have decided to switch to ffmpeg and it works perfectly:

class FFmpeg
{
    Process ffmpeg;

    public FFmpeg()
    {
        String args = "";
        ffmpeg = new Process();
        ffmpeg.StartInfo.CreateNoWindow = true;
        ffmpeg.StartInfo.UseShellExecute = false;
        ffmpeg.StartInfo.RedirectStandardInput = true;
        ffmpeg.StartInfo.RedirectStandardOutput = true;
        ffmpeg.StartInfo.FileName = @"C:\test\ffmpeg.exe";
        args = @" -i C:\test\video.h264 -c:v rawvideo -pix_fmt yuv420p -f rawvideo -";
        ffmpeg.StartInfo.Arguments = args;
    }

    public void Start()
    {
        ffmpeg.Start();
    }

    public void End()
    {
        ffmpeg.Kill();
    }

    public BinaryWriter InputStream
    {
        get
        {
            return new BinaryWriter(ffmpeg.StandardInput.BaseStream);
        }
    }

    public Stream OutputStream
    {
        get
        {
            return ffmpeg.StandardOutput.BaseStream;
        }
    }
}

Sample usage:

        FFmpeg.FFmpeg ffmpeg = new FFmpeg.FFmpeg();
        ffmpeg.Start();
        Utils.YUVDecoder decoder = new Utils.YUVDecoder(ffmpeg.OutputStream, 640, 480);
        decoder.NewFrame += Decoder_NewFrame;
        decoder.Start();
CoreMeltdown
  • 194
  • 1
  • 11