一.项目介绍
本项目适用于新手对ffmpeg框架学习的项目,此项目包括功能,屏幕录制、音频录制、摄像头采集录制、音视频通过RTMP推流。
二、开发环境
QT+vs2017+ffmpeg
三、主要代码介绍
1.使用QT获取音频输入设备代码
QStringList CUtilDevice::get_input_audio_devices()
{
//获取输入音频设备名称
QList<QAudioDeviceInfo> audioDeviceListI = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
QStringList ret;
for(int i = 0; i < audioDeviceListI.size(); i++)
{
QString device_name = audioDeviceListI.at(i).deviceName();
bool is_repeat = false;
for(int j = 0; j < ret.size(); j++)
{
if(ret.at(j) == device_name)
{
is_repeat = true;
}
}
if(!is_repeat)
{
ret.append(device_name);
}
}
return ret;
}
2.使用QT获取摄像头设备代码
QStringList ret;
QList<QCameraInfo> device_list = QCameraInfo::availableCameras();
for(int i = 0; i < device_list.size(); i++)
{
QString device_name = device_list.at(i).description();
bool is_repeat = false;
for(int j = 0; j < ret.size(); j++)
{
if(ret.at(j) == device_name)
{
is_repeat = true;
}
}
if(!is_repeat)
{
ret.append(device_name);
}
}
return ret;
3.ffmpeg初始化
avcodec_register_all();
av_register_all();
avdevice_register_all();
4.ffmpeg音视频输入流设置
if(m_video_device.isEmpty()& m_audio_device.isEmpty())
{
qDebug("you have not set any capture device \n");
return false;
}
int i;
//打开Directshow设备前需要调用FFmpeg的avdevice_register_all函数,否则下面返回失败
m_pInputFormat_d = av_find_input_format("dshow"); //这个主要用于摄像头和音频设备的输入
m_pInputFormat = av_find_input_format("gdigrab");//这个主要用于屏幕获取的
if(nullptr == m_pInputFormat)
{
qDebug()<<"find video input fail.";
}
// Set device params
AVDictionary *device_param = 0;
//if not setting rtbufsize, error messages will be shown in cmd, but you can still watch or record the stream correctly in most time
//setting rtbufsize will erase those error messages, however, larger rtbufsize will bring latency
//av_dict_set(&device_param, "rtbufsize", "10M", 0);
if(!m_video_device.isEmpty())
{
int res = 0;
if(m_is_use_camera)//如果是摄像头录制
{
QString device_name = "video=" + m_video_device;
//Set own video device's name
if ((res = avformat_open_input(&m_pVidFmtCtx, device_name.toStdString().c_str(), m_pInputFormat_d, &device_param)) != 0)
{
qDebug("Couldn't open input video stream.(无法打开输入流)\n");
return false;
}
}
else//如果是屏幕录制
{
av_dict_set(&device_param,"framerate","5",0);
QString device_name = "desktop";
qDebug()<<"device_name: "<<device_name;
if ((res = avformat_open_input(&m_pVidFmtCtx, device_name.toStdString().c_str(), m_pInputFormat, &device_param)) != 0)
{
qDebug("Couldn't open input video stream.(无法打开输入流)\n");
return false;
}
}
//input video initialize
AVDictionary *param = NULL;
if (avformat_find_stream_info(m_pVidFmtCtx, ¶m) < 0)
{
qDebug("Couldn't find video stream information.(无法获取流信息)\n");
return false;
}
m_videoindex = -1;
for (i = 0; i < m_pVidFmtCtx->nb_streams; i++)
{
if (m_pVidFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
m_videoindex = i;
break;
}
}
if (m_videoindex == -1)
{
qDebug("Couldn't find a video stream.(没有找到视频流)\n");
return false;
}
//编码器
//if (avcodec_open2(encodec_ctx, encodec, ¶m) < 0)
if (avcodec_open2(m_pVidFmtCtx->streams[m_videoindex]->codec, avcodec_find_decoder(m_pVidFmtCtx->streams[m_videoindex]->codec->codec_id),NULL) < 0)
{
qDebug("Could not open video codec.(无法打开解码器)\n");
return false;
}
}
//
if(!m_audio_device.isEmpty())
{
AVDictionary *device_param_a = 0;
QString device_name = "audio=" + m_audio_device;
//Set own audio device's name
if (avformat_open_input(&m_pAudFmtCtx, device_name.toStdString().c_str(), m_pInputFormat_d, &device_param_a) != 0){
qDebug("Couldn't open input audio stream.(无法打开输入流)\n");
return false;
}
//input audio initialize
if (avformat_find_stream_info(m_pAudFmtCtx, NULL) < 0)
{
qDebug("Couldn't find audio stream information.(无法获取流信息)\n");
return false;
}
m_audioindex = -1;
for (i = 0; i < m_pAudFmtCtx->nb_streams; i++)
{
if (m_pAudFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
m_audioindex = i;
break;
}
}
if (m_audioindex == -1)
{
qDebug("Couldn't find a audio stream.(没有找到音频流)\n");
return false;
}
if (avcodec_open2(m_pAudFmtCtx->streams[m_audioindex]->codec, avcodec_find_decoder(m_pAudFmtCtx->streams[m_audioindex]->codec->codec_id), NULL) < 0)
{
qDebug("Could not open audio codec.(无法打开解码器)\n");
return false;
}
}
return true;
5.ffmpeg音视频输出流设置代码
m_output_path = out_path;
//output initialize
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_path);
//rtmp 直播使用
//avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_pa