FFmpeg5.1 解码rtsp 并用OpenCV 播放

news2025/9/24 11:53:48

RTSP 连接过程如下图

在这里插入图片描述

看下实际过程中FFmpeg 的日志情况:

[tcp @ 0000014CC3256D40] No default whitelist set
[tcp @ 0000014CC3256D40] Original list of addresses:
[tcp @ 0000014CC3256D40] Address ::1 port 8554
[tcp @ 0000014CC3256D40] Address 127.0.0.1 port 8554
[tcp @ 0000014CC3256D40] Interleaved list of addresses:
[tcp @ 0000014CC3256D40] Address ::1 port 8554
[tcp @ 0000014CC3256D40] Address 127.0.0.1 port 8554
[tcp @ 0000014CC3256D40] Starting connection attempt to ::1 port 8554
[tcp @ 0000014CC3256D40] Successfully connected to ::1 port 8554
===========================================================================================
[rtsp @ 0000014CC325DA80] Sending:
OPTIONS rtsp://:8554/test RTSP/1.0
CSeq: 1
User-Agent: Lavf59.34.101
--
[rtsp @ 0000014CC325DA80] line='RTSP/1.0 200 OK'
[rtsp @ 0000014CC325DA80] line='Server: VLC/3.0.17.4'
[rtsp @ 0000014CC325DA80] line='Content-Length: 0'
[rtsp @ 0000014CC325DA80] line='Cseq: 1'
[rtsp @ 0000014CC325DA80] line='Public: DESCRIBE,SETUP,TEARDOWN,PLAY,PAUSE,GET_PARAMETER'
[rtsp @ 0000014CC325DA80] line=''
===========================================================================================
[rtsp @ 0000014CC325DA80] Sending:
DESCRIBE rtsp://:8554/test RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf59.34.101
--
[rtsp @ 0000014CC325DA80] line='RTSP/1.0 200 OK'
[rtsp @ 0000014CC325DA80] line='Server: VLC/3.0.17.4'
[rtsp @ 0000014CC325DA80] line='Date: Thu, 17 Nov 2022 06:45:09 GMT'
[rtsp @ 0000014CC325DA80] line='Content-Type: application/sdp'
[rtsp @ 0000014CC325DA80] line='Content-Base: rtsp://[::1]:8554/test'
[rtsp @ 0000014CC325DA80] line='Content-Length: 542'
[rtsp @ 0000014CC325DA80] line='Cache-Control: no-cache'
[rtsp @ 0000014CC325DA80] line='Cseq: 2'
[rtsp @ 0000014CC325DA80] line=''
[rtsp @ 0000014CC325DA80] SDP:
v=0
o=- 16654407034258208241 16654407034258208241 IN IP6 tayu-pc
s=Unnamed
i=N/A
c=IN IP6 ::
t=0 0
a=tool:vlc 3.0.17.4
a=recvonly
a=type:broadcast
a=charset:UTF-8
a=control:rtsp://[::1]:8554/test
m=audio 0 RTP/AVP 14
b=AS:128
b=RR:0
a=rtpmap:14 MPA/90000/2
a=control:rtsp://[::1]:8554/test/trackID=0
m=video 0 RTP/AVP 96
b=RR:0
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=640020;sprop-parameter-sets=Z2QAIKzZQFAGWwFqBAQCgAAAAwCAAAAFR4wYyw==,aOvjyyLA;
a=control:rtsp://[::1]:8554/test/trackID=1
===========================================================================================
[rtp @ 0000014CC32558C0] No default whitelist set
[udp @ 0000014CC3262100] No default whitelist set
[udp @ 0000014CC3262100] end receive buffer size reported is 393216
[udp @ 0000014CC3262000] No default whitelist set
[udp @ 0000014CC3262000] end receive buffer size reported is 393216
===========================================================================================
[rtsp @ 0000014CC325DA80] Sending:
SETUP rtsp://[::1]:8554/test/trackID=0 RTSP/1.0
Transport: RTP/AVP/UDP;unicast;client_port=20332-20333
CSeq: 3
User-Agent: Lavf59.34.101
--
[rtsp @ 0000014CC325DA80] line='RTSP/1.0 200 OK'
[rtsp @ 0000014CC325DA80] line='Server: VLC/3.0.17.4'
[rtsp @ 0000014CC325DA80] line='Date: Thu, 17 Nov 2022 06:45:21 GMT'
[rtsp @ 0000014CC325DA80] line='Transport: RTP/AVP/UDP;unicast;client_port=20332-20333;server_port=61687-61688;ssrc=416BF87E;mode=play'
[rtsp @ 0000014CC325DA80] line='Session: a242cd292f307f4b;timeout=60'
[rtsp @ 0000014CC325DA80] line='Content-Length: 0'
[rtsp @ 0000014CC325DA80] line='Cache-Control: no-cache'
[rtsp @ 0000014CC325DA80] line='Cseq: 3'
[rtsp @ 0000014CC325DA80] line=''
===========================================================================================
[rtsp @ 0000014CC325DA80] Sending:
SETUP rtsp://[::1]:8554/test/trackID=1 RTSP/1.0
Transport: RTP/AVP/UDP;unicast;client_port=20334-20335
CSeq: 4
User-Agent: Lavf59.34.101
Session: a242cd292f307f4b
--
[rtsp @ 0000014CC325DA80] line='RTSP/1.0 200 OK'
[rtsp @ 0000014CC325DA80] line='Server: VLC/3.0.17.4'
[rtsp @ 0000014CC325DA80] line='Date: Thu, 17 Nov 2022 06:45:46 GMT'
[rtsp @ 0000014CC325DA80] line='Transport: RTP/AVP/UDP;unicast;client_port=20334-20335;server_port=61688-61689;ssrc=4ACDD3CA;mode=play'
[rtsp @ 0000014CC325DA80] line='Session: a242cd292f307f4b;timeout=60'
[rtsp @ 0000014CC325DA80] line='Content-Length: 0'
[rtsp @ 0000014CC325DA80] line='Cache-Control: no-cache'
[rtsp @ 0000014CC325DA80] line='Cseq: 4'
[rtsp @ 0000014CC325DA80] line=''
===========================================================================================
[rtsp @ 0000014CC325DA80] Sending:
PLAY rtsp://[::1]:8554/test RTSP/1.0
Range: npt=0.000-
CSeq: 5
User-Agent: Lavf59.34.101
Session: a242cd292f307f4b
--
[rtsp @ 0000014CC325DA80] line='RTSP/1.0 200 OK'
[rtsp @ 0000014CC325DA80] line='Server: VLC/3.0.17.4'
[rtsp @ 0000014CC325DA80] line='Date: Thu, 17 Nov 2022 06:45:56 GMT'
[rtsp @ 0000014CC325DA80] line='RTP-Info: url=rtsp://[::1]:8554/test/trackID=0;seq=12541;rtptime=1127806156, url=rtsp://[::1]:8554/test/trackID=1;seq=942;rtptime=1127806156'
[rtsp @ 0000014CC325DA80] line='Range: npt=58.978649-'
[rtsp @ 0000014CC325DA80] line='Session: a242cd292f307f4b;timeout=60'
[rtsp @ 0000014CC325DA80] line='Content-Length: 0'
[rtsp @ 0000014CC325DA80] line='Cache-Control: no-cache'
[rtsp @ 0000014CC325DA80] line='Cseq: 5'
[rtsp @ 0000014CC325DA80] line=''
===========================================================================================

日志到Play 就没再记录时因为后面日志就比较多了,没仔细看。
总体逻辑就是客户端向服务端发送几次请求,并会收到服务端的一些响应。
Sending: OPTIONS Cseq: 1
Receive: 'RTSP/1.0 200 OK Cseq: 1

Sending: DESCRIBE Accept: application/sdp Cseq: 2
Receive: 'RTSP/1.0 200 OK Cseq: 2

SDP:
v=0
o=- 16654407034258208241 16654407034258208241 IN IP6 tayu-pc
s=Unnamed
i=N/A
c=IN IP6 ::
t=0 0
a=tool:vlc 3.0.17.4
a=recvonly
a=type:broadcast
a=charset:UTF-8
a=control:rtsp://[::1]:8554/test
m=audio 0 RTP/AVP 14
b=AS:128
b=RR:0
a=rtpmap:14 MPA/90000/2
a=control:rtsp://[::1]:8554/test/trackID=0
m=video 0 RTP/AVP 96
b=RR:0
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=640020;sprop-parameter-sets=Z2QAIKzZQFAGWwFqBAQCgAAAAwCAAAAFR4wYyw==,aOvjyyLA;
a=control:rtsp://[::1]:8554/test/trackID=1


Sending: SETUP Transport: RTP/AVP/UDP;unicast;client_port=20332-20333 trackID=0 Cseq: 3 //视频轨道
Receive: 'RTSP/1.0 200 OK Cseq: 3

'Transport: RTP/AVP/UDP;unicast;client_port=20332-20333;server_port=61687-61688;ssrc=416BF87E;mode=play


Sending: SETUP Transport: RTP/AVP/UDP;unicast;client_port=20332-20333 trackID=1 Cseq: 4 //音频轨道
Receive: 'RTSP/1.0 200 OK Cseq: 4

'Transport: RTP/AVP/UDP;unicast;client_port=20332-20333;server_port=61687-61688;ssrc=416BF87E;mode=play


Sending: PLAY Session: a242cd292f307f4b Cseq: 5
Receive: 'RTSP/1.0 200 OK Session: a242cd292f307f4b;timeout=60 Cseq: 5

上面说了这么多消息对应早FFmpeg 中其实就是一个API 做的事情:

API avformat_open_input

当返回值为0时上面的操作就基本都完成了。
需要注意的是 SDP 协议是使用TCP 连接,RTSP 是会建立RTP 连接,FFMpeg 默认使用UDP 建立RTP连接,从上面日志中也可以看出来。
所以如果API 一直失败可以考虑是否不是UDP 的连接,可以使用AVDictionary了修改为TCP 连接。

UDP代码

  auto ret = avformat_open_input(&format_ctx, "rtsp://192.168.10.182/video/pri", NULL, nullptr);

TCP 代码

  AVDictionary* format_opts = NULL;
  av_dict_set(&format_opts, "stimeout", std::to_string(2 * 1000000).c_str(), 0); //设置链接超时时间(us)
  av_dict_set(&format_opts, "rtsp_transport", "tcp", 0); //设置推流的方式,默认udp。
  auto ret = avformat_open_input(&format_ctx, "rtsp://192.168.10.182/video/pri", NULL, &format_opts);

到这里基本RTSP 的连接工作就结束了。。。。

API av_read_frame

 while (av_read_frame(format_ctx, &packet) >= 0 && cnt < 1000)

可以循环使用这个API 从RTSP 中读取h264的流,packet 中包换的nal 的buffer。

到这里思路就应该是如何从h264得到yuv或rgb/bgr了。我们使用Opencv 就获取BGR24即可。

之后的代码和解码代码类似,直接放全部代码仅供参考。

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sstream>

extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
#include "libswscale/swscale.h"
}
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

using namespace cv;
int main(int argc, char** argv) {

  // Open the initial context variables that are needed
  SwsContext* img_convert_ctx;
  AVFormatContext* format_ctx = avformat_alloc_context();
  AVCodecContext* codec_ctx = NULL;
  int video_stream_index;

  av_log_set_level(AV_LOG_TRACE); //AV_LOG_TRACE //AV_LOG_DEBUG
  //open RTSP

  AVDictionary* format_opts = NULL;
  av_dict_set(&format_opts, "stimeout", std::to_string(2 * 1000000).c_str(), 0); //设置链接超时时间(us)
  av_dict_set(&format_opts, "rtsp_transport", "tcp", 0); //设置推流的方式,默认udp。
  auto ret = avformat_open_input(&format_ctx, "rtsp://:8554/test", NULL, &format_opts);

  ret = avformat_find_stream_info(format_ctx, NULL);


  //search video stream
  for (int i = 0; i < format_ctx->nb_streams; i++) {
    if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
      video_stream_index = i;
  }

  AVPacket packet;
  av_init_packet(&packet);

  AVStream* stream = NULL;
  int cnt = 0;

  //start reading packets from stream and write them to file
  av_read_play(format_ctx);    //play RTSP

  // Get the codec
  const AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264);
  if (!codec) {
    exit(1);
  }
  std::ofstream myfile;
  // Add this to allocate the context by codec
  codec_ctx = avcodec_alloc_context3(codec);
  avcodec_parameters_from_context(format_ctx->streams[video_stream_index]->codecpar, codec_ctx);
  std::ofstream output_file;
  codec_ctx->width = 640;
  codec_ctx->height = 480;
  codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
  if (avcodec_open2(codec_ctx, codec, NULL) < 0)
    exit(1);

  img_convert_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt
                                  , codec_ctx->width, codec_ctx->height, AV_PIX_FMT_BGR24,
                                                              SWS_BICUBIC, NULL, NULL, NULL);
  AVFrame* picture = av_frame_alloc();
  picture = av_frame_alloc();
  AVFrame* picturergb = av_frame_alloc();
  picturergb = av_frame_alloc();
  if (!picture) {
    fprintf(stderr, "Could not allocate video frame\n");
    exit(1);
  }
  picture->format = codec_ctx->pix_fmt;
  picture->width = codec_ctx->width;
  picture->height = codec_ctx->height;
  picturergb->format = AV_PIX_FMT_BGR24;
  picturergb->width = codec_ctx->width;
  picturergb->height = codec_ctx->height;
  ret = av_frame_get_buffer(picture, 0);
  ret = av_frame_get_buffer(picturergb, 0);
  AVCodecParserContext* parser;
  parser = av_parser_init(codec->id);
  if (!parser) {
    fprintf(stderr, "parser not found\n");
    exit(1);
  }

  while (av_read_frame(format_ctx, &packet) >= 0 && cnt < 1000)
  {
    if (stream == NULL)
    {
      stream = avformat_new_stream(format_ctx, codec);
      avcodec_parameters_from_context(stream->codecpar, codec_ctx);
    }


    ret = avcodec_send_packet(codec_ctx, &packet);
    if (ret < 0) {
      continue;
    }

    while (ret >= 0) {
      ret = avcodec_receive_frame(codec_ctx, picture);
      if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
        break;
      else if (ret < 0) {
        fprintf(stderr, "Error during decoding\n");
        return -1;
      }
      ret = sws_scale(img_convert_ctx, picture->data, picture->linesize, 0, 480, picturergb->data, picturergb->linesize);
      Mat src(cv::Size(640,480), CV_8UC3, picturergb->buf[0]->data);

      imshow("test", src);
      waitKey(1);
    }
  }
  
  av_free(picture);

  av_read_pause(format_ctx);

  return (EXIT_SUCCESS);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/15765.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用BP神经网络、RBF神经网络以及PSO优化的RBF神经网络对数据进行预测(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

Keysight是德科技E5061B网络分析仪-安泰测试

E5061B ENA系列网络分析仪从5Hz 至3GHz提供了广泛的频率范围。它不仅支持一般的射频应用(例如滤波器或放大器测量等)&#xff0c;还支持低频应用(例如直流至直流转换器环路增益测量)。因此&#xff0c;它是所有实验台上进行网络分析的最重要工具。 拥有E5061B&#xff0c;您就…

Selenium4 新特性

一、Selenium4 简介 Selenium是一个综合性项目,包含一系列的工具和库,支持Web浏览器的各种自动化操作: 软件测试爬虫领域RPA领域优点: 开源:https://github.com/SeleniumHQ兼容性: Chrome、FireFox、Edeg、IE、Opera、Safari支持多种编程语言:Java、Python、C#、Ruby、…

Charles抓包web、手机、小程序配置

一、下载地址 二、web抓包 Charles Web抓包&#xff0c;启动Charles会自动与浏览器设置成代理&#xff0c;不需要进行过多的设置。接下来就是通过浏览器发送网络请求&#xff0c;Charles就会直接抓取到这些信息和响应信息。 1、抓取HTTPS协议 Charles配置 点击顶部菜单栏【He…

双功能螯合剂p-NCS-Bz-DFO,1222468-90-7,p-SCN-Bn-Deferoxamine特点分析

●外观以及性质&#xff1a; p-SCN-Bn-Deferoxamine属于双功能螯合剂&#xff0c;西安凯新生物科技有限公司是各种修饰性PEG供应商&#xff0c;提供各种品质优良PEG衍生物&#xff0c;分子量从1000-40000不等&#xff0c;纯度≥95%&#xff0c;发货速度快。 ●中文名&#xff…

Web学习笔记-React

笔记内容转载自AcWing的Web应用课讲义&#xff0c;课程链接&#xff1a;AcWing Web应用课。 CONTENTS1. React配置环境2. ES6语法补充3. Components1. React配置环境 React官网&#xff1a;React。 React是一个声明式&#xff0c;高效且灵活的用于构建用户界面的JavaScript库…

凡事预则立,不预则缺货!2022年底了核芯物联蓝牙AOA定位基站GA25缺货!GA10缺货!GA60也缺货!

凡事预则立&#xff0c;不预则缺货&#xff01;2022年底了核芯物联蓝牙AOA定位基站GA25缺货&#xff01;GA10缺货&#xff01;GA60也缺货&#xff01; 核芯物联岳毅恒 ​ 深圳核芯物联科技有限公司 战略合作拓展总监 凡事预则立&#xff0c;不预则缺货&#xff01;202222年底…

brython | 初探鼠标事件-1:点击事件

各位前端大佬勿笑话&#xff0c;运维小弟献丑了。 前段时间看见大佬使用【文言文】写了一个连连看&#xff0c;于是我也想用【brython】也实现一个连连看。 于是乎&#xff0c;你们就看到这篇文章和这个项目了。 如果大佬们对brython不是特别了解的话&#xff0c;建议先查看之…

JVM分析工具

JVM在运行过程中&#xff0c;我们可以利用各种工具对JVM进行分析&#xff0c;这是性能调优的利器。可以通过各种工具了解在系统运行过程中&#xff0c;在JVM底层到底发生了什么。JVM分析工具一般分为两种&#xff0c;一种是命令行工具&#xff0c;一种是图形界面工具。 JVM分析…

卷积操作的不同类型

文章目录1. 一维卷积2. 二维卷积3. 三维卷积4. 扩张卷积5. 空洞卷积6. 分组卷积一般而言&#xff0c;一维卷积用于文本数据&#xff1b;二维卷积用于图像数据&#xff0c;对宽度和高度都进行卷积&#xff1b;三维卷积用于视频及3D图像处理领域&#xff0c;对立方体的三个面进行…

CS5269TypeC转HDMI2.0+VGA带PD100W快充拓展坞方案芯片完整设计资料(原理图+PCB文件)

CS5269TypeC转HDMI2.0VGA带PD100W快充方案芯片原理图&#xff1a; 用于US Type-C或DP1.4连接到HDMI2.0转换器。CS5269集成了DP1.4HDMI2.0的输出端和VGA输出接口。另外&#xff0c;两个CC控制器包括CC通信&#xff0c;以实现DP Alt模式和功率传输功能&#xff0c;一个用于上游类…

SD-WAN NFV uCPE VNF

NFV&#xff08;network function virtulization) NFV&#xff08;network function virtulization&#xff0c;网络功能虚拟化&#xff09;是指一种操作框架&#xff0c;目的是为了将部署在COTS硬件上的、在虚拟基础架构中的VNF软件设备编排和自动化起来&#xff0c;然后进行…

精耕丨“银发族”与“熬夜党”都在养生,大健康品牌怎样精耕消费者需求?

“被疫情偷走的这三年”里&#xff0c;健康成为所有人不得不面对的生活命题。 丁香医生《2022国民健康洞察报告》显示&#xff0c;2021年人们平均存在4.8个健康困扰&#xff0c;算得上“人均亚健康”&#xff0c;其中情绪、身材、皮肤焦虑位列TOP3。 人们对稳住健康的追求也一…

5G无线技术基础自学系列 | 物理共享信道分配

素材来源&#xff1a;《5G无线网络优化实践》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G无线技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 在LTE协议中&#xff0c;DCI的位置和对应…

第一章《初学者问题大集合》第8节:Java程序初步释疑

当成功运行了第一个Java程序,很多读者都对之前的各项操作以及所写的这行代码有一些不清楚的地方,本节就来解答一下这些问题。其实,初学者的大部分疑问都集中体现在图1-41中。 图1-41 源文件名与类名称 1.类是个什么东西? 前文曾经让各位读者在写代码之前先创建一个“类”…

day065:IO流、字节流、字节流写数据

目录 一、IO流 1.IO流的目的 2.IO的表示 二、IO流的分类 1.按流向分 2.按数据类型分 三、字节流 1.字节流写数据 2.字节流的注意事项 3.字节流写数据的三种方式 4.字节流写数据的两个问题 &#xff08;1&#xff09;字节流写数据如何换行&#xff1f; &#xff08;…

腾讯云服务器部署vue前端项目(Ubuntu+vue+nginx+nodejs+npm)

一、安装nodejs和npm sudo apt-get nodejs sudo apt-get npm 但是在安装npm后&#xff0c;输入npm --version时&#xff0c;会报错 此时&#xff0c;需要升级nodejs的版本&#xff0c;执行下面的两条命令 wget -qO- https://deb.nodesource.com/setup_16.x | sudo -E bash - …

兄弟兄弟,在git中的使用.gitignore忽略不想要提交的文件,了解一下呗

1. .gitignore的作用 在实际的工程项目中&#xff0c;除了项目本身的代码文件、配置文件外&#xff0c;还有一些文件或目录并不需要纳入版本管理中&#xff0c;如idea工具会在工程根目录生成一个.idea的目录、工程编译后生的target等。因此在提交代码文件的时候需要自动把这些目…

医学图像处理-安装nibabel包命令

医学图像处理-安装nibabel包命令问题与解决方案问题与解决方案 直接使用 pip install nibabel 出现如下报错&#xff1a; 尝试使用conda 命令安装&#xff0c;conda官网查命令&#xff1a; conda install -c conda-forge nibabel conda install -c conda-forge/label/gcc7 ni…

编译 - Make 命令教程 - 学习/实践

1.应用场景 主要用于学习和使用make命令进行软件编译安装。 2.学习/操作 1.文档阅读 Make 命令教程 - 阮一峰的网络日志 Make- GNU Project - Free Software Foundation 2.整理输出 2.1 什么是make命令&#xff1f; Make 是最常用的构建工具&#xff0c;诞生于1977年&#xff…