我的目标是编写一个c ++ / cli wrap arount ffmpeg库,使用从dll-modules导入ffmpeg函数。 稍后我将在c#中使用此接口。 这是我的挑战,不要问我为什么))
所以我已经实现了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();
};
}
因此,对libavcodec等的导入是成功的。 在调用dll func期间,问题出在AccessViolationException中,例如,在OpenInput中(即本机ffmpeg库中的av_open_input)
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 :(得分:0)
遇到同样的问题,你需要初始化AVFormatContext对象。
好例子:
AVFormatContext *pFormatCtx = avformat_alloc_context();
错误的例子:
AVFormatContext *pFormatCtx = NULL;