2015-07-21 1 views
2

Моя цель - написать библиотеку arount ffmpeg для обтекания C++/cli, используя импорт функций ffmpeg из dll-модулей. Позже я буду использовать этот интерфейс в C#. Это моя проблема, не спрашивайте меня, почему))ffmpeg C++/cli wrapper для использования в C#. AccessViolationException после вызова функции dll по ее указателю

Так я реализовал класс Wrap, который приведен ниже:

namespace FFMpegWrapLib 
{ 
    public class Wrap 
    { 
    private: 

    public: 
     //wstring libavcodecDllName = "avcodec-56.dll"; 
     //wstring libavformatDllName = "avformat-56.dll"; 
     //wstring libswscaleDllName = "swscale-3.dll"; 
     //wstring libavutilDllName = "avutil-54.dll"; 

     HMODULE libavcodecDLL; 
     HMODULE libavformatDLL; 
     HMODULE libswsscaleDLL; 
     HMODULE libavutilDLL; 

     AVFormatContext  **pFormatCtx = nullptr; 
     AVCodecContext  *pCodecCtxOrig = nullptr; 
     AVCodecContext  *pCodecCtx = nullptr; 
     AVCodec    **pCodec = nullptr; 
     AVFrame    **pFrame = nullptr; 
     AVFrame    **pFrameRGB = nullptr; 
     AVPacket   *packet = nullptr; 
     int     *frameFinished; 
     int     numBytes; 
     uint8_t    *buffer = nullptr; 
     struct SwsContext *sws_ctx = nullptr; 

     void    Init(); 
     void    AVRegisterAll(); 
     void    Release(); 
     bool    SaveFrame(const char *pFileName, AVFrame * frame, int w, int h); 
     bool    GetStreamInfo(); 
     int     FindVideoStream(); 
     bool    OpenInput(const char* file); 
     AVCodec*   FindDecoder(); 
     AVCodecContext*  AllocContext3(); 
     bool    CopyContext(); 
     bool    OpenCodec2(); 
     AVFrame*   AllocFrame(); 
     int     PictureGetSize(); 
     void*    Alloc(size_t size); 
     int     PictureFill(AVPicture *, const uint8_t *, enum AVPixelFormat, int, int); 
     SwsContext*   GetSwsContext(int, int, enum AVPixelFormat, int, int, enum AVPixelFormat, int, SwsFilter *, SwsFilter *, const double *); 
     int     ReadFrame(AVFormatContext *s, AVPacket *pkt); 
     int     DecodeVideo2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt); 
     int     SwsScale(struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]); 
     void    PacketFree(AVPacket *pkt); 
     void    BufferFree(void *ptr); 
     void    FrameFree(AVFrame **frame); 
     int     CodecClose(AVCodecContext *); 
     void    CloseInput(AVFormatContext **); 
     bool    SeekFrame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags); 

     Wrap(); 
     ~Wrap(); 

     bool    GetVideoFrame(char* str_in_file, char* str_out_img, uint64_t time); 
    }; 

    public ref class managedWrap 
    { 
    public: 

     managedWrap(){} 
     ~managedWrap(){ delete unmanagedWrap; } 

     bool GetVideoFrameToFile(char* str_in_file, char* str_out_img, uint64_t time) 
     { 
      return unmanagedWrap->GetVideoFrame(str_in_file, str_out_img, time); 
     } 

     static Wrap* unmanagedWrap = new Wrap(); 
    }; 
} 

Так импорта в кодек и т.д. успешно. Проблема заключается в AccessViolationException при вызове DLL FUNC, например, в OpenInput (т.е. av_open_input в родной библиотеки FFmpeg)

Код функ OpenInput ниже:

bool FFMpegWrapLib::Wrap::OpenInput(const char* file) 
{ 
    typedef int avformat_open_input(AVFormatContext **, const char *, AVInputFormat *, AVDictionary **); 

    avformat_open_input* pavformat_open_input = (avformat_open_input *)GetProcAddress(libavformatDLL, "avformat_open_input"); 
    if (pavformat_open_input == nullptr) 
    { 
     throw exception("Unable to find avformat_open_input function address in libavformat module"); 
     return false; 
    } 

    //pin_ptr<AVFormatContext *> pinFormatContext = &(new interior_ptr<AVFormatContext *>(pCodecCtx)); 
    pFormatCtx = new AVFormatContext*; 
    //*pFormatCtx = new AVFormatContext; 


    int ret = pavformat_open_input(pFormatCtx, file, NULL, NULL); // here it fails 

    return ret == 0; 
} 

Таким образом, проблема, я думаю, что классные классы класса Wrap находятся в защищенной памяти. И ffmpeg работает с собственной памятью, инициализируя переменную pFormatCtx по ее адресу. Могу ли я избежать этого, или это невозможно?

ответ

0

Полученная же проблема, вам нужно инициализировать объект AVFormatContext.

Хороший пример:

AVFormatContext *pFormatCtx = avformat_alloc_context(); 

Плохой пример:

AVFormatContext *pFormatCtx = NULL; 
Смежные вопросы