[英]Generating a video from images with avimanager is throwing an error
我正在使用webclient從url獲取圖像數據,並嘗試像這樣生成視頻:
//http://www.codeproject.com/Articles/7388/A-Simple-C-Wrapper-for-the-AviFile-Library
WebClient client = new WebClient();
System.Net.WebRequest request = System.Net.WebRequest.Create(images);
System.Net.WebResponse response = request.GetResponse();
System.IO.Stream responseStream = response.GetResponseStream();
Bitmap bitmap = new Bitmap(responseStream);
//create a new AVI file
AviManager aviManager = new AviManager(@"C:\Users\Laptop\Documents\tada.avi", false);
//add a new video stream and one frame to the new file
//set IsCompressed = false
VideoStream aviStream = aviManager.AddVideoStream(false, 2, bitmap);
aviManager.Close();
但它消除了以下內容。 在圖書館這一行
int result = Avi.AVIFileCreateStream(aviFile, out aviStream, ref strhdr);
我收到以下錯誤:
System.AccessViolationException:'試圖讀取或寫入受保護的內存。 這通常表明其他內存已損壞。
您目前可能擁有“ Any CPU
” ...因此,您的應用程序隨后將作為64位進程(在64位Windows版本上)編譯/運行。
問題似乎是AVI Wrapper庫可能從未使用64位.NET應用程序進行過測試。...它沒有正確定義“ pinvoke”定義,因此在創建時將參數正確推入/彈出堆棧64位API調用。
將項目設置“平台目標”更改為x86 ...以便可以避免此問題。...盡管可以在32位模式下也可以調用“ avifil32.dll”。
Windows確實附帶了該AVI庫的32位和64位,因此從理論上講,當您是64位進程時,可以調用AVI庫。...但是您需要正確定義互操作/編組拼音。
在32位中(Microsoft使用ILP32數據模型)...
在64位中(Microsoft使用LLP64或P64數據模型)。
(請參閱https://msdn.microsoft.com/zh-cn/library/windows/desktop/aa384083(v=vs.85).aspx )
經常發生的錯誤是,在定義指針類型時,“ pinvoke”定義使用了“ int”,而不是更正確的IntPtr
類型。
因此,“調用”在32位上正常工作(因為“整數”與“指針”的大小相同)....而在64位上,它們的大小不同。
當您也是64位時,其他情況也會發生變化...例如默認邊界對齊...這可能會更改結構中類型的偏移量-因此,在定義pinvoke c#結構時必須小心...因此它們匹配。
如果您對函數調用AVIFileCreateStream
感興趣,則其WIN32簽名如下:
STDAPI AVIFileCreateStream(
PAVIFILE pfile,
PAVISTREAM *ppavi,
AVISTREAMINFO *psi
);
其參數的“類型”為:
typedef IAVIFile *PAVIFILE; // i.e. just a pointer
typedef IAVIStream *PAVISTREAM; // i.e. just a pointer
typedef struct {
DWORD fccType;
DWORD fccHandler;
DWORD dwFlags;
DWORD dwCaps;
WORD wPriority;
WORD wLanguage;
DWORD dwScale;
DWORD dwRate;
DWORD dwStart;
DWORD dwLength;
DWORD dwInitialFrames;
DWORD dwSuggestedBufferSize;
DWORD dwQuality;
DWORD dwSampleSize;
RECT rcFrame;
DWORD dwEditCount;
DWORD dwFormatChangeCount;
TCHAR szName[64];
} AVISTREAMINFO;
該包裝庫庫使用以下方法將NET“ pinvoke”定義為AVIFileCreateStream
:
//Create a new stream in an open AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileCreateStream(
int pfile,
out IntPtr ppavi,
ref AVISTREAMINFO ptr_streaminfo);
馬上,您會看到第一個參數定義不正確。
當“進行呼叫”時。...第一個參數僅將4個字節放置到堆棧中……而不是8個字節,然后對於第二個參數(這是指向指針的指針)將8個字節壓入( (因為使用了IntPtr)(“寫入”地址的地址),所以第三個參數是AVISTREAMINFO結構的地址。
因此,當AVIFileCreateStream
時,它訪問堆棧上的那些參數,但它們基本上是垃圾。.....它將嘗試使用具有錯誤值的指針(即,(第一個參數)指針地址中只有4個字節出現了)通過堆棧...,剩余的4個字節(8字節指針的)從堆棧上的“下一個”對象中填充...因此,指針地址很可能是垃圾。...這就是為什么您會遇到訪問沖突。
應該定義它的方式是這樣的(請注意,還有其他方法可以實現此目的):
[DllImport("avifil32.dll", SetLastError=true)]
public static extern int AVIFileCreateStream(IntPtr pfile, out IntPtr ppavi, ref AVISTREAMINFO psi);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.