-1

I write Windows service witch decodig video stream from camera. I write it on c# with FFMPEG.Autogen wrapper.

My problem is "AccessViolationException" when i run it as service. If i run application as Console Application i have no exceptions.

In Stacktrace i see this:

в FFmpeg.AutoGen.ffmpeg+<>c.<.cctor>b__5_572(FFmpeg.AutoGen.AVFrame*, FFmpeg.AutoGen.AVFrame*, Int32)
в FFmpeg.AutoGen.ffmpeg.av_hwframe_transfer_data(FFmpeg.AutoGen.AVFrame*, FFmpeg.AutoGen.AVFrame*,Int32)
в VideoProviderService.VideoSources.RTSPVideoSource.TryDecodeNextFrame(Boolean ByRef)

Code of TryDecodeNextFrame method:

public IntPtr TryDecodeNextFrame(out bool state)
{
    try
    {
        ffmpeg.av_frame_unref(pFrame);
        ffmpeg.av_frame_unref(cpuFrame);
        int error;
        do
        {
            try
            {
                do
                {
                    timeout = DateTime.Now.AddSeconds(2);
                    error = ffmpeg.av_read_frame(_pFormatContext, pPacket);
                    if (error == ffmpeg.AVERROR_EOF)
                    {
                        state = false;
                        return IntPtr.Zero;
                    }
                    error.ThrowExceptionIfError();
                } while (pPacket->stream_index != _streamIndex);
                ffmpeg.avcodec_send_packet(pCodecContext, pPacket).ThrowExceptionIfError();
            }
            finally
            {
                ffmpeg.av_packet_unref(pPacket);
            }
            error = ffmpeg.avcodec_receive_frame(pCodecContext, pFrame);
        } while (error == ffmpeg.AVERROR(ffmpeg.EAGAIN));
        error.ThrowExceptionIfError();
        ffmpeg.av_hwframe_transfer_data(cpuFrame, pFrame, 0).ThrowExceptionIfError();
        ptrToFrame = (IntPtr)vfc.Convert(*cpuFrame).data[0];  
    }
    catch
    {
        state = false;
        return IntPtr.Zero;
    }
    state = true;
    return ptrToFrame;
}

What i tried to do:

  1. I checked arguments of av_hwframe_transfer_data.
  2. I changed the user for the service.
  3. I tried compile as x86 or x64 configuration.

I have no idea how to solve this. Does anyone have any thoughts?

vakym
  • 61
  • 1
  • 9

1 Answers1

0

It seems that you are not handling properly your frames (pFrame/cpuFrame). Especially, for the cpuFrame you should alloc it in every run and free it at the end of every run. Additionally for the pFrame you should unref it directly after av_hw_frame_transfer_data. Eg:-

cpuFrame = ffmpeg.av_frame_alloc();

....

ffmpeg.av_hwframe_transfer_data(cpuFrame, pFrame, 0).ThrowExceptionIfError();

ffmpeg.av_frame_unref(pFrame);

.... Process your cpuFrame ...

ffmpeg.av_frame_free(&cpuFrame);

....
SuRGeoNix
  • 482
  • 1
  • 3
  • 10
  • I'm not wrote that, but i allocate memory for frames every time when i create context for decoding. And i invoke `ffmpeg.av_frame_unref(pFrame);` and `ffmpeg.av_frame_free(cpuFrame);` methods at beginning on every step . The algorithm look like that: 1) Create decoding context 2) Allocate memory for frames 3) Invoke TryDecodeNextFrame method 4) In this method invoke `ffmpeg.av_frame_unref(pFrame);` and `ffmpeg.av_frame_free(cpuFrame);` 5) Receive new pFrame. 6) Copy pFrame to cpuFrame 7) Go back to step 3 I suppose my code does the same steps that you wrote in your answer. – vakym Nov 11 '19 at 14:15
  • It's not easy to help, when we cannot see the whole code. But I would bet that you problem is your cpuFrame. Alloc it befeore hwframe_transfer and never unref it (just free it when you are done with it in every process). Try exactly this :- `code cpuFrame = ffmpeg.av_frame_alloc(); fmpeg.av_hwframe_transfer_data(cpuFrame, pFrame, 0).ThrowExceptionIfError(); ffmpeg.av_frame_unref(pFrame); .... process cpuFrame ... ffmpeg.av_frame_free(&cpuFrame); ` dont touch cpuFrame with unref/free elsewhere... just that – SuRGeoNix Nov 13 '19 at 09:20