重定向stdin和stdout,其中stdin首先关闭

时间:2009-09-03 13:21:58

标签: c# ipc

这实际上与我已经回答的另一个问题有关。这个问题在这里:Redirecting stdout of one process object to stdin of another

我的问题是(我认为)获得输入的程序应该在程序输出之前退出。这是我正在做的bash相当于:tccat -i / dev / sr0 -T 1 | ffmpeg -i - -r 1 -t 1 -s 96x72 -ss 5 /tmp/wsmanage/preview_tmp/test\%03d.jpg

这只是使用一个名为tccat的程序来读取DVD的第一个标题。这将输出到ffmpeg,它将以.jpg格式创建一个每秒1帧的输出文件,长度为1秒。一旦输出其框架(或两个),它就会存在。这很好。

但是,以下代码没有。我得到了“打印行到ffmpeg”的大量内容,而命令行版本只需一秒钟即可退出。然后,它会在30或40秒左右停止打印。 FFmpeg永远不会退出,我的程序永远不会继续。

我是这样做的吗?

Process tccatProcess = new Process();           
tccatProcess.StartInfo.FileName = "tccat";
tccatProcess.StartInfo.Arguments = String.Format("-i {0} -T {1}", devNode, title);
tccatProcess.StartInfo.UseShellExecute = false;
tccatProcess.StartInfo.RedirectStandardOutput = true;

Process ffmpegProcess = new Process();
string bashSafePreviewTemplate = slasher.bashSlash(previewTempDir + "/test%03d.jpg");
ffmpegProcess.StartInfo.FileName = "ffmpeg";
ffmpegProcess.StartInfo.Arguments = String.Format("-i - -r 1 -t 1 -s {1}x{2} -ss {3} {0}", 
    bashSafePreviewTemplate, width, height, timePosition);
ffmpegProcess.StartInfo.UseShellExecute = false;
ffmpegProcess.StartInfo.RedirectStandardInput = true;


try{
    tccatProcess.Start();
    ffmpegProcess.Start();

    StreamReader tccatOutput = tccatProcess.StandardOutput;
    StreamWriter ffmpegInput = ffmpegProcess.StandardInput;

    string line;
    while(!ffmpegProcess.HasExited)
    {
        ffmpegProcess.Refresh();
        if((line = tccatOutput.ReadLine()) != null)
        {
            Console.WriteLine("Printing line to ffmpeg");
            Console.Out.Flush();
            ffmpegInput.WriteLine(line);
            ffmpegInput.Flush();
        }
    }

    Console.WriteLine("Closing tccat");
    Console.Out.Flush();
    tccatProcess.Close();
    Console.WriteLine("Tccat closed");
    Console.Out.Flush();


}catch(Exception e){
    //uninteresting log code
    return false;
}

2 个答案:

答案 0 :(得分:1)

对于任何想要做类似事情的人来说,以下是适用KeeperOfTheSoul建议的新版本:

        Process tccatProcess = new Process();           
        tccatProcess.StartInfo.FileName = "tccat";
        tccatProcess.StartInfo.Arguments = String.Format("-i {0} -T {1}", devNode, title);
        tccatProcess.StartInfo.UseShellExecute = false;
        tccatProcess.StartInfo.RedirectStandardOutput = true;

        Process ffmpegProcess = new Process();
        string bashSafePreviewTemplate = slasher.bashSlash(previewTempDir + "/test%03d.jpg");
        ffmpegProcess.StartInfo.FileName = "ffmpeg";
        ffmpegProcess.StartInfo.Arguments = String.Format("-i - -r 1 -t 1 -s {1}x{2} -ss {3} {0}", 
            bashSafePreviewTemplate, width, height, timePosition);
        ffmpegProcess.StartInfo.UseShellExecute = false;
        ffmpegProcess.StartInfo.RedirectStandardInput = true;

        Console.WriteLine("tccat command: {0} {1}", tccatProcess.StartInfo.FileName, tccatProcess.StartInfo.Arguments);
        Console.WriteLine("ffmpeg command: {0} {1}", ffmpegProcess.StartInfo.FileName, ffmpegProcess.StartInfo.Arguments);

        //return true;

        try{
            tccatProcess.Start();
            ffmpegProcess.Start();

            BinaryReader tccatOutput = new BinaryReader(tccatProcess.StandardOutput.BaseStream);
            BinaryWriter ffmpegInput = new BinaryWriter(ffmpegProcess.StandardInput.BaseStream);
            int buffSize = 4096;
            byte[] buff = new byte[buffSize];


            while(!ffmpegProcess.HasExited)
            {
                ffmpegProcess.Refresh();
                buff = tccatOutput.ReadBytes(buffSize);
                ffmpegInput.Write(buff);
                ffmpegInput.Flush();
            }


            tccatProcess.Kill();
            tccatProcess.Close();
            ffmpegProcess.Close();


        }catch(Exception e){
                    //uninteresting log code
                    return false;

        }

答案 1 :(得分:0)

由于您正在使用视频和图像,因此不会输出二进制数据吗?如果是这样,你不应该直接读/写输入/输出流而不是将它们包装在文本阅读器中吗?

如果是这样,您想要使用Can i put binary in stdin? C#