popen在进程之间传递二进制数据

时间:2011-03-14 17:37:48

标签: c ipc pipe popen

我在处理过程中传递二进制数据时面临问题。我的程序使用popen()打开一个到ffmpeg的管道,并尝试捕获输出,然后将其作为HTTP服务器流式传输。

我正在做这样的事情

ffmpeg -i "input_video.avi" -ab 56 -ar 44100 -b 1500000 -r 25 -s 800x600 -f flv - 

(输出文件名“ - ”将输出转移到标准输出)

打开后我使用fread()来读取管道。

我可以阅读它和我的程序流内容,当我在浏览器上下载文件时,它已完成,但输出文件无法播放!!!

我怀疑管道打开是“非二进制”句柄,因为我用popen(“”,“r”)打开它,因为fopen中的“r”用于打开文本文件。

但是我无法用“rb”打开它,就像我为fopen()所做的那样,因为pob()不接受“rb”。

我该如何解决这个问题?

更新

#define FFMPEG_COMMAND "ffmpeg -i %s -ab 56 -ar 44100 -b 1500000 -r 25 -s 800x600 -f flv -"

代码开启管道

Opening_pipe(filename)
{
    STREAMING_HANDLE *vfp = NULL;
    char command[512] = {  0 };


    vfp = (STREAMING_HANDLE *)malloc(sizeof(STREAMING_HANDLE));
    if(NULL != vfp)
    {
        sprintf(command, FFMPEG_COMMAND, filename);
        vfp->ffmpeg_pipe = popen( command, 
                                  "r" );

        if( NULL == vfp->ffmpeg_pipe )
        {
            free(vfp);
            vfp = NULL;
        }
    }    
    printf("Virt_dir_fopen : vfp => 0x%X\n", vfp);
    return vfp;
}

从管道中读取的代码

Reading_data_from_pipe(fileHnd, buff, buflen)
{
    STREAMING_HANDLE *vfp = (STREAMING_HANDLE *)fileHnd;
    int ret_code;
    printf("Virt_dir_fread : Asking for %d bytes \n", buflen);
    ret_code =  fread(buf, 1, buflen, vfp->ffmpeg_pipe );
    printf("Virt_dir_fread : Returning %d bytes \n", ret_code);

    return ret_code;
}

关闭管道代码(完整性:))

Closing_pipe(fileHnd)
{
    STREAMING_HANDLE *vfp = (STREAMING_HANDLE *)fileHnd;
    pclose(vfp->ffmpeg_pipe);
    free(vfp);
    return 0;
}

更新-2:

比较文件

1)文件-1 =>通过将数据输出ffmpeg

获得

2)文件-2 =>使用相同的配置直接从ffmpeg获取

我可以看到差异, 1)File-1中的File_Duration_field为0但File-2有一些值。 2)File-1中的File_size_field为0但File-2有一些值 3)File-1在末尾有一些额外的18个字节,在File-2中不存在。看起来缺少有关file_size和file_duration的详细信息。

这看起来很自然不是吗?因为ffmpeg不知道输出的确切file_size,所以它可能在文件-1的标题中将其设置为0(但仍然想知道为什么它必须在文件-1中将持续时间设为0)。

我的目标是将我的视频文件转码为flv并同时传输它们,这样我就不必等待转换或者必须提前转换所有内容。但实现这一点看起来不可能这样。有什么办法让我这样做吗?

任何帮助/建议都将非常有帮助和赞赏。

此致

微内核

2 个答案:

答案 0 :(得分:3)

我猜你正在使用linux或其他一些unix。在这种情况下,在二进制模式或文本模式下打开某些东西没有区别。你根本不需要“b”标志。你的问题出在其他地方。

来自fopen联机帮助页:

  

模式字符串还可以包括字母“b”作为最后一个字符或者作为上述任意两个字符串中的字符之间的字符。这完全是为了与C89兼容而没有效果;所有符合POSIX标准的系统(包括Linux)都会忽略“b”。 (其他系统可能会以不同方式处理文本文件和二进制文件,如果您对二进制文件执行I / O并且期望您的程序可能移植到非Unix环境,则添加“b”可能是个好主意。)

答案 1 :(得分:1)

输出可能是没有容器的原始数据。因此,应用程序无法知道如何解释文件中的二进制数据。

您可能还想尝试使用ffmpeg pipe option来查看它是否对输出产生影响。

  

请注意某些格式(通常是   MOV),需要输出协议   是可以追查的,所以他们会失败的   管道输出协议。