popen to pass binary data between processes

2019-06-09 10:33发布

问题:

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

回答1:

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.



回答2:

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.)



标签: c ipc pipe popen