公司项目需要提供实时显示网络摄像头实时视频.

void RTSPFFmpeg::rtsp_open(const char *url) {
AVFormatContext* format_ctx = avformat_alloc_context();
AVCodecContext *pAVCodecContext_video = nullptr;
AVCodec *pAVCodec_video = nullptr;
AVCodecParameters *pAVCodePar_video = avcodec_parameters_alloc();
AVPacket *pAVPacket = av_packet_alloc(); ; // ffmpeg单帧数据包
AVFrame *pAVFrame_video = av_frame_alloc(); // ffmpeg单帧缓存
AVFrame *pAVFrameRGB32_video = av_frame_alloc(); // ffmpeg单帧缓存转换颜色空间后的缓存
AVCodecParserContext *pAVCodeParseContext_video = nullptr;
struct SwsContext *pSwsContext_video = nullptr; // ffmpeg编码数据格式转换
AVDictionary * opts = nullptr; int ret = -1;
int numBytes = 0; // 解码后的数据长度
u_char *outBuffer = nullptr; // 解码后的数据存放缓存区
// open rtsp: Open an input stream and read the header. The codecs are not opened
//const char* url = "rtsp://admin:genepoint2020@192.168.100.14:554/cam/realmonitor?channel=1&subtype=0";
av_dict_set(&opts, "rtsp_transport", "tcp", 0);
av_dict_set(&opts, "stimeout", "2000000", 0);
// audio/video stream index
int video_stream_index = -1;
   ret = avformat_open_input(&format_ctx, url, nullptr, &opts);
if (ret != 0) {
fprintf(stderr, "fail to open url: %s, return value: %d\n", url, ret);
continue;
}
// Read packets of a media file to get stream information
ret = avformat_find_stream_info(format_ctx, nullptr);
if (ret < 0) {
fprintf(stderr, "fail to get stream information: %d\n", ret);
continue;
} fprintf(stdout, "Number of elements in AVFormatContext.streams: %d\n", format_ctx->nb_streams);
for (int i = 0; i < format_ctx->nb_streams; ++i) {
const AVStream *stream = format_ctx->streams[i];
fprintf(stdout, "type of the encoded data: %d\n", stream->codecpar->codec_id);
if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
// 对找到的视频流寻解码器
pAVCodePar_video = stream->codecpar;
pAVCodec_video = avcodec_find_decoder(stream->codecpar->codec_id);
if (!pAVCodec_video) {
video_stream_index = -1;
break;
}
pAVCodeParseContext_video = av_parser_init(pAVCodec_video->id);
if (!pAVCodeParseContext_video) {
video_stream_index = -1;
break;
}
pAVCodecContext_video = avcodec_alloc_context3(pAVCodec_video);
if (!pAVCodecContext_video) {
}
if (avcodec_open2(pAVCodecContext_video, pAVCodec_video, NULL) < 0) {
video_stream_index = -1;
break;
}
fprintf(stdout, "dimensions of the video frame in pixels: width: %d, height: %d, pixel format: %d\n",
stream->codecpar->width, stream->codecpar->height, stream->codecpar->format);
}
}
if (video_stream_index == -1) {
fprintf(stderr, "no video stream\n");
continue;
}
// 对拿到的原始数据格式进行缩放转换为指定的格式高宽大小
pSwsContext_video = sws_getContext(
pAVCodePar_video->width,
pAVCodePar_video->height,
static_cast<AVPixelFormat>(pAVCodePar_video->format),
pAVCodePar_video->width,
pAVCodePar_video->height,
AV_PIX_FMT_RGBA,
SWS_FAST_BILINEAR,
nullptr,
nullptr,
nullptr
);
numBytes = av_image_get_buffer_size(
AV_PIX_FMT_RGBA,
pAVCodePar_video->width,
pAVCodePar_video->height,
1
);
outBuffer = (u_char *) av_malloc(numBytes);
// pAVFrame32的data指针指向了outBuffer
av_image_fill_arrays(
pAVFrameRGB32_video->data,
pAVFrameRGB32_video->linesize,
outBuffer,
AV_PIX_FMT_RGBA,
pAVCodePar_video->width,
pAVCodePar_video->height,
1
);
while (1) {
ret = av_read_frame(format_ctx, pAVPacket);
if (ret < 0) {
fprintf(stderr, "error or end of file: %d\n", ret);
continue;
}
if (pAVPacket->stream_index == video_stream_index) {
// fprintf(stdout, "video stream, packet size: %d\n", pAVPacket->size);
ret = avcodec_send_packet(pAVCodecContext_video,pAVPacket);
if( 0 != ret){
continue;
}
while (avcodec_receive_frame(pAVCodecContext_video,pAVFrame_video) == 0){
sws_scale(pSwsContext_video,
(const uint8_t * const *)pAVFrame_video->data,
pAVFrame_video->linesize,
0,
pAVCodePar_video->height,
pAVFrameRGB32_video->data,
pAVFrameRGB32_video->linesize);
QImage image((u_char*)outBuffer,pAVCodePar_video->width,pAVCodePar_video->height,QImage::Format_RGBA8888);
emit rtsp_image_sig(image);
}
}
av_packet_unref(pAVPacket);
}
av_parser_close(pAVCodeParseContext_video);
av_frame_free(&pAVFrame_video);
av_frame_free(&pAVFrameRGB32_video);
av_free(outBuffer);
av_free(pSwsContext_video);
avcodec_free_context(&pAVCodecContext_video);
avformat_close_input(&format_ctx);
}

ffmpeg拉取rtsp视频流的更多相关文章

  1. ffmpeg API录制rtsp视频流

    原文出自http://blog.csdn.net/zxwangyun/article/details/8190638#reply   作者 Sloan 这里在录制时,并没有进行转码,只是相当于把rts ...

  2. Web下无插件播放rtsp视频流的方案及各家优秀内容资源整理

    Web下无插件播放rtsp视频流的方案及各家优秀内容资源整理 方案一:服务器端用 websocket 接受 rtsp ,然后,推送至客户端 实现步骤: 方案二:使用 ffmpeg + nginx 把 ...

  3. 使用FFmpeg如何转发一个RTSP视频流

    版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/6930221.html   转发RTSP流,这类需求一般出现于转发一些摄像头采集视频,并在摄像头上做RTSP ...

  4. Ffmpeg 获取USB Camera 视频流

    本文讲述的案例是如何通过Ffmpeg实现从USB Camera中获取视频流并将视频流保存到MP4文件. 本文亦适用于从USB Camera 获取视频流并将视频流转发到rtmp服务的案例,二者基本的原理 ...

  5. OpenCV读取RTSP视频流

    用opencv的VideoCapture读取RTSP视频流,只有opencv3.1版本可以,之前的版本都无法读取视频流.可能的原因是云平台的RTSP视频流太差,经常错码.项目最后使用的是opencv2 ...

  6. 基于阿里云直播实现视频推流(ffmpeg)/拉流(Django2.0)以及在线视频直播播放(支持http/https)功能

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_146 由于5g网络的光速推广,视频业务又被推上了风口浪尖,在2019年初我们还在谈论照片,短视频等关键字,而进入2020年,我们津 ...

  7. github拉取和推送

    登入github 创建一个开源项目 然后打开安装好的git 首先进入一个指定的文件夹 例如: 1)E:\>cd miaov/testGit 回车 进入E盘的testGit文件夹 2)E:\mia ...

  8. 流媒体测试笔记记录之————阿里云监控、OBS、FFmpeg拉流和推流变化比较记录

    OBS设置视频(512kbps)和音频(128kbps)比特率 阿里云监控结果: 使用FFmpeg拉流到Nginx 服务器测试比特率 第二次测试,修改视频和音频比特率 OBS设置 阿里云监控 Ngin ...

  9. git&sourcetree安装及在IntelliIJ下拉取项目基础使用

    be careful: 1)git版本与Sourcetree版本最好一致 ,不能git为2.5,sourcetree为1.8 2)先安装git再安装Sourcetree 3)拥有git和sourcet ...

随机推荐

  1. <一>从指令角度了解函数堆栈调用过程

    代码 点击查看代码 #include <iostream> using namespace std; int sum(int a,int b){ int temp=0; temp= a + ...

  2. Spring三级缓存解决循环依赖

    前提知识 1.解决循环依赖的核心依据:实例化和初始化步骤是分开执行的 2.实现方式:三级缓存 3.lambda表达式的延迟执行特性 spring源码执行逻辑 核心方法refresh(), popula ...

  3. <五>关于类的各类成员

    类的各种成员-> 成员方法 & 成员变量 普通的成员方法=>编译器会添加一个this形参变量 1:属于类的作用域 2:调用该方法时,需要依赖一个对象,而且常对象不能调 3:可以任意 ...

  4. dp入门30题

    前言:本文章主要记录一些 \(dp\) 入门题,都是我做过的,希望读者能从这些基础题中打好 \(dp\) 扎实的基础,有不足的地方也欢迎指出.大部分是 \(CodeFoces\) 和 \(Atcode ...

  5. shell文件报错syntax error near unexpected token '$'\r''

    本来跑的好好得一个文件,在windows下修改了,然后移植到linux就报错了. 找了一圈以下是解决方案: 这种情况发生的原因是因为你所处理的文件换行符是dos格式的"\r\n" ...

  6. 森林野火故事2.0:一眼看穿!使用 Panel 和 hvPlot 可视化 ⛵

    作者:韩信子@ShowMeAI 数据分析实战系列:https://www.showmeai.tech/tutorials/40 本文地址:https://www.showmeai.tech/artic ...

  7. go get 报错:dial tcp 142.251.43.17:443: i/o timeout

    自动下载 go env -w GO111MODULE=on 设置环境为国内代理 go env -w GOPROXY=https://goproxy.cn,direct 注:go 版本需要支持 mod

  8. 1. scrapy 框架应该怎么学习(前言)

    其实 scrapy 框架并不难学习, 我觉得分为两部分: 命令 和 代码逻辑的构建 1. 如何学习命令 其实 scrapy 已经帮我们做好了很充足的说明了, 下面我来说如何好好利用这些说明 scrap ...

  9. C++编程笔记(QT)

    目录 入门基础 模态对话框 消息提示框(messagebox) 文件和目录 字体选择框 输入对话框 进度条 工具栏 控件布局 Windows托盘案例 控件 button 下拉菜单按钮 `radioBu ...

  10. 4.10:Spark之wordcount

    〇.概述 1.拓扑结构 2.目标 使用spark完成计数实验 一.启动环境 二.新建数据文件 三.查看文件内容 四.启动spark服务 五.编写代码 复制以下代码到shell中(复制后在终端右键-&g ...