ffmpeg av_interleaved_write_frame(): Broken pipe under windows
Asked Answered
I

0

3

I am using ffmpeg to convert original media file to rawvideo yuv format, ouputed the yuv to pipe, then my command tool receive the raw yuv as input, do some processing.

e.g:

D:\huang_xuezhong\build_win32_VDNAGen>ffmpeg -i test.mkv -c:v rawvideo -s 320x240 -f rawvideo - | my_tool -o output

every time, when run the command, ffmpeg will dump this av_interleaved_write_frame(): Broken pipe error msg:

Output #0, rawvideo, to 'pipe:':
  Metadata:
  encoder         : Lavf56.4.101
  Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 320x240 [SAR 120:91 DAR 160:91], q=2-31, 200 kb/s, 24 fps, 24 tbn, 24 tbc (default)
  Metadata:
      encoder         : Lavc56.1.100 rawvideo
  Stream mapping:
      Stream #0:0 -> #0:0 (h264 (native) -> rawvideo (native))
Press [q] to stop, [?] for help
av_interleaved_write_frame(): Broken pipe
frame=    1 fps=0.0 q=0.0 Lsize=     112kB time=00:00:00.04 bitrate=22118.2kbits/s
video:112kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing o
verhead: 0.000000%
Conversion failed!

in my souce code: it take stdin as the input file, every time, it read a frame size content from it, if the content read is less than a frame size, then continue read, until a frame is fetched, then it use the frame content to generate something.

int do_work (int jpg_width, int jpg_height) 
{
int ret = 0;

FILE *yuv_fp = NULL;
unsigned char * yuv_buf = NULL;
int frame_size = 0;
int count = 0;
int try_cnt = 0;

frame_size = jpg_width * jpg_height * 3 / 2;
va_log (vfp_log, "a frame size:%d\n", frame_size);

yuv_fp = stdin;

yuv_buf = (unsigned char *) aligned_malloc_int(
        sizeof(char) * (jpg_width + 1) * (jpg_height + 1) * 3, 128);

if (!yuv_buf) {
    fprintf (stderr, "malloc yuv buf error\n");
    goto end;
} 

memset (yuv_buf, 0, frame_size);
while (1) {

    try_cnt++;
    va_log (vfp_log, "try_cnt is %d\n", try_cnt);

    //MAX_TRY_TIMES = 10
    if (try_cnt > MAX_TRY_TIMES) {
        va_log (vfp_log, "try time out\n");
        break;
    }

    count = fread (yuv_buf + last_pos, 1, frame_size - last_pos, yuv_fp);
    if (last_pos + count < frame_size) {
        va_log (vfp_log, "already read yuv: %d, this time:%d\n", last_pos + count, count);
        last_pos += count;
        continue;
    }

    // do my work here

    memset (yuv_buf, 0, frame_size);
    last_pos = 0;
    try_cnt = 0;
}

end:
if (yuv_buf) {
    aligned_free_int (yuv_buf);
}

return ret;
}

my log:

2016/04/05 15:20:38: a frame size:115200 2016/04/05 15:20:38: try_cnt is 1 2016/04/05 15:20:38: already read yuv: 49365, this time:49365 2016/04/05 15:20:38: try_cnt is 2 2016/04/05 15:20:38: already read yuv: 49365, this time:0 2016/04/05 15:20:38: try_cnt is 3 2016/04/05 15:20:38: already read yuv: 49365, this time:0 2016/04/05 15:20:38: try_cnt is 4 2016/04/05 15:20:38: already read yuv: 49365, this time:0 2016/04/05 15:20:38: try_cnt is 5 2016/04/05 15:20:38: already read yuv: 49365, this time:0 2016/04/05 15:20:38: try_cnt is 6 2016/04/05 15:20:38: already read yuv: 49365, this time:0 2016/04/05 15:20:38: try_cnt is 7 2016/04/05 15:20:38: already read yuv: 49365, this time:0 2016/04/05 15:20:38: try_cnt is 8 2016/04/05 15:20:38: already read yuv: 49365, this time:0 2016/04/05 15:20:38: try_cnt is 9 2016/04/05 15:20:38: already read yuv: 49365, this time:0 2016/04/05 15:20:38: try_cnt is 10 2016/04/05 15:20:38: already read yuv: 49365, this time:0 2016/04/05 15:20:38: try_cnt is 11 2016/04/05 15:20:38: try time out ```

my question:

when piping used ,does ffmpeg write content to pipe buffer as soon as it has content, or it will buffer some size content, then flushes them to pipe?Maybe some internal logic that I misunderstood,any one could help explain or fix my code?

PS: this command run ok under linux.

Incapacity answered 5/4, 2016 at 7:51 Comment(2)
I have fixed this myself:It is just a windows issue, under Unix system, stdin/stdout/stderr opened in Binary mode by default,while under windows system is Text mode . so add 'set_mode(fileno(stdin),O_BINARY)' before yuv_fp = stdin; can work now.Incapacity
Thank you for sharing your solution. I ran into the same issue on my application and I was able to resolve the issue very quickly with this comment.Afterimage

© 2022 - 2024 — McMap. All rights reserved.