未圧縮のPCMならAVIファイルに時間ピッタリで入れ込むことが簡単にできるんですよ。
これがMP3になると、ネタ的に古すぎるのか(0年台初期の話ですからねぇ)
ググっても出てこない、出てきても、どうやるの?って質問ばっかり。
やっと、論理的に整合のつくAPI引数設定がわかりました。
1152がキモな数値。
AVICreateStream()の引数のAVISTREAMINFOの設定を以下のソースコードのように
します。
あとは、waveInOpen()でマイクを設定して、バッファに溜め込まれたPCMデータを
定期的にacmStreamConvert()でMP3データに変換して
AVIStreamWrite()で流し込んでやればいいだけ、のはず。(まだ確認してない)
ただし、Lameのコーデックだと、デフォルトでビットレート可変になってしまっているのか
失敗します。
Lameコーデックのエンコード設定をするコードを書けばいいんでしょうけど、
そこまで調べるのが面倒。。。
ということで、OSに付属のFraunhoferのコーデックを使うことになるのですが、
MSも意地悪な設定をしていて、レジストリを書き換えないとエンコードも可能な
MP3コーデックを使用できないみたい。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32
のmsacm.l3acmの値をl3codecp.acmに変更することで、エンコードも可能なコーデック
'MPEG Layer-3'を使用できるようになります。
これで、キャプチャした動画/音声をx264/MP3のAVIファイルとして作成できるようになった!
(と思う^^;;;)
※
まだ、STREAMINFOの設定がこなれていないんだよね。
PCMでAUDIO_CAPTURE_BITSPERSAMPLE=24のときどうなるかではっきりすると思う。
#define VIDEO_CODEC 0x34363278 // 'x''2''6''4'
#define VIDEO_CAPTURE_FPS 15
#define VIDEO_CAPTURE_WIDTH 640
#define VIDEO_CAPTURE_HEIGHT 480
#define VIDEO_CAPTURE_BITSPERSAMPLE 32
#define AUDIO_CAPTURE_SAMPLINGFREQUENCY 32000
#define AUDIO_CAPTURE_CHANNELS 2
#define AUDIO_CAPTURE_BITSPERSAMPLE 16
#define MP3_BITRATE 128
#define MP3_SAMPLESPERFRAME 1152
#define MP3_FRAMESIZE (MP3_SAMPLESPERFRAME*((MP3_BITRATE*1000)/8)/AUDIO_CAPTURE_SAMPLINGFREQUENCY)
PAVIFILE pavifile;
PAVISTREAM pvid, paud;
HACMDRIVERID hmp3driverid=NULL;
AVIFileOpen(pavifile, filename, OF_WRITE|OF_CREATE, NULL);
BITMAPINFOHEADER bi;
memset(&bi, 0, sizeof(BITMAPINFOHEADER));
bi.biSize=sizeof(BITMAPINFOHEADER);
bi.biWidth=VIDEO_CAPTURE_WIDTH;
bi.biHeight=VIDEO_CAPTURE_HEIGHT;
bi.biPlanes=1;
bi.biBitCount=VIDEO_CAPTURE_BITSPERSAMPLE;
bi.biCompression=BI_RGB;
bi.biSizeImage=bi.biHeight*bi.biWidth*(bi.biBitCount/8);
RECT rc;
SetRect(0, 0, VIDEO_CAPTURE_WIDTH, VIDEO_CAPTURE_HEIGHT);
WAVEFORMATEX wfx;
memset(&wfx, 0, sizeof(WAVEFORMATEX));
wfx.wFormatTag=WAVE_FORMAT_PCM;
wfx.nChannels=AUDIO_CAPTURE_CHANNELS;
wfx.nSamplesPerSec=AUDIO_CAPTURE_SAMPLINGFREQUENCY;
wfx.wBitsPerSample=AUDIO_CAPTURE_BITSPERSAMPLE
wfx.nBlockAlign=wfx.wBitsPerSample/8*wfx.nChannels;
wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;
MPEGLAYER3WAVEFORMAT mp3wf;
memset(&mp3wf, 0, sizeof(MPEGLAYER3WAVEFORMAT));
mp3wf.wfx.wFormatTag=WAVE_FORMAT_MPEGLAYER3;
mp3wf.wfx.nChannels=AUDIO_CAPTURE_CHANNELS;
mp3wf.wfx.nSamplesPerSec=AUDIO_CAPTURE_SAMPLINGFREQUENCY;
mp3wf.wfx.wBitsPerSample=0;
mp3wf.wfx.nBlockAlign=1;
mp3wf.wfx.nAvgBytesPerSec=(MP3_BITRATE*1000)/8;
mp3wf.wfx.cbSize=MPEGLAYER3_WFX_EXTRA_BYTES;
mp3wf.wID=MPEGLAYER3_ID_MPEG;
mp3wf.fdwFlags=MPEGLAYER3_FLAG_PADDING_OFF;
mp3wf.nFramesPerBlock=1;
mp3wf.nBlockSize=MP3_FRAMESIZE*mp3wf.nFramesPerBlock;
mp3wf.nCodecDelay=1393;
// video stream
AVISTREAMINFO si;
memset(&si, 0, sizeof(AVISTREAMINFO));
si.fccType=streamtypeVIDEO;
si.dwScale=1;
si.dwRate=VIDEO_CAPTURE_FPS;
si.fccHandler=VIDEO_CAPTURE_CODEC;
si.rcFrame=rc;
AVIFileCreateStream(pavifile, &pvid, &si);
AVICOMPRESSOPTIONS op;
memset(&op, 0, sizeof(AVICOMPRESSOPTIONS));
op.fccType=streamtypeVIDEO;
op.fccHandler=VIDEO_CAPTURE_CODEC;
PAVISTREAM pvidcomp;
AVIMakeCompressedStream(&pvidcomp, pvid, &op, NULL);
AVIStreamRelease(pvid);
pvid=pvidcomp;
AVIStreamSetFormat(pvid, 0, &bi, sizeof(BITMAPINFOHEADER));
// audio stream
AVISRETAMINFO si;
memset(&si, 0, sizeof(AVISTREAMINFO));
si.fccType=streamtypeAUDIO;
if(hmp3driverid==NULL){
// wav
si.dwSampleSize=AUDIO_CAPTURE_BITSPERSAMPLE/8*AUDIO_CAPTURE_CHANNELS;
si.dwScale=si.dwSampleSize;
si.dwRate=AUDIO_CAPTURE_SAMPLINGFREQUENCY*si.dwSampleSize;
AVIFileCreateStream(pavifile, &paud, &si);
AVIStreamSetFormat(paud, 0, &wfx, sizeof(WAVEFORMATEX));
}else{
// mp3
si.dwSampleSize=MP3_FRAMESIZE;
si.dwScale=MP3_SAMPLESPERFRAME;
si.dwRate=AUDIO_CAPTURE_SAMPLINGFREQUENCY*si.dwSampleSize;
AVIFileCreateStream(pavifile, &paud, &si);
AVIStreamSetFormat(paud, 0, (LPWAVEFORMATEX)&mp3wf, sizeof(MPEGLAYER3WAVEFORMAT));
}
0 件のコメント:
コメントを投稿