适用于Windows的视频 - 将音频流添加到AVI

时间:2011-08-23 16:21:13

标签: c++ avi vfw

我有一个非常简单的程序,将一个音频流添加到一个带有预先存在的视频流的avi文件中。 问题是生成的文件包含视频流,但流中似乎没有任何数据。 音频文件由SDKwavefile从DirectX示例中读取。

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,但这个决定超出了我的想法。而且我知道我不会检查任何结果,这可能会在以后发生。)

感谢。

1 个答案:

答案 0 :(得分: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;
}