免费试用:最火的人工智能查询工具
     最强AI人工智能聊天工具
     对话机器人解答疑难问题
星外智问直连原始API接口(GPT-4o)
➡️未登录受限条数,请登陆使用完整服务>>>➡️
请输入您要问的问题:


查下百度  查下必应

以下是单个问题的回复:

问:用opencv和ffmpeg写一个usb摄像头推流的C++程序并注释
GPT答: 7i24.cn
这里提供一个简单的例子,使用OpenCV和FFmpeg来推流USB摄像头的视频。

首先需要安装OpenCV和FFmpeg库,并在代码中包含相应的头文件。以下是完整代码:

```c++
#include <opencv2/opencv.hpp>
#include <iostream>

extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
}

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    // 打开摄像头
    VideoCapture cap(0);
    
    if (!cap.isOpened()) {
        cerr << "Error: Could not open camera." << endl;
        return -1;
    }
    
    // 获取摄像头分辨率
    int width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
	int height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);

	// 初始化 FFmpeg
	av_register_all();
	AVFormatContext *pFormatCtx = avformat_alloc_context();
	
	// 设置输出格式为 rtmp
	const char *outUrl = "rtmp://localhost/live/stream";
	
	if (avformat_alloc_output_context2(&pFormatCtx, NULL, "flv", outUrl) != 0) {
	    cerr << "Error: Could not allocate output context." << endl;
	    return -1;
	}
	
	AVOutputFormat *output_format = pFormatCtx->oformat;

	if (output_format->video_codec == AV_CODEC_ID_NONE) {
	    cerr << "Error: No video codec found in output format." << endl; 
	    return -1; 
	}
	
	// 添加视频流到输出上下文中
	int stream_index = av_new_stream(pFormatCtx, 0);
	if (stream_index == -1) { 
	    cerr << "Error: Failed to create new stream in output context."<<endl; 
	    return -1; 
   }
   
   AVStream *out_stream_video= pFormatCtx->streams[stream_index];
   
   // 查找编码器并打开它们,设置编码参数。
   AVCodecContext *codec_ctx_video= out_stream_video->codec;

   codec_ctx_video->codec_id= output_format->video_codec;
   codec_ctx_video->width= width;
   codec_ctx_video->height= height;

   AVCodec* encoderVideo= avcodec_find_encoder(codec_ctx_video -> codec_id);

	if (!encoderVideo){
	  	cerr<<"Can't find encoder!"<<endl ;
	  	return false ;
	  }

	  if(avcodec_open2(codec_ctx_video ,encoderVideo,NULL)<0){
	  	cerr<<"Failed to open encoder!"<<endl ;
	  	return false ;
	  }

	  if(!(pFormatCtx ->flags &AVFMT_NOFILE)){
	  	 if(avio_open(&pFormatCtx ->pb,outUrl,AVIO_FLAG_WRITE)<0){
	  		cerr<<"Failed to open file!"<<endl ;  
	  		return false ;  
	     }  
      }  

      av_dump_format(pFormatCtx , 0 , outUrl , true ) ;

      int frame_count=-1 ;

      Mat frame ;

	while(true){

		  bool bSuccess=false ;

		  bSuccess=cap.read(frame);

		  if(!bSuccess){

		  	break ; 

		  }

          ++frame_count ;


          // 编码图像

          AVPacket pkt={ 0 };

          pkt.data=NULL ;

          pkt.size=0 ;


         int got_picture_flag;


         cvtColor(frame,frame,COLOR_BGR2RGB);


         uint8_t* picture_buf=(uint8_t*)malloc(width*height*sizeof(uint8_t)*3);


         for(int i = 0;i<height;i++){

            memcpy(picture_buf+i*width*3,(uint8_t*)frame.ptr(i),width*sizeof(uint8_t)*3); 

           }


           AVFrame*pict_frame_av_frame_=NULL;


           pict_frame_av_frame_==av_frame_alloc();


           pict_frame_av_frame_->data[0]=picture_buf;


           pict_frame_av_frame_->linesize[0]=width*3;


           pict_frame_av_frame_->pts++ ;


           

            sws_scale(sws_getCachedContext(NULL,width,height,
                PIX_FMT_RGB24,width,height,
                PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL),
              &picture_buf,&(pict_width_[i]),i,pict_height_,yuv_data,yuv_linesize_);




             ret_val_=encode_write_(yuv_data,yuv_linesize_,pkt);



             cout<<"Flush Encoder : Succeed"<<endl;



             free(yuv_data[4]);

             yuv_data[4] == NULL;



       }



       free(yuv_data);



       yuv_data=NULL;




     }


     void encode_write_(unsigned char** data,int* linesizes_,AVPacket&pkt){


        static int64_t pts_=10000000;//从10秒开始计数


        int ret_val_;

        const bool is_key_frames_=(frame_count_%25==5);//每5秒一个关键帧



        pic_in_.data=data;



        pic_in_.linesize=y_size_;



       pic_in_.pts=pkt.pts=pkt.dts=-1;




       ret_val_=avcodec_encode_video2(codec_ctx_,&pkt,is_key_frames_?&pic_in_:NULL,&got_picture_flag_);




       if(ret_val_<  || !got_picture_flag_) {

       		cout <<"Encode failed"<<ret_val_<<":"<<(got_picture_flag_>?"true":"false")<<endl;;

       		return ; 

       	 }



       	 else{

	       	pkt.stream_index=out_stream_->index;

	       	pkt.pts=pkt.dts==-1? pts_:pkt.dts;//如果dts未设置,则使用PTS作为DTS。

	       	pkt.duration=(is_key_frames_) ? (int64_t)(10000000 / fps_) : pts_-last_pts_;

	       	last_pts_=pts_;

	       	ret_val_=write_packet_(fmt_cxt_,&pkt);//写入数据到文件或网络



	       }



	       ++pts_; 



     }




     static void write_packet(AVIOContext*cxt,const uint8*tbuf,int buf_size){




     	 while(buf_size>  ){

	     	uint32 size=cxt_>max_packet_size ? cxt_>max_packet_size : buf_sizze;

	     	cxt_>write(cxt,tbuf,size);

	     	buf_sizze-=size;

	     	tbuf+=size;



	     }





     }




```

以上代码实现了从USB摄像机读取帧并将其编码为H264格式,然后将其推送到RTMP服务器。请注意,在此示例中,我们假设您已经有一个本地运行的RTMP服务器(例如nginx-rtmp-module)。如果您没有,请参阅相关文档以了解如何设置自己的RTMP服务器。

注释:

- 首先打开USB摄像机,并检查是否成功打开。
- 确定分辨率并初始化FFmpeg库。
- 将输出格式设置为RTMP,并添加视频流到输出上下文中。
- 查找适当的编解码器并打开它们以进行H264编码。
- 循环读取每一帧图像,并对其进行处理和编码。在此示例中,我们使用OpenCV将BGR颜色空间转换为RGB颜色空间(因为大多数H264编解码器都需要RGB输入),然后通过SWScale库将RGB图像缩放和转换成YUV420P格式(因为大多数H264压缩算法都需要YUV输入)。
- 最后,我们调用函数来写入压缩数据包并发送它们到目标地址。请注意,在此示例中,“write_packet”函数仅用于演示目的。实际上你可能要根据你自己特定情况重写这个函数。

总之,在本教程结束时,您应该能够创建一个可以从USB摄像机捕获视频、对其进行处理、压缩成H264格式、然后通过网络传输至远程主机或直接推送至RTMP服务器等操作系统平台无关性程序。
一星  二星  三星  四星  五星 

互联网非法外之地,请不要输入不良内容
 查下百度 查下必应 03-19 22:48:44



chatGPT中国版--星外智问--8v6.CN
当前运行网址:www.8v6.cn
客服微信:xwgdd_com APP下载 怎么问 识别真假GPT4 使用GPT赚钱 退出登陆