基于ffmpeg,实现采集屏幕或摄像头以后向EasyDarwin推流

 近期看了一些关于ffmpeg 推流的文章,但是文章中都是基于ffmpeg命令行实现的,觉得不是很灵活,不好和easydarwin 集成到一起工作。于是自己基于ffmpeg 的lib 实现了,采集,编码,推流的过程
    ffmpeg 可以支持多种方式的采集,如windows 下的dshow,采集桌面的 gdigrab,linux下有video4linux2 等方式采集。我在windows 下实现的是dshow 设备的采集。
   实现的过程如下
    1、使用avformat_alloc_context分配一个AVFormatContext 一个结构。
    2、使用av_find_input_format  查找dshow 的输入是否存在  如AVInputFormat *ifmt = av_find_input_format("dshow"),此时如果dshow 没有被编译进ffmpeg ,ifmt 等于NULL
    3、使用avformat_open_input 打开输入流   avformat_open_input(&pFormatCtx, strUtf8.c_str(), ifmt, &options) ,注意此处,输入的设备名称一定要utf 8 编码的设备名称,否则在中文设备名称下会导致打开设备失败。
   4、avformat_find_stream_info 解析流名称,找到输出流的一些格式信息,这个和用ffmpeg 打开视频文件类似。
   5、 avcodec_find_decoder  基本上来说是解析具体的图像帧格式,一般是YUV420 或者YUV422 格式,
   6、 分配YUV数据的缓冲区 pFrameYUV = av_frame_alloc()
   7、初始化 h264 编码器等  pCodecOut = avcodec_find_encoder(AV_CODEC_ID_H264);   pCodecOutCtx = avcodec_alloc_context3(pCodecOut);
       h264 编码器的具体参数设置如下 
         av_opt_set(pCodecOutCtx->priv_data, "preset", "veryfast", 0);
         av_opt_set(pCodecOutCtx->priv_data, "tune", "zerolatency", 0);
         av_opt_set(pCodecOutCtx->priv_data,"profile","baseline",0);
 8、打开编码器准备编码
  当然如果摄像头输出的YUV422 或RGB 等图像帧时 需要对 使用 sws_scale API 进行转换
9、循环调用 av_read_frame 读取图像,然后使用    avcodec_encode_video2进行编码
10、使用write_frame 写入编码好的视频帧,如果是保存文件,就写入文件,如果是流媒体协议则向网络发送数据,这里我们使用的EasyDarwin 的推流功能,因此只要调用了
write_frame 就向 EasyDarwin 发送视频数据了

输出方式的设定:
  ffmpeg 多种方式输出,由于EasyDarwin 支持RTSP 协议推流转发,因此输出采用了RTSP 推流输出。
  关键API 如下:
             avformat_alloc_output_context2(&FormatOutCtx, NULL, “rtsp”, 输出的URL);
             avio_open(&m_FormatOutCtx->pb, strOut.c_str(), AVIO_FLAG_READ_WRITE)
    如果连接EasyDarwin 服务器失败时   avio_open 返回值小于0 .
最后我们可以用 EasyDarwin 自带的EasyPlayer 或者vlc 观看推送的实时流了。

你可能感兴趣的:(EasyDrawin学习笔记)