簡體   English   中英

使用avimanager從圖像生成視頻會引發錯誤

[英]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庫。...但是您需要正確定義互操作/編組拼音。

  • c:\\ windows \\ system32 \\ avifil32.dll(64位)
  • c:\\ windows \\ syswow64 \\ avifil32.dll(32位)

在32位中(Microsoft使用ILP32數據模型)...

  • 一個int是4個字節
  • 指針是4個字節

在64位中(Microsoft使用LLP64或P64數據模型)。

  • 一個int是(仍然)4個字節
  • 指針是(現在)8個字節

(請參閱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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM