gpt4 book ai didi

用于在 c# 中使用的 ffmpeg c++/cli 包装器。通过它的指针调用dll函数后的AccessViolationException

转载 作者:行者123 更新时间:2023-12-04 22:50:50 46 4
gpt4 key购买 nike

我的目标是编写一个 c++/cli 包装 ffmpeg 库,通过从 dll 模块导入 ffmpeg 函数来使用。
后面我会在c#中使用这个接口(interface)。
这是我的挑战,不要问我为什么))

所以我实现了 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 使用 native 内存,通过它的地址初始化 pFormatCtx 变量。
我可以避免这种情况,还是不可能?

最佳答案

遇到同样的问题,你需要初始化 AVFormatContext 对象。

好的例子:

AVFormatContext *pFormatCtx = avformat_alloc_context();

不好的例子:
AVFormatContext *pFormatCtx = NULL;

关于用于在 c# 中使用的 ffmpeg c++/cli 包装器。通过它的指针调用dll函数后的AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31536317/

46 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com