2011-08-23 201 views
1

我真的很簡單的程序添加一個音頻流添加到一個AVI文件與預先存在的視頻流。 問題是生成的文件包含視頻流,但流中沒有任何數據。 音頻文件由DirectX示例中的SDKwavefile讀取。Windows視頻 - 添加音頻流到AVI

AVIFileInit(); 

PAVIFILE avi; 
AVIFileOpen(&avi, argv[1], OF_WRITE, NULL); 

CWaveFile wav; 
wav.Open(argv[2], NULL, WAVEFILE_READ); 
WAVEFORMATEX *wavFormat = wav.GetFormat(); 

PAVISTREAM audioStream; 
AVIFileCreateStream(avi, &audioStream, &audioInfo); 

AVISTREAMINFO audioInfo; 
memset(&audioInfo, 0, sizeof(AVISTREAMINFO)); 
audioInfo.fccType = streamtypeAUDIO; 
audioInfo.dwScale = wavFormat->nBlockAlign; 
audioInfo.dwRate = wavFormat->nSamplesPerSec * wavFormat->nBlockAlign; 
audioInfo.dwSampleSize = wavFormat->nBlockAlign; 
audioInfo.dwQuality = (DWORD)-1; 
AVIStreamSetFormat(audioStream, 0, wavFormat, sizeof(WAVEFORMATEX)); 

BYTE *data = (BYTE *)malloc(wav.GetSize()); 
DWORD sizeRead; 
wav.Read(data, wav.GetSize(), &sizeRead); 
AVIStreamWrite(audioStream, 0, (wav.GetSize() * 8)/wavFormat->wBitsPerSample, data, wav.GetSize(), 0, NULL, NULL); 

AVIStreamRelease(audioStream); 

free(data); 

wav.Close(); 

AVIFileRelease(avi); 
AVIFileExit(); 

(另外,我知道我不應該再使用VFW,但這一決定必須高於我的頭的方式,我也知道我不檢查任何事物的結果,可以晚一點。)

謝謝。

回答

3

我試圖用它來添加一個.wav到現有的.avi(雖然我有一個類CWaveSoundRead)。 如果你檢查返回碼,你會得到AVIStreamWrite(),它返回0x80044065,結果是AVIERR_UNSUPPORTED。

事後看來,我會說你在填充AVISTREAMINFO對象之前調用了AVIFileCreateStream()。實際上,現在我明白了,很難想象你的代碼是按原樣編譯的,因爲audioInfo是在AVIFileCreateStream之後定義的!

這裏的東西我做到了,儘管它仍然失誤音頻流長:

struct FmtChunk { 
    char id[4];   //="fmt " 
    unsigned long size;    //=16 or 0x28 
    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 
}; 

struct DataChunk { 
    char id[4]; //="data" 
    unsigned long size; //=datsize, size of the following array 
    unsigned char data[1]; //=the raw data goes here 
}; 

struct WavChunk { 
    char id[4]; //="RIFF" 
    unsigned long size; //=datsize+8+16+4 
    char type[4]; //="WAVE" 
}; 

bool Q_AVI_AddWav(cstring fnameVideo,cstring fnameAudio) 
// Adds a .wav file to an existing .avi (with video stream) 
{ 
    IAVIStream* m_pStreamAudio=0; 
    HRESULT hr; 

    AVIFileInit(); 

    PAVIFILE avi; 
    hr=AVIFileOpen(&avi, fnameVideo,OF_WRITE,NULL); 
    CHECK(hr,"AVIFileOpen"); 

    WavChunk wav; 
    FmtChunk fmt; 
    DataChunk dat; 

    //read wav file 
    FILE *fr; 
    int pos; 

    fr=qfopen(fnameAudio,"rb"); 

    // Read header 
    fread(&wav,1,sizeof(wav),fr); 

    // Read 'fmt' chunk; may be 16 or 40 in length 
    pos=ftell(fr); 
    fread(&fmt,1,sizeof(fmt),fr); 
    if(fmt.size==40)fseek(fr,40-16,SEEK_CUR); // Skip rest of fmt 
    // else it's ok 

    // Read data specs 
    fread(&dat,sizeof(dat),1,fr); 
    char *buf = new char[dat.size]; 
    qdbg("Wav data %d bytes\n",dat.size); 
    fread(buf,1,dat.size,fr); 
    qfclose(fr); 

    // set wave format info 
    WAVEFORMATEX wfx; 
    wfx.wFormatTag=fmt.wFormatTag; 
    wfx.cbSize=0; 
    wfx.nAvgBytesPerSec=fmt.dwAvgBytesPerSec; 
    wfx.nBlockAlign=fmt.wBlockAlign; 
    wfx.nChannels=fmt.wChannels; 
    wfx.nSamplesPerSec=fmt.dwSamplesPerSec; 
    wfx.wBitsPerSample=fmt.wBitsPerSample; 

    // create audio stream 
    AVISTREAMINFO ahdr; ZeroMemory(&ahdr,sizeof(ahdr)); 
    ahdr.fccType=streamtypeAUDIO; 
    ahdr.dwScale=wfx.nBlockAlign; 
    ahdr.dwRate=wfx.nSamplesPerSec*wfx.nBlockAlign; 
    ahdr.dwSampleSize=wfx.nBlockAlign; 
    ahdr.dwQuality=(DWORD)-1; 
    hr=AVIFileCreateStream(avi, &m_pStreamAudio, &ahdr); 
    CHECK(hr,"AVIFileCreateStream"); 
    if(hr!=AVIERR_OK) {if (buf) QDELETE_ARRAY(buf); /*delete[] buf;*/ return false;} 
    hr = AVIStreamSetFormat(m_pStreamAudio,0,&wfx,sizeof(WAVEFORMATEX)); 
    CHECK(hr,"AVIStreamSetFormat"); 
    if(hr!=AVIERR_OK) {if (buf) QDELETE_ARRAY(buf); /*delete[] buf;*/ return false;} 

    //write audio stream 
    unsigned long numbytes = dat.size; 
    unsigned long numsamps = fmt.wChannels*numbytes*8/wfx.wBitsPerSample; 
    hr = AVIStreamWrite(m_pStreamAudio,0,numsamps,buf,numbytes,0,0,0); 
    CHECK(hr,"AVIStreamWrite"); 
    qdbg("Write numsamps %d, numbytes %d\n",numsamps,numbytes); 
    QDELETE_ARRAY(buf); //if(buf)delete[] buf; 

    // Release audio stream 
    AVIStreamRelease(m_pStreamAudio); 

    // Close AVI 
    hr=AVIFileRelease(avi); 
    CHECK(hr,"AVIFileRelease"); 

    // Close VFW 
    AVIFileExit(); 

    return hr==AVIERR_OK; 
}