获取设备名
//ffmpeg 版本5.1 低版本 获取dshow设备名可能未实现
void find_video_device(){
avdevice_register_all();
const AVInputFormat * ifmt=av_find_input_format("dshow");
AVDeviceInfoList* list; //设备描述列表
int devices_num=avdevice_list_input_sources(ifmt,"dshow",NULL,&list);
String cur_video,cur_audio;
for(int i=0;i<devices_num;i++){
if(*(list->devices[i]->media_types)==(AVMediaType::AVMEDIA_TYPE_VIDEO)){
cur_video=list->devices[i]->device_description;
}else if(*(list->devices[i]->media_types)==(AVMediaType::AVMEDIA_TYPE_AUDIO)){
cur_audio=list->devices[i]->device_description;
}
}
avdevice_free_list_devices(&list);
}
打开设备以及获取信息进行编解码 (dshow)
void open_v_device_decode(String s){
char video_name[6+s.size()]="video=";
int index=6;
std::string cur=s.toStdString();
for(auto c:cur) video_name[index++]=c;
AVDictionary* options = NULL;
//摄像头采集选项
av_dict_set(&options,"fps","25",0);
/*音频采集选项
*av_dict_set(&options, "sample_size", "16", 0);
*av_dict_set(&options, "channels", "2", 0);
*av_dict_set(&options, "sample_rate", "44100", 0);
*av_dict_set(&options, "audio_buffer_size", "40", 0);
*若为实时音频需要调小,这是采集缓冲区,即几毫秒发送,默认500ms
*/
int ret=avformat_open_input(&pFormatCtx,video_name,ifmt,&options);
if(ret!=0){
qWarning()<< ret << "Couldn't open input stream.";
return ;
}
ret=avformat_find_stream_info(pFormatCtx,NULL);
if(ret<0)
{
qWarning()<<"Couldn't find stream information."<<ret;
return ;
}
int videoindex=-1;
uint i;
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO)
{
videoindex=i;
break;
}
if(videoindex==-1)
{
qWarning()<<"Couldn't find a video stream.";
return ;
}
const AVCodec* pCodec=avcodec_find_decoder(pFormatCtx->streams[videoindex]->codecpar->codec_id);//视频解码器
AVCodecContext* pCodecCtx=avcodec_alloc_context3(pCodec);//解码上下文
if ((ret = avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoindex]->codecpar)) < 0) return ;//从输入上下文获取编码参数
pCodecCtx->thread_count=8; //解码线程数目
//打开解码器
ret = avcodec_open2(pCodecCtx,pCodec,nullptr);
if(ret < 0){
qDebug() << QStringLiteral("打开解码器失败");
return;
}
}
//获取其原始数据 一般获取到的为yuv格式图像和PCM数据
//若要实时传输需要进一步重采样和编码
/* AVPacket *pkt=(AVPacket *)av_malloc(sizeof(AVPacket));
AVFrame *pFrameYUYV=av_frame_alloc();
if(av_read_frame(pFormatCtx,pkt)<0){
av_packet_free(&pkt);
av_frame_free(&pFrameYUYV);
//quit
}
ret = avcodec_send_packet(pCodecCtx, pkt);
if (ret != 0){
qDebug() << QStringLiteral("receive pkt from video is failed");
//quit
}
ret =avcodec_receive_frame(pCodecCtx, pFrameYUYV);
if (ret != 0){
qDebug() << QStringLiteral("receive pAVFrame is failed");
av_frame_unref(pFrameYUYV);
//quit
}
*/
进行录屏获取图像信息(gdibrab)
avdevice_register_all();
// gdigrab 选项
AVDictionary* options = NULL;
pFormatCtx = avformat_alloc_context();
// frame rate
av_dict_set(&options,"framerate","25",0);
//与边界相隔多少像素
av_dict_set(&options,"offset_x","20",0);
av_dict_set(&options,"offset_y","40",0);
const AVInputFormat *ifmt=av_find_input_format("gdigrab");
if(avformat_open_input(&pFormatCtx,"desktop",ifmt,&options)!=0){
qWarning() << "Couldn't open input stream(screen record).";
return ;
}
if(avformat_find_stream_info(pFormatCtx,NULL)<0)
{
qWarning()<<"Couldn't find stream information.";
return ;
}
//以下同dshow获取stream信息,解码相同