2011-08-23 142 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; 
}