ffmpeg实现H264压缩并且推流至RTSP

一、整体思路

    1 利用ffmpeg读取出视频的一帧图像   存储在pFrame中

    2 利用ffmpeg进行格式转换    sws_scale

    3 利用ffmpeg编码存在pFrame中的图像   H264压缩

    4 利用ffmpeg的 av_interleaved_write_frame( )  写入到rtsp端

    5 辅助部分:解码、编码初始化,QT线程创建

二、编解码初始化

    1 解码初始化

        参考http://blog.csdn.net/yunge812/article/details/79342089

    2 编码初始化           

 
  1.     //创建AVFormatContext结构体

  2. //分配一个AVFormatContext,FFMPEG所有的操作都要通过这个AVFormatContext来进行

  3. fmtctx = avformat_alloc_context();

  4. //获得输出格式,这里是RTP网络流

  5. fmtctx->oformat = av_guess_format("rtp", NULL, NULL);

  6. snprintf(fmtctx->filename, sizeof(fmtctx->filename),"rtp://%s:%d",RDIP,RDPORT);

  7. //打开网络流 fmtctx->pb:创建的AVIOContext结构体 fmtctx->filename url协议地址 方式为只写

  8. avio_open(&fmtctx->pb,fmtctx->filename, AVIO_FLAG_WRITE);

  9. //打开输出流

  10. video_codec = avcodec_find_encoder(AV_CODEC_ID_H264);

  11. if(video_codec == NULL )

  12. {

  13. qDebug() << "video_codec == NULL"<< endl;

  14. }

  15. //初始化AVStream

  16. video_st = avformat_new_stream(fmtctx, video_codec);

  17. if(video_st == NULL )

  18. {

  19. qDebug() << "video_st == NULL"<< endl;

  20. }

  21. video_st->id = fmtctx->nb_streams-1; //add

  22. //设置AVCodecContext编码参数

  23. c = video_st->codec;

  24. avcodec_get_context_defaults3(c, video_codec);

  25. c->codec_id = AV_CODEC_ID_H264;

  26. c->width = OUTWIDTH;

  27. c->height = OUTHEIGHT;

  28. c->time_base.den = FPS; //分母

  29. c->time_base.num = 1; //分子

  30. c->pix_fmt = AV_PIX_FMT_YUV422P;

  31. c->codec_type = AVMEDIA_TYPE_VIDEO;

  32. if(fmtctx->oformat->flags & AVFMT_GLOBALHEADER)

  33. c->flags|= CODEC_FLAG_GLOBAL_HEADER;

  34. //AVOptions的参数

  35. // av_opt_set(c->priv_data, "preset", "ultrafast", 0);

  36. // av_opt_set(c->priv_data, "tune","stillimage,fastdecode,zerolatency",0);

  37. // av_opt_set(c->priv_data, "x264opts","crf=26:vbv-maxrate=728:vbv-bufsize=364:keyint=25",0);

  38. av_opt_set(c->priv_data, "preset", "slow", 0);

  39. av_opt_set(c->priv_data, "tune","zerolatency",0);

  40. av_opt_set(c->priv_data, "x264opts","crf=26:vbv-maxrate=728:vbv-bufsize=3640:keyint=25",0);

  41. //创建AVFormatContext结构体

  42. //分配一个AVFormatContext,FFMPEG所有的操作都要通过这个AVFormatContext来进行

  43. fmtctx = avformat_alloc_context();

  44. //获得输出格式,这里是RTP网络流

  45. fmtctx->oformat = av_guess_format("rtp", NULL, NULL);

  46. snprintf(fmtctx->filename, sizeof(fmtctx->filename),"rtp://%s:%d",RDIP,RDPORT);

  47. //打开网络流 fmtctx->pb:创建的AVIOContext结构体 fmtctx->filename url协议地址 方式为只写

  48. avio_open(&fmtctx->pb,fmtctx->filename, AVIO_FLAG_WRITE);

  49. //打开输出流

  50. video_codec = avcodec_find_encoder(AV_CODEC_ID_H264);

  51. if(video_codec == NULL )

  52. {

  53. qDebug() << "video_codec == NULL"<< endl;

  54. }

  55. //初始化AVStream

  56. video_st = avformat_new_stream(fmtctx, video_codec);

  57. if(video_st == NULL )

  58. {

  59. qDebug() << "video_st == NULL"<< endl;

  60. }

  61. video_st->id = fmtctx->nb_streams-1; //add

  62. //设置AVCodecContext编码参数

  63. c = video_st->codec;

  64. avcodec_get_context_defaults3(c, video_codec);

  65. c->codec_id = AV_CODEC_ID_H264;

  66. c->width = OUTWIDTH;

  67. c->height = OUTHEIGHT;

  68. c->time_base.den = FPS; //分母

  69. c->time_base.num = 1; //分子

  70. c->pix_fmt = AV_PIX_FMT_YUV422P;

  71. c->codec_type = AVMEDIA_TYPE_VIDEO;

  72. if(fmtctx->oformat->flags & AVFMT_GLOBALHEADER)

  73. c->flags|= CODEC_FLAG_GLOBAL_HEADER;

  74. //AVOptions的参数

  75. // av_opt_set(c->priv_data, "preset", "ultrafast", 0);

  76. // av_opt_set(c->priv_data, "tune","stillimage,fastdecode,zerolatency",0);

  77. // av_opt_set(c->priv_data, "x264opts","crf=26:vbv-maxrate=728:vbv-bufsize=364:keyint=25",0);

  78. av_opt_set(c->priv_data, "preset", "slow", 0);

  79. av_opt_set(c->priv_data, "tune","zerolatency",0);

  80. av_opt_set(c->priv_data, "x264opts","crf=26:vbv-maxrate=728:vbv-bufsize=3640:keyint=25",0);

 

        这里要注意的是最后一句av_opt_set   不同设置可能导致不同的结果  有时候程序无法运行

        这里需要根据需要自行设置

    //打开编码器
    avcodec_open2(c, video_codec, NULL);
    /*写入数据流的头部*/
    avformat_write_header(fmtctx, NULL);
    //打印SDP信息, 该信息可用于Rtp流接收解码
    char sdp[2048];
    int tmp = av_sdp_create(&fmtctx,1, sdp, sizeof(sdp));
    qDebug() << sdp <<endl;
    if(tmp != 0)
    {
        qDebug() << "av_sdp_create error " <<endl;
    }

        打印信息可以打印出当前的RTSP流的信息   用于另一端捕获用。具体用法后文会有介绍

三、读取视频

     3.1 视频读取   

  av_read_frame(pFormatCtx_decode, packet)

    3.2  视频解码

 avcodec_decode_video2(pCodecCtx_decode, pFrame, &got_picture, packet)

    3.3  格式转换

 
  1. sws_scale(img_convert_ctx,pFrame->data, pFrame->linesize, 0, pCodecCtx_decode->height, //源

  2. pFrameYUV->data, pFrameYUV->linesize); //目的

 

    此时 经过解码的视频存储在pFrameYUV中

四、编码视频        

 avcodec_encode_video2(c, &pkt, pFrameYUV, &got_output)

五 推流至RTSP

  av_interleaved_write_frame(fmtctx,&pkt);

六 利用VLC播放器接受压缩之后的视频

    6.1 识别打印信息

        第二步留下打印信息很有用   例如我的打印信息是

 
  1. v=0

  2. o=- 0 0 IN IP4 127.0.0.1

  3. s=No Name

  4. c=IN IP4 127.0.0.1

  5. t=0 0

  6. a=tool:libavformat 57.71.100

  7. m=video 5678 RTP/AVP 96

  8. a=rtpmap:96 H264/90000

  9. a=fmtp:96 packetization-mode=1

        将上述打印信息直接copy到记事本,另存为 test.sdp的文件

    6.2 再次运行程序  同时将 test.sdp文件拖到VLC播放器中进行播放

    6.3 播放效果     

 

参考:http://blog.csdn.net/czc1009/article/details/12913759

         http://blog.csdn.net/ytaosky/article/details/72820329

  • 1
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值