AVI-Erstellung



  • Servus,

    ich such jetzt schon seit längerer Zeit nach einer Möglichkeit aus mehreren Bmps eine avi-Datei zu erstellen. Ich bin auf folgendes Beispiel gestoßen:

    #include <math.h>
    #include <tchar.h>
    #include <windows.h>
    #include <vfw.h>
    
    #define LENG 10
    #define PIXELS 1000
    #define WIDTH 600
    #define HEIGHT 400
    #define LINE ((((WIDTH)*24+31)&~31)/8)
    #define SIZEIMAGE (LINE*(HEIGHT))
    #define PI 3.1415926535
    
    int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszCmdLine,int nCmdShow)
    {
        int i,j,s;
        AVISTREAMINFO si={streamtypeVIDEO,mmioFOURCC('M','P','G','4'),0,0,0,0,1,30,0,LENG,0,0,(DWORD)-1,0,{0,0,WIDTH,HEIGHT},0,0,_T("Video #1")};
        BITMAPINFOHEADER bmih={sizeof(BITMAPINFOHEADER),WIDTH,HEIGHT,1,24,BI_RGB, SIZEIMAGE,0,0,0,0};
        BYTE bBit[SIZEIMAGE];
        PAVIFILE pavi;
        PAVISTREAM pstm;
    
        memset(bBit,0,SIZEIMAGE);
        AVIFileInit();
    
        if (AVIFileOpen(&pavi,"TEST03.AVI", OF_CREATE | OF_WRITE | OF_SHARE_DENY_NONE,NULL)!=0)
            return 0;
        if (AVIFileCreateStream(pavi,&pstm,&si)!=0)
            return 0;
        if (AVIStreamSetFormat(pstm,0,&bmih,sizeof(BITMAPINFOHEADER))!=0)
            return 0;
    
        for (i=0;i<LENG;i++) {
            for (j=0;j<PIXELS;j++) {
                s=(int)(cos(PI*2*j/PIXELS)*min(WIDTH,HEIGHT)*(i*PIXELS+j)
                                                /(LENG*PIXELS*2)+WIDTH/2)*3
                    +(int)(sin(PI*2*j/PIXELS)*min(WIDTH,HEIGHT)*(i*PIXELS+j)
                                                /(LENG*PIXELS*2)+HEIGHT/2)*LINE;
                bBit[s]=bBit[s+1]=bBit[s+2]=0xff;
            }
            if (AVIStreamWrite(pstm,i,1,bBit,SIZEIMAGE,AVIIF_KEYFRAME,NULL,NULL)!=0)
                return 0;
        }
    
        AVIStreamRelease(pstm);
        AVIFileRelease(pavi);
        AVIFileExit();
    
        ShellExecute(NULL, "open", "TEST03.AVI", NULL, NULL, SW_SHOW);
    
        return 0;
    }
    

    Wenn man Dev-C++ nutzt, muss libvfw32.a einbinden. Was mich interessieren würde, wäre, wie man in das Byte-Array bBit ein Bild hineinschreibt. Wenn das nicht funktioniert: Kann man die einzelnen Pixel statt weiß auch z.B. rot färben. Hier werden sie, soweit ich weiss, weiß gefärbt:

    bBit[s]=bBit[s+1]=bBit[s+2]=0xff;
    

    Danke für eure Hilfe,
    Felix



  • Probier einfach mal ein bisschen rum. Zum Beispiel:

    bBit[s]=0xff;
    bBit[s+1]=0x00;
    bBit[s+2]=0x00;
    


  • Danke für deine Antwort. Sie hat mir zu diesem Programm verholfen:

    #include <math.h>
    #include <tchar.h>
    #include <windows.h>
    #include <vfw.h>
    
    #define LENG 10
    #define PIXELS 1000
    #define WIDTH 800
    #define HEIGHT 600
    #define LINE ((((WIDTH)*24+31)&~31)/8)
    #define SIZEIMAGE (LINE*(HEIGHT))
    
    int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszCmdLine,int nCmdShow)
    {
        int i,j,s;
        AVISTREAMINFO si={streamtypeVIDEO,mmioFOURCC('M','P','G','4'),0,0,0,0,1,30,0,LENG,0,0,(DWORD)-1,0,{0,0,WIDTH,HEIGHT},0,0,_T("Video #1")};
        BITMAPINFOHEADER bmih={sizeof(BITMAPINFOHEADER),WIDTH,HEIGHT,1,24,BI_RGB, SIZEIMAGE,0,0,0,0};
        BYTE bBit[SIZEIMAGE];
        PAVIFILE pavi;
        PAVISTREAM pstm;
    
        HBITMAP hBmp; 
        BITMAP bm;
        HDC hdc;
        HDC hdc2;
        HDC hdcBmp;
        COLORREF Farb;
    
        int x,y;
    
        hBmp = (HBITMAP) LoadImage(NULL, "test1.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
        GetObject(hBmp, sizeof(BITMAP), &bm);
    
        hdcBmp = CreateCompatibleDC(hdc); 
    	SelectObject(hdcBmp, hBmp);
    	BitBlt(hdc,0,0, bm.bmWidth,bm.bmHeight, hdcBmp, 0,0, SRCCOPY);
    
        StretchBlt(hdc2,0,0,800,600,hdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
    
        memset(bBit,0,SIZEIMAGE);
        AVIFileInit();
    
        if (AVIFileOpen(&pavi,"TEST03.AVI", OF_CREATE | OF_WRITE | OF_SHARE_DENY_NONE,NULL)!=0)
            return 0;
        if (AVIFileCreateStream(pavi,&pstm,&si)!=0)
            return 0;
        if (AVIStreamSetFormat(pstm,0,&bmih,sizeof(BITMAPINFOHEADER))!=0)
            return 0;
    
        for(i=0;i<100;i++)
        {
                    s=0;
                    for(x=0;x<800;x++)
                    {
                          for(y=599;y>-1;y--)
                          {    
                               Farb=GetPixel(hdc2,x,y);
                               bBit[s]=GetBValue(Farb);
                               bBit[s+1]=GetGValue(Farb);
                               bBit[s+2]=GetRValue(Farb);
                               s=s+3;
                           }
                    }
                    if (AVIStreamWrite(pstm,i,1,bBit,SIZEIMAGE,AVIIF_KEYFRAME,NULL,NULL)!=0)
                    return 0;
        } 
    
        AVIStreamRelease(pstm);
        AVIFileRelease(pavi);
        AVIFileExit();
        ShellExecute(NULL, "open", "TEST03.AVI", NULL, NULL, SW_SHOW);
    
        return 0;
    }
    

    Das Programm soll ein Bild in eine avi-Datei schreiben. Allerdings kommt es nur zu einer weißen Fläche. Was hab ich falsch gemacht?



  • Moin,

    http://www.wischik.com/lu/programmer/avi_utils.html

    sollte genug Beispiele enthalten, denke ich ... 😉

    Gruß



  • Servus C++Greenhorn,

    du hast Recht, die avi_utils Bibliothek funktioniert wunderbar, wie man an diesem Programm erkennen kann:

    #include <windows.h>
    #include <vfw.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "avi_utils.h"
    #include "avi_utils.cpp"
    
    int dc2bitmap(HDC hdc, int width, int height) 
    { 
       HDC hdc2;
       HBITMAP aBmp;
       BITMAPINFO bi;
       HGDIOBJ OldObj; 
       void *dibvalues;
       HANDLE fileHandle;
       BITMAPFILEHEADER bmfh;
       BITMAPINFOHEADER bmih;
       DWORD bytes_write; 
       DWORD bytes_written;
    
       hdc2=CreateCompatibleDC(hdc);
    
       ZeroMemory(&bmih,sizeof(BITMAPINFOHEADER));
       bmih.biSize=sizeof(BITMAPINFOHEADER);
       bmih.biHeight=height; 
       bmih.biWidth=width;
       bmih.biPlanes=1;
       bmih.biBitCount=24;
       bmih.biCompression=BI_RGB; 
       bmih.biSizeImage = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3) * bmih.biHeight;
       bmih.biXPelsPerMeter = 0;
       bmih.biYPelsPerMeter = 0; 
       bmih.biClrImportant = 0; 
       bi.bmiHeader=bmih; 
    
       aBmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&dibvalues,NULL,0); 
       if (aBmp==NULL) 
       { 
                  return 0;
    
       } 
    
       OldObj=SelectObject(hdc2,aBmp); 
    
       BitBlt(hdc2,0,0,width,height,hdc,0,0,SRCCOPY); 
    
       ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER)); 
    
       bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); 
       bmfh.bfSize=(3*bmih.biHeight*bmih.biWidth)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); 
       bmfh.bfType=0x4d42; 
       bmfh.bfReserved1 = 0; 
       bmfh.bfReserved2 = 0; 
    
       fileHandle=CreateFile("test.bmp",GENERIC_READ | GENERIC_WRITE,(DWORD)0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL); 
       if (fileHandle==INVALID_HANDLE_VALUE) 
       { 
               return 0;
       } 
    
       bytes_write=sizeof(BITMAPFILEHEADER); 
       if (!WriteFile(fileHandle,(void*)&bmfh,bytes_write,&bytes_written,NULL)) 
       { 
               return 0;
       } 
    
       bytes_write=sizeof(BITMAPINFOHEADER); 
       if (!WriteFile(fileHandle,(void*)&bmih,bytes_write,&bytes_written,NULL)) 
       { 
               return 0; 
       } 
    
       bytes_write=bmih.biSizeImage;
       if (!WriteFile(fileHandle,(void*)dibvalues,bytes_write,&bytes_written,NULL)) 
       { 
            return 0;
       } 
    
       CloseHandle(fileHandle);
       DeleteObject(SelectObject(hdc2,OldObj)); 
       DeleteDC(hdc2); 
    
       return 1; 
    } 
    
    int WINAPI WinMain (HINSTANCE hThisInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nFunsterStil)
    
    {
    RECT rt;
    HWND hWnd; 
    int width, height = 0;
    HDC hdc;
    HBITMAP hbm;
    int i;
    
    HAVI avi = CreateAvi("test1.avi",750,NULL);
    
    for(i=0;i<100;i++)
    {
        hWnd=GetDesktopWindow(); 
        hdc= GetDC(hWnd); 
        GetWindowRect(hWnd,&rt); 
        width=rt.right-rt.left; 
        height=rt.bottom-rt.top; 
    
        dc2bitmap(hdc,  width,  height);
    
        hbm=(HBITMAP)LoadImage(NULL,"test.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
        AddAviFrame(avi,hbm);
        DeleteObject(hbm);
    }
    CloseAvi(avi);
    
    return 0;
    }
    

    Aber gibt es auch eine Möglichkeit ohne C++?



  • Portier die paar Zeilen doch einfach nach C ... nicht?



  • Ich habs' jetzt mal probiert. Aber ich kenn mich in C++ nur ganz wenig aus. Wie übersetzt man ein "new" oder ein "delete" z.B. im folgenden Sourcecode:

    HAVI CreateAvi(const char *fn, int frameperiod, const WAVEFORMATEX *wfx)
    { IAVIFile *pfile;
      AVIFileInit();
      HRESULT hr = AVIFileOpen(&pfile, fn, OF_WRITE|OF_CREATE, NULL);
      if (hr!=AVIERR_OK) {AVIFileExit(); return NULL;}
      TAviUtil *au = new TAviUtil;
      au->pfile = pfile;
      if (wfx==NULL) ZeroMemory(&au->wfx,sizeof(WAVEFORMATEX)); else CopyMemory(&au->wfx,wfx,sizeof(WAVEFORMATEX));
      au->period = frameperiod;
      au->as=0; au->ps=0; au->psCompressed=0;
      au->nframe=0; au->nsamp=0;
      au->iserr=false;
      return (HAVI)au;
    }
    
    HRESULT CloseAvi(HAVI avi)
    { if (avi==NULL) return AVIERR_BADHANDLE;
      TAviUtil *au = (TAviUtil*)avi;
      if (au->as!=0) AVIStreamRelease(au->as); au->as=0;
      if (au->psCompressed!=0) AVIStreamRelease(au->psCompressed); au->psCompressed=0;
      if (au->ps!=0) AVIStreamRelease(au->ps); au->ps=0;
      if (au->pfile!=0) AVIFileRelease(au->pfile); au->pfile=0;
      AVIFileExit();
      delete au;
      return S_OK;
    }
    


  • Sieh dir mal malloc und free an ...

    Gruß



  • Es hat funktioniert! Für alle, die eine Avi-C-Bibliothek bevorzugen:

    /*
    Avi_Utils.h
    Written by Lucian Wischik, used in the ScreenCapture class
    */
    
    #ifndef _avi_utils_H
    #define _avi_utils_H
    
    // AVI utilities -- for creating avi files
    // (c) 2002 Lucian Wischik. No restrictions on use.
    
    DECLARE_HANDLE(HAVI);
    // An HAVI identifies an avi file that is being created
    
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #include <vfw.h>
    
    // First, we'll define the WAV file format.
    #include <pshpack1.h>
    typedef struct
    { char id[4];         //="fmt "
      unsigned long size; //=16
      short wFormatTag;   //=WAVE_FORMAT_PCM=1
      unsigned short wChannels;       //=1 or 2 for mono or stereo
      unsigned long dwSamplesPerSec;  //=11025 or 22050 or 44100
      unsigned long dwAvgBytesPerSec; //=wBlockAlign * dwSamplesPerSec
      unsigned short wBlockAlign;     //=wChannels * (wBitsPerSample==8?1:2)
      unsigned short wBitsPerSample;  //=8 or 16, for bits per sample
    } FmtChunk;
    
    typedef struct
    { char id[4];            //="data"
      unsigned long size;    //=datsize, size of the following array
      unsigned char data[1]; //=the raw data goes here
    } DataChunk;
    
    typedef struct
    { char id[4];         //="RIFF"
      unsigned long size; //=datsize+8+16+4
      char type[4];       //="WAVE"
      FmtChunk fmt;
      DataChunk dat;
    } WavChunk;
    #include <poppack.h>
    
    // This is the internal structure represented by the HAVI handle:
    typedef struct
    { IAVIFile *pfile;    // created by CreateAvi
      WAVEFORMATEX wfx;   // as given to CreateAvi (.nChanels=0 if none was given). Used when audio stream is first created.
      int period;         // specified in CreateAvi, used when the video stream is first created
      IAVIStream *as;     // audio stream, initialised when audio stream is first created
      IAVIStream *ps, *psCompressed;  // video stream, when first created
      unsigned long nframe, nsamp;    // which frame will be added next, which sample will be added next
      BOOL iserr;         // if true, then no function will do anything
    } TAviUtil;
    
    HAVI CreateAvi(const char *fn, int frameperiod, const WAVEFORMATEX *wfx)
    { IAVIFile *pfile;
      AVIFileInit();
      HRESULT hr = AVIFileOpen(&pfile, fn, OF_WRITE|OF_CREATE, NULL);
      if (hr!=AVIERR_OK) {AVIFileExit(); return NULL;}
      TAviUtil *au;
      au=(TAviUtil *) malloc(1000);
      au->pfile = pfile;
      if (wfx==NULL) ZeroMemory(&au->wfx,sizeof(WAVEFORMATEX)); else CopyMemory(&au->wfx,wfx,sizeof(WAVEFORMATEX));
      au->period = frameperiod;
      au->as=0; au->ps=0; au->psCompressed=0;
      au->nframe=0; au->nsamp=0;
      au->iserr=FALSE;
      return (HAVI)au;
    }
    
    HRESULT CloseAvi(HAVI avi)
    { if (avi==NULL) return AVIERR_BADHANDLE;
      TAviUtil *au = (TAviUtil*)avi;
      if (au->as!=0) AVIStreamRelease(au->as); au->as=0;
      if (au->psCompressed!=0) AVIStreamRelease(au->psCompressed); au->psCompressed=0;
      if (au->ps!=0) AVIStreamRelease(au->ps); au->ps=0;
      if (au->pfile!=0) AVIFileRelease(au->pfile); au->pfile=0;
      AVIFileExit();
      free(au);
      return S_OK;
    }
    
    HRESULT SetAviVideoCompression(HAVI avi, HBITMAP hbm, AVICOMPRESSOPTIONS *opts, BOOL ShowDialog, HWND hparent)
    { if (avi==NULL) return AVIERR_BADHANDLE;
      if (hbm==NULL) return AVIERR_BADPARAM;
      DIBSECTION dibs; int sbm = GetObject(hbm,sizeof(dibs),&dibs);
      if (sbm!=sizeof(DIBSECTION)) return AVIERR_BADPARAM;
      TAviUtil *au = (TAviUtil*)avi;
      if (au->iserr) return AVIERR_ERROR;
      if (au->psCompressed!=0) return AVIERR_COMPRESSOR;
      //
      if (au->ps==0) // create the stream, if it wasn't there before
      { AVISTREAMINFO strhdr; ZeroMemory(&strhdr,sizeof(strhdr));
        strhdr.fccType = streamtypeVIDEO;// stream type
        strhdr.fccHandler = 0; 
        strhdr.dwScale = au->period;
        strhdr.dwRate = 1000;
        strhdr.dwSuggestedBufferSize  = dibs.dsBmih.biSizeImage;
        SetRect(&strhdr.rcFrame, 0, 0, dibs.dsBmih.biWidth, dibs.dsBmih.biHeight);
        HRESULT hr=AVIFileCreateStream(au->pfile, &au->ps, &strhdr);
        if (hr!=AVIERR_OK) {au->iserr=TRUE; return hr;}
      }
      //
      if (au->psCompressed==0) // set the compression, prompting dialog if necessary
      { AVICOMPRESSOPTIONS myopts; ZeroMemory(&myopts,sizeof(myopts));
        AVICOMPRESSOPTIONS *aopts[1];
        if (opts!=NULL) aopts[0]=opts; else aopts[0]=&myopts;
        if (ShowDialog)
        { BOOL res = (BOOL)AVISaveOptions(hparent,0,1,&au->ps,aopts);
          if (!res) {AVISaveOptionsFree(1,aopts); au->iserr=TRUE; return AVIERR_USERABORT;}
        }
        HRESULT hr = AVIMakeCompressedStream(&au->psCompressed, au->ps, aopts[0], NULL);
        AVISaveOptionsFree(1,aopts);
        if (hr != AVIERR_OK) {au->iserr=TRUE; return hr;}
        DIBSECTION dibs; GetObject(hbm,sizeof(dibs),&dibs);
        hr = AVIStreamSetFormat(au->psCompressed, 0, &dibs.dsBmih, dibs.dsBmih.biSize+dibs.dsBmih.biClrUsed*sizeof(RGBQUAD));
        if (hr!=AVIERR_OK) {au->iserr=TRUE; return hr;}
      }
      //
      return AVIERR_OK;
    }
    
    HRESULT AddAviFrame(HAVI avi, HBITMAP hbm)
    { if (avi==NULL) return AVIERR_BADHANDLE;
      if (hbm==NULL) return AVIERR_BADPARAM;
      DIBSECTION dibs; int sbm = GetObject(hbm,sizeof(dibs),&dibs);
      if (sbm!=sizeof(DIBSECTION)) return AVIERR_BADPARAM;
      TAviUtil *au = (TAviUtil*)avi;
      if (au->iserr) return AVIERR_ERROR;
      //
      if (au->ps==0) // create the stream, if it wasn't there before
      { AVISTREAMINFO strhdr; ZeroMemory(&strhdr,sizeof(strhdr));
        strhdr.fccType = streamtypeVIDEO;// stream type
        strhdr.fccHandler = 0; 
        strhdr.dwScale = au->period;
        strhdr.dwRate = 1000;
        strhdr.dwSuggestedBufferSize  = dibs.dsBmih.biSizeImage;
        SetRect(&strhdr.rcFrame, 0, 0, dibs.dsBmih.biWidth, dibs.dsBmih.biHeight);
        HRESULT hr=AVIFileCreateStream(au->pfile, &au->ps, &strhdr);
        if (hr!=AVIERR_OK) {au->iserr=TRUE; return hr;}
      }
      //
      // create an empty compression, if the user hasn't set any
      if (au->psCompressed==0)
      { AVICOMPRESSOPTIONS opts; ZeroMemory(&opts,sizeof(opts));
        opts.fccHandler=mmioFOURCC('D','I','B',' '); 
        HRESULT hr = AVIMakeCompressedStream(&au->psCompressed, au->ps, &opts, NULL);
        if (hr != AVIERR_OK) {au->iserr=TRUE; return hr;}
        hr = AVIStreamSetFormat(au->psCompressed, 0, &dibs.dsBmih, dibs.dsBmih.biSize+dibs.dsBmih.biClrUsed*sizeof(RGBQUAD));
        if (hr!=AVIERR_OK) {au->iserr=TRUE; return hr;}
      }
      //
      //Now we can add the frame
      HRESULT hr = AVIStreamWrite(au->psCompressed, au->nframe, 1, dibs.dsBm.bmBits, dibs.dsBmih.biSizeImage, AVIIF_KEYFRAME, NULL, NULL);
      if (hr!=AVIERR_OK) {au->iserr=TRUE; return hr;}
      au->nframe++; return S_OK;
    }
    
    HRESULT AddAviAudio(HAVI avi, void *dat, unsigned long numbytes)
    { if (avi==NULL) return AVIERR_BADHANDLE;
      if (dat==NULL || numbytes==0) return AVIERR_BADPARAM;
      TAviUtil *au = (TAviUtil*)avi;
      if (au->iserr) return AVIERR_ERROR;
      if (au->wfx.nChannels==0) return AVIERR_BADFORMAT;
      unsigned long numsamps = numbytes*8 / au->wfx.wBitsPerSample;
      if ((numsamps*au->wfx.wBitsPerSample/8)!=numbytes) return AVIERR_BADPARAM;
      //
      if (au->as==0) // create the stream if necessary
      { AVISTREAMINFO ahdr; ZeroMemory(&ahdr,sizeof(ahdr));
        ahdr.fccType=streamtypeAUDIO;
        ahdr.dwScale=au->wfx.nBlockAlign;
        ahdr.dwRate=au->wfx.nSamplesPerSec*au->wfx.nBlockAlign; 
        ahdr.dwSampleSize=au->wfx.nBlockAlign;
        ahdr.dwQuality=(DWORD)-1;
        HRESULT hr = AVIFileCreateStream(au->pfile, &au->as, &ahdr);
        if (hr!=AVIERR_OK) {au->iserr=TRUE; return hr;}
        hr = AVIStreamSetFormat(au->as,0,&au->wfx,sizeof(WAVEFORMATEX));
        if (hr!=AVIERR_OK) {au->iserr=TRUE; return hr;}
      }
      //
      // now we can write the data
      HRESULT hr = AVIStreamWrite(au->as,au->nsamp,numsamps,dat,numbytes,0,NULL,NULL);
      if (hr!=AVIERR_OK) {au->iserr=TRUE; return hr;}
      au->nsamp+=numsamps; return S_OK;
    }
    
    HRESULT AddAviWav(HAVI avi, const char *src, DWORD flags)
    { if (avi==NULL) return AVIERR_BADHANDLE;
      if (flags!=SND_MEMORY && flags!=SND_FILENAME) return AVIERR_BADFLAGS;
      if (src==0) return AVIERR_BADPARAM;
      TAviUtil *au = (TAviUtil*)avi;
      if (au->iserr) return AVIERR_ERROR;
      //
      char *buf=0; WavChunk *wav = (WavChunk*)src;
      if (flags==SND_FILENAME)
      { HANDLE hf=CreateFile(src,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
        if (hf==INVALID_HANDLE_VALUE) {au->iserr=TRUE; return AVIERR_FILEOPEN;}
        DWORD size = GetFileSize(hf,NULL);
        char *buf;
        buf=(char *) malloc(size);
        DWORD red; ReadFile(hf,buf,size,&red,NULL);
        CloseHandle(hf);
        wav = (WavChunk*)buf;
      }
      //
      // check that format doesn't clash
      BOOL badformat=FALSE;
      if (au->wfx.nChannels==0)
      { au->wfx.wFormatTag=wav->fmt.wFormatTag;
        au->wfx.cbSize=0;
        au->wfx.nAvgBytesPerSec=wav->fmt.dwAvgBytesPerSec;
        au->wfx.nBlockAlign=wav->fmt.wBlockAlign;
        au->wfx.nChannels=wav->fmt.wChannels;
        au->wfx.nSamplesPerSec=wav->fmt.dwSamplesPerSec;
        au->wfx.wBitsPerSample=wav->fmt.wBitsPerSample;
      }
      else
      { if (au->wfx.wFormatTag!=wav->fmt.wFormatTag) badformat=TRUE;
        if (au->wfx.nAvgBytesPerSec!=wav->fmt.dwAvgBytesPerSec) badformat=TRUE;
        if (au->wfx.nBlockAlign!=wav->fmt.wBlockAlign) badformat=TRUE;
        if (au->wfx.nChannels!=wav->fmt.wChannels) badformat=TRUE;
        if (au->wfx.nSamplesPerSec!=wav->fmt.dwSamplesPerSec) badformat=TRUE;
        if (au->wfx.wBitsPerSample!=wav->fmt.wBitsPerSample) badformat=TRUE;
      }
      if (badformat) {if (buf!=0) free(buf); return AVIERR_BADFORMAT;}
      //
      if (au->as==0) // create the stream if necessary
      { AVISTREAMINFO ahdr; ZeroMemory(&ahdr,sizeof(ahdr));
        ahdr.fccType=streamtypeAUDIO;
        ahdr.dwScale=au->wfx.nBlockAlign;
        ahdr.dwRate=au->wfx.nSamplesPerSec*au->wfx.nBlockAlign; 
        ahdr.dwSampleSize=au->wfx.nBlockAlign;
        ahdr.dwQuality=(DWORD)-1;
        HRESULT hr = AVIFileCreateStream(au->pfile, &au->as, &ahdr);
        if (hr!=AVIERR_OK) {if (buf!=0) free(buf); au->iserr=TRUE; return hr;}
        hr = AVIStreamSetFormat(au->as,0,&au->wfx,sizeof(WAVEFORMATEX));
        if (hr!=AVIERR_OK) {if (buf!=0) free(buf); au->iserr=TRUE; return hr;}
      }
      //
      // now we can write the data
      unsigned long numbytes = wav->dat.size;
      unsigned long numsamps = numbytes*8 / au->wfx.wBitsPerSample;
      HRESULT hr = AVIStreamWrite(au->as,au->nsamp,numsamps,wav->dat.data,numbytes,0,NULL,NULL);
      if (buf!=0) free(buf);
      if (hr!=AVIERR_OK) {au->iserr=TRUE; return hr;}
      au->nsamp+=numsamps; return S_OK;
    }
    
    unsigned int FormatAviMessage(HRESULT code, char *buf,unsigned int len)
    { const char *msg="unknown avi result code";
      switch (code)
      { case S_OK: msg="Success"; break;
        case AVIERR_BADFORMAT: msg="AVIERR_BADFORMAT: corrupt file or unrecognized format"; break;
        case AVIERR_MEMORY: msg="AVIERR_MEMORY: insufficient memory"; break;
        case AVIERR_FILEREAD: msg="AVIERR_FILEREAD: disk error while reading file"; break;
        case AVIERR_FILEOPEN: msg="AVIERR_FILEOPEN: disk error while opening file"; break;
        case REGDB_E_CLASSNOTREG: msg="REGDB_E_CLASSNOTREG: file type not recognised"; break;
        case AVIERR_READONLY: msg="AVIERR_READONLY: file is read-only"; break;
        case AVIERR_NOCOMPRESSOR: msg="AVIERR_NOCOMPRESSOR: a suitable compressor could not be found"; break;
        case AVIERR_UNSUPPORTED: msg="AVIERR_UNSUPPORTED: compression is not supported for this type of data"; break;
        case AVIERR_INTERNAL: msg="AVIERR_INTERNAL: internal error"; break;
        case AVIERR_BADFLAGS: msg="AVIERR_BADFLAGS"; break;
        case AVIERR_BADPARAM: msg="AVIERR_BADPARAM"; break;
        case AVIERR_BADSIZE: msg="AVIERR_BADSIZE"; break;
        case AVIERR_BADHANDLE: msg="AVIERR_BADHANDLE"; break;
        case AVIERR_FILEWRITE: msg="AVIERR_FILEWRITE: disk error while writing file"; break;
        case AVIERR_COMPRESSOR: msg="AVIERR_COMPRESSOR"; break;
        case AVIERR_NODATA: msg="AVIERR_READONLY"; break;
        case AVIERR_BUFFERTOOSMALL: msg="AVIERR_BUFFERTOOSMALL"; break;
        case AVIERR_CANTCOMPRESS: msg="AVIERR_CANTCOMPRESS"; break;
        case AVIERR_USERABORT: msg="AVIERR_USERABORT"; break;
        case AVIERR_ERROR: msg="AVIERR_ERROR"; break;
      }
      unsigned int mlen=(unsigned int)strlen(msg);
      if (buf==0 || len==0) return mlen;
      unsigned int n=mlen; if (n+1>len) n=len-1;
      strncpy(buf,msg,n); buf[n]=0;
      return mlen;
    }
    
    #endif
    

Anmelden zum Antworten