Видео для Windows - Добавление аудиопотока в AVI - PullRequest
1 голос
/ 23 августа 2011

У меня действительно простая программа, добавляющая аудиопоток в 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 Ответ

3 голосов
/ 01 июня 2012

Я пытался использовать это, чтобы добавить .wav к существующему .avi (хотя у меня был класс CWaveSoundRead). Если вы проверите коды возврата, вы получите AVIStreamWrite (), который возвращает 0x80044065, который оказывается AVIERR_UNSUPPORTED.

Оглядываясь назад, я бы сказал, что вы вызывали AVIFileCreateStream () до того, как заполнили объект AVISTREAMINFO. На самом деле, теперь, когда я это вижу, трудно представить, как ваш код компилируется как есть, так как 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;
}
...