avformat_open_input 最近公司在做法院项目,需要将相机的画面和本地法官说话的声音整合到一个录像文件中,为此,专门收集了不少资料。决定用FFmpeg+winapi采集音频+sdl播放
首先FFmpeg,是一款开源的音视频算法库,可以实现打开本地和网络资源、解码、编码、存储等一系列操作。
一、FFMPEG的工作流程
二、winapi采集音频
Windows自带的API函数waveInOpen打开音频采集
WAVEFORMATEX waveform;
waveform.wFormatTag = WAVE_FORMAT_PCM;//声音格式为PCM
waveform.nSamplesPerSec = AUDIO_SAMP_RATE;//采样率,16000次/秒
waveform.wBitsPerSample = AUDIO_SAMP_BIT;//采样比特,16bits/次
waveform.nChannels = AUDIO_CHANNEL;//采样声道数,2声道
waveform.nAvgBytesPerSec = AUDIO_SAMP_RATE* AUDIO_SAMP_BIT *AUDIO_CHANNEL / 8;//每秒的数据率,就是每秒能采集多少字节的数据
waveform.nBlockAlign = AUDIO_SAMP_BIT*AUDIO_CHANNEL / 8;//一个块的大小,采样bit的字节数乘以声道数
waveform.cbSize = 0;//一般为0
//使用waveInOpen函数开启音频采集
if (MMSYSERR_NOERROR != waveInOpen(&hWaveIn, 0, &waveform, (DWORD)(DeviceAudioCallback), DWORD(this), CALLBACK_FUNCTION))
{
return FALSE;
}
设置采集声音需要的缓冲区
DWORD bufsize = m_nAudioFrmSize;//AUDIO_SAMP_RATE/AUDIO_DEVICE_SAMP_CNT_PER_SECOND;
pBuffer1 = (BYTE*)malloc(bufsize);
pBuffer2 = (BYTE*)malloc(bufsize);
wHdr1.lpData = (LPSTR)pBuffer1;
wHdr1.dwBufferLength = bufsize;
wHdr1.dwBytesRecorded = 0;
wHdr1.dwUser = 0;
wHdr1.dwFlags = 0;
wHdr1.dwLoops = 1;
wHdr1.lpNext = NULL;
wHdr1.reserved = 0;
//将建立好的wHdr1做为备用
waveInPrepareHeader(hWaveIn, &wHdr1, sizeof(WAVEHDR));
这里的bufsize可以根据自己的需要进行设定,当声音采集调节dwBytesRecorded=dwBufferLength后,回调函数返回。也就是说当收集的声音将缓冲区填满后返回。
开始声音采集:waveInStart
收到声音后回调函数
DWORD WINAPI CRecordRtspAndMicrophone::DeviceAudioCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
CRecordRtspAndMicrophone *pDlg = (CRecordRtspAndMicrophone*)dwInstance;
if (NULL == pDlg) return FALSE;
int re(0)
;
switch (uMsg)
{
case WIM_OPEN:
break;
case WIM_DATA:
pDlg->InputAudioData((PWAVEHDR)dwParam1);
waveInAddBuffer(hwavein, (PWAVEHDR)dwParam1, sizeof (WAVEHDR));
break;
case WIM_CLOSE:
break;
default:
break;
}
return 0;
}
当数据为WIM_DATA的时候 可以将PCM声音送入到共享缓冲区中
三、SDL播放实时视频
收到图像包---->解码---->显示
为了将SDL窗口绑定到目标窗口中,可以调用SDL_putenv设置与窗口绑定
char sdl_var[64];
sprintf(sdl_var, "SDL_WINDOWID=%d",m_hWnd);//主窗口句柄
SDL_putenv(sdl_var);
SDL_putenv------>SDL_Init-
SDL_SetVideoMode---创建一个窗口
SDL_CreateYUVOverlay--创建一个图像空间
SDL_DisplayYUVOverlay--显示图像空间
在这个过程中需要用到缩放 缩放函数为sws_scale
具体每个环节的讲解 我会上传到空间