Windows 视频 - 将音频流添加到 AVI

发布于 2024-12-01 01:13:24 字数 1188 浏览 0 评论 0原文

我有一个非常简单的程序,将音频流添加到带有预先存在的视频流的 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,但这个决定超出了我的想象。而且我知道我不会检查任何结果,这可以稍后再进行。)

谢谢。

I have really simple program add the add an audio stream into an avi file with a pre-existing video stream.
The issue is that the resulting file contains a video stream but there does not appear to be any data in the stream.
The audio file is read by SDKwavefile from the DirectX samples.

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();

(Also, I know I shouldn't be using VFW anymore but that decision goes way above my head. And I know I'm not checking the results of anything, that can come later.)

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

何以畏孤独 2024-12-08 01:13:24

我尝试使用它来将 .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;
}

I tried to use this to add a .wav to an existing .avi (although I had a class CWaveSoundRead).
If you check the return codes, you get to AVIStreamWrite() which returns 0x80044065, which turns out to be AVIERR_UNSUPPORTED.

In hindsight, I'd say you called AVIFileCreateStream() before you filled in the AVISTREAMINFO object. Actually, now that I see it, it's hard to imagine your code compiling as-is, since audioInfo is defined AFTER AVIFileCreateStream!

Here's something I did, although it still mistakes the audio stream length:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文