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

发布于 2024-10-22 08:45:37 字数 2379 浏览 1 评论 0原文

我在进程之间传递二进制数据时遇到问题。我的程序使用 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”用于打开文本文件。

但我无法像 fopen() 那样用“rb”打开它,因为 popen() 不接受“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;
}

Update-2:

比较文件

1) File-1 =>通过将数据从 ffmpeg 管道输出而获得

2) File-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,它可能会将其作为 0 放在 file-1 的标头中(但仍然想知道为什么它必须在 file-1 中将持续时间设置为 0)。

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

任何帮助/建议都将非常有帮助和感激。

问候,

微内核

I am facing issue in passing binary data between processes. My program opens a pipe to ffmpeg using popen() and tries to capture the output and then stream it as HTTP server.

I am doing something like this

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

(Output filename "-" diverts the output to stdout)

After opening I am using fread() to read the pipe.

I can read it and my program streams content, when I downloaded the file on my browser, it completed, but the output file is not playable!!!

I am suspecting pipe opened to be "non-binary" handle as I opened it with popen("", "r"), as "r" in fopen is for text file opening.

But I am not able to open it with "rb" like I do for fopen(), as "rb" is not acceptable by popen().

How can I solve this issue?

UPDATE:

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

Code Opening pipe

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

Code for reading from pipe

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

Code for closing pipe (For completeness :) )

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

Update-2:

Compared the files

1) File-1 => Obtained by piping the data out off ffmpeg

2) File-2 => Obtained directly from ffmpeg using the same configuration

There are differences that I can see,
1) File_Duration_field in File-1 is 0 but File-2 has some value.
2) File_size_field in File-1 is 0 but File-2 has some value
3) File-1 has some extra 18 bytes at the end which is not present in File-2. Looks like the missing detailed about file_size and file_duration.

This looks natural isn't it? as ffmpeg doesn't know exact file_size of output it might have put it as 0 in the header of file-1 (But still wonder why it has to put 0 for duration in file-1).

My goal is to transcode my videos files into flv and stream them simultaneously so I don't have to wait for the conversion or have to convert everything in advance. But accomplishing this looks not possible this way. Is there any way for me to do this???

Any help/suggestion will be highly helpful and appreciated.

Regards,

Microkernel

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

双手揣兜 2024-10-29 08:45:37

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

fopen 联机帮助页:

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

I'm guessing you're using linux, or some other unix. In that case there's no distinction between opening something in binary mode or text mode. You don't need the "b" flag at all. Your problem lies elsewhere.

From the fopen manpage:

The mode string can also include the letter ''b'' either as a last character or as a character between the characters in any of the two-character strings described above. This is strictly for compatibility with C89 and has no effect; the ''b'' is ignored on all POSIX conforming systems, including Linux. (Other systems may treat text files and binary files differently, and adding the ''b'' may be a good idea if you do I/O to a binary file and expect that your program may be ported to non-Unix environments.)

荒芜了季节 2024-10-29 08:45:37

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

您可能还想尝试使用 ffmpeg 管道选项 看看是否有对输出的影响。

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

The output may be raw data without a container. So, there is no way for an application to know how to interpret the binary data in the file.

You may also want to try using the ffmpeg pipe option to see if that has an effect on the output.

Note that some formats (typically
MOV), require the output protocol to
be seekable, so they will fail with
the pipe output protocol.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文