Search code examples
c#ffmpegh.264rtpsharpffmpeg

FFmpeg (sharpFFmpeg) decoding - Protected memory error


I'm trying to use C# binding of FFmpeg library calling SharpFFmpeg to decode H264 video stream that I receive by RTP. I think I correctly decapsulate NALUs from RTP-packets, but I can't decode complete frames. Function avcodec_decode_video calling throws an AccessViolationException (Attempted to read or write protected memory).
Here are some code lines:

    //buf is a byte array containing encoded frame
    int success;
    FFmpeg.avcodec_init();
    FFmpeg.avcodec_register_all();
    IntPtr codec = FFmpeg.avcodec_find_decoder(FFmpeg.CodecID.CODEC_ID_H264);
    IntPtr codecCont = FFmpeg.avcodec_alloc_context(); //AVCodecContext
    FFmpeg.avcodec_open(codecCont, codec);
    IntPtr frame = FFmpeg.avcodec_alloc_frame();  //AVFrame
    FFmpeg.avcodec_decode_video(codecCont, frame, ref success, (IntPtr)buf[0], buf.Length); //exception

Function has been imported as follows:

    [DllImport("avcodec.dll", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
    public unsafe static extern int avcodec_decode_video(IntPtr pAVCodecContext, IntPtr pAVFrame, ref int got_picture_ptr, IntPtr buf, int buf_size);

Unfortunately, I don't know what do I have to do with the codecCont. Somebody wrote that it is needed to fill this structure by AVCDCR using session description received by RTSP. But I don't know which field(s) store this record.
I'll be glad for any help.
P.S. Excuse me for my English


Solution

  • I've detected that (IntPtr)buf[0] is pointing to the managed memory. And I've updated my code as follows:

      IntPtr frame = FFmpeg.avcodec_alloc_frame();
      IntPtr buffer = Marshal.AllocHGlobal(buf.Length + FFmpeg.FF_INPUT_BUFFER_PADDING_SIZE);
      for (int i = 0; i < buf.Length; i++)
          Marshal.StructureToPtr(buf[i], buffer + i, true);
      avcodec_decode_video(codecCont, frame, ref success, buffer, buf.Length + FFmpeg.FF_INPUT_BUFFER_PADDING_SIZE);
    

    Now function makes success variable equal zero, but do not throws exception.