Windows 7 64位环境。 C#Windows Forms应用程序通过C ++桥接DLL调用FFmpeg库,包括avcodec-57.dll,avformat-57.dll,avutil-55.dll,swresample-2.dll和swscale-4.dll,用H编写MPEG-4文件。 264 / MPEG-4 AVC编解码器。编写单个MP4文件时,从来没有问题。当同时写入多个MP4文件时,通过多个C#线程,偶尔会得到av_interleaved_write_frame failure -22,这是一个或两个但从不是所有文件的无效参数。不用说,参数永远不会改变。 FFmpeg是否使用临时文件?当使用相同的DLL同时写入多个文件时,是否可能存在自相残杀效应? 编辑:在入口/出口处放置互斥到我的写帧功能,请参阅下面的源代码,并且无法再重现该问题。看起来有关FFmpeg的东西不是线程安全的。
extern "C" __declspec(dllexport) int ffmpeg_write_video_frame(FFMPEG_CONTEXT *ffmpegContext, uint8_t *frameBuffer)
{
#ifdef SINGLE_THREAD
WaitForSingleObject(hMutex, INFINITE);
#endif
AVFrame *frame = ffmpeg_get_video_frame(&ffmpegContext->video, frameBuffer);
if (frame == NULL)
{
MessageBox(GetActiveWindow(), "ffmpeg_get_video_frame returned NULL", "ffmpeg_write_video_frame", MB_OK);
#ifdef SINGLE_THREAD
ReleaseMutex(hMutex);
#endif
return(-1);
}
AVPacket pkt = { 0 };
av_init_packet(&pkt);
// encode the image
int got_packet = 0;
int result = avcodec_encode_video2(ffmpegContext->video.avCodecContext, &pkt, frame, &got_packet);
if (result < 0)
{
char text[256];
sprintf_s(text, sizeof(text), "avcodec_encode_videos failure=%d", result);
MessageBox(GetActiveWindow(), text, "ffmpeg_write_video_frame", MB_OK);
#ifdef SINGLE_THREAD
ReleaseMutex(hMutex);
#endif
return(result);
}
// if the encoder has produced an output packet
if (got_packet)
{
result = ffmpeg_write_frame(ffmpegContext->avFormatContext, &ffmpegContext->video.avCodecContext->time_base, ffmpegContext->video.avStream, &pkt);
if (result < 0)
{
char text[256];
sprintf_s(text, sizeof(text), "ffmpeg_write_frame failure=%d", result);
MessageBox(GetActiveWindow(), text, "ffmpeg_write_video_frame", MB_OK);
#ifdef SINGLE_THREAD
ReleaseMutex(hMutex);
#endif
return(result);
}
}
#ifdef SINGLE_THREAD
ReleaseMutex(hMutex);
#endif
return (0);
}
extern "C" int ffmpeg_write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt)
{
/* rescale output packet timestamp values from codec to stream timebase */
av_packet_rescale_ts(pkt, *time_base, st->time_base);
pkt->stream_index = st->index;
/* Write the compressed frame to the media file. */
#if 0
log_packet(fmt_ctx, pkt);
#endif
int result = av_interleaved_write_frame(fmt_ctx, pkt);
if (result < 0)
{
char text[256];
sprintf_s(text, sizeof(text), "av_interleaved_write_frame failure=%d", result);
MessageBox(GetActiveWindow(), text, "ffmpeg_write_frame", MB_OK);
}
return(result);
}