1

Windows 7 64 bit environment. C# Windows Forms application calling FFmpeg libraries through C++ bridge DLL including avcodec-57.dll, avformat-57.dll, avutil-55.dll, swresample-2.dll and swscale-4.dll to write MPEG-4 file using H.264/MPEG-4 AVC codec. When writing a single MP4 file, never a problem. When writing multiple MP4 files concurrently, via multiple C# threads, occasionally get av_interleaved_write_frame failure -22 which is invalid parameter on one or two but never all files. Needless to say, the parameters never change. Does FFmpeg use temporary files? Is it possible that there is a fratricidal effect when using the same DLLs to write multiple files concurrently? Edit: placed mutex at entry/exit to my write frame function, see source below, and can no longer reproduce the problem. It would appear something about FFmpeg is not thread-safe.

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);
}
  • Update: have determined that av_packet_rescale_ts is occasionally placing 0x8000000000000000LL in pkt->pts, and when that happens, FFmpeg fails av_interleaved_write_frame with message "timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly." Problem is, I'm not setting pts, av_packet_rescale_ts is. And I observe, when the failure does not occur, pts is not monotonically increasing. Why does av_packet_rescale_ts behave erratically with identical data, run to run? –  Oct 29 '17 at 16:47
  • Update: have further determined that it is avcodec_encode_video2 that is generating erratic pts values. When the first packet generated by avcodec_encode_video2 contains pts=0, all that follows succeeds, including all calls to av_interleaved_write frame. But when the first packet generated by avcodec_encode_video2 contains very, very strange pts values, e.g., 0x610063006F004C, the av_packet_rescale_ts chokes and generates AV_NOPTS_VALUE. So now the question is why is avcodec_encode_video2 generating erratic pts when the input data is always exactly the same? –  Oct 29 '17 at 17:33
  • Problem resolved: based my code on FFmpeg muxing.c sample, which has automatic variable OutputStream that is statically initialized with {0}. I am dynamically allocating OutputStreams and failed to manually clear and initialize the structure elements, hence next_pts was random garbage. Once next_pts was zeroed, problem solved. –  Oct 29 '17 at 18:02

0 Answers0