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”用于打开文本文件。
但我无法像 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我猜你正在使用linux,或者其他一些unix。在这种情况下,以二进制模式或文本模式打开某些内容没有区别。您根本不需要“b”标志。你的问题出在别处。
从 fopen 联机帮助页:
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:
输出可能是没有容器的原始数据。因此,应用程序无法知道如何解释文件中的二进制数据。
您可能还想尝试使用 ffmpeg 管道选项 看看是否有对输出的影响。
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.