我使用ffmpeg将原始媒体文件转换为rawvideo yuv格式,将yuv转换为pipe,然后我的命令工具接收原始的yuv作为input,做一些处理。
例如:
D:\huang_xuezhong\build_win32_VDNAGen>ffmpeg -i test.mkv -c:v rawvideo -s 320x240 -f rawvideo - | my_tool -o output
每次运行命令的时候,ffmpeg都会把这个av_interleaved_write_frame(): Broken pipe
转储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!
在我的源代码中:它以stdin
作为input文件,每次从它读取一个帧大小的内容,如果读取的内容小于一个帧大小,则继续读取,直到获取一帧,然后使用框架内容来产生的东西。
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; }
我的日志:
2016/04/05 15:20:38:一帧尺寸:115200 2016/04/05 15:20:38:try_cnt是1 2016/04/05 15:20:38:已经读过yuv:49365,这个时候: 49365 2016/04/05 15:20:38:try_cnt是2 2016/04/05 15:20:38:已经阅读yuv:49365,这个时候:0 2016/04/05 15:20:38:try_cnt是3 2016/04/05 15:20:38:已经阅读yuv:49365,这个时候:0 2016/04/05 15:20:38:try_cnt是4 2016/04/05 15:20:38:已经阅读yuv: 49365,这个时间:0 2016/04/05 15:20:38:try_cnt是5 2016/04/05 15:20:38:已经读过yuv:49365,这个时候:0 2016/04/05 15:20: 38:try_cnt是6 2016/04/05 15:20:38:已经阅读yuv:49365,这个时候:0 2016/04/05 15:20:38:try_cnt是7 2016/04/05 15:20:38 :已经阅读yuv:49365,这个时候:0 2016/04/05 15:20:38:try_cnt是8 2016/04/05 15:20:38:已经阅读yuv:49365,这个时候:0 2016/04 / 05 15:20:38:try_cnt是9 2016/04/05 15:20:38:已经阅读yuv:49365,这个时候:0 2016/04/05 15:20:38:try_cnt是10 2016/04/05 15:20:38:已经读过yuv:49365,这次是:0 2016/04/05 15:20:38:try_cnt是11 2016/04/05 15:20:38:尝试超时“`
我的问题:
当使用pipe道时,ffmpeg一旦有内容就将内容写入pipe道缓冲区,或者它会缓冲一些大小的内容,然后将它们刷新到pipe道?也许是我误解了一些内部逻辑,任何人都可以帮助解释或修复我的代码?
PS:这个命令在linux下运行正常。