ffmpeg拉取rtsp视频流
公司项目需要提供实时显示网络摄像头实时视频.
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视频流的更多相关文章
- ffmpeg API录制rtsp视频流
原文出自http://blog.csdn.net/zxwangyun/article/details/8190638#reply 作者 Sloan 这里在录制时,并没有进行转码,只是相当于把rts ...
- Web下无插件播放rtsp视频流的方案及各家优秀内容资源整理
Web下无插件播放rtsp视频流的方案及各家优秀内容资源整理 方案一:服务器端用 websocket 接受 rtsp ,然后,推送至客户端 实现步骤: 方案二:使用 ffmpeg + nginx 把 ...
- 使用FFmpeg如何转发一个RTSP视频流
版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/6930221.html 转发RTSP流,这类需求一般出现于转发一些摄像头采集视频,并在摄像头上做RTSP ...
- Ffmpeg 获取USB Camera 视频流
本文讲述的案例是如何通过Ffmpeg实现从USB Camera中获取视频流并将视频流保存到MP4文件. 本文亦适用于从USB Camera 获取视频流并将视频流转发到rtmp服务的案例,二者基本的原理 ...
- OpenCV读取RTSP视频流
用opencv的VideoCapture读取RTSP视频流,只有opencv3.1版本可以,之前的版本都无法读取视频流.可能的原因是云平台的RTSP视频流太差,经常错码.项目最后使用的是opencv2 ...
- 基于阿里云直播实现视频推流(ffmpeg)/拉流(Django2.0)以及在线视频直播播放(支持http/https)功能
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_146 由于5g网络的光速推广,视频业务又被推上了风口浪尖,在2019年初我们还在谈论照片,短视频等关键字,而进入2020年,我们津 ...
- github拉取和推送
登入github 创建一个开源项目 然后打开安装好的git 首先进入一个指定的文件夹 例如: 1)E:\>cd miaov/testGit 回车 进入E盘的testGit文件夹 2)E:\mia ...
- 流媒体测试笔记记录之————阿里云监控、OBS、FFmpeg拉流和推流变化比较记录
OBS设置视频(512kbps)和音频(128kbps)比特率 阿里云监控结果: 使用FFmpeg拉流到Nginx 服务器测试比特率 第二次测试,修改视频和音频比特率 OBS设置 阿里云监控 Ngin ...
- git&sourcetree安装及在IntelliIJ下拉取项目基础使用
be careful: 1)git版本与Sourcetree版本最好一致 ,不能git为2.5,sourcetree为1.8 2)先安装git再安装Sourcetree 3)拥有git和sourcet ...
随机推荐
- ahk精简自用
;9:03 2022/8/20 自用 #NoEnv #Warn #SingleInstance Force ;设工作目录为桌面 SetWorkingDir %A_Desktop% ;托盘提示必须放在热 ...
- 河北首家城商行传统核心业务国产化,TDSQL突破三“最”为秦皇岛银行保驾护航
11 月 1 日,秦皇岛银行新一代分布式核心系统成功投产并稳定安全运行超过三个月,标志着秦皇岛银行数字化转型应用和服务水平登上了一个新台阶. 这是秦皇岛银行有史以来规模最大.范围最广.难度最高的一次系 ...
- Codeforces Global Round 23 D.Paths on the Tree(记忆化搜索)
https://codeforces.ml/contest/1746/problem/D 题目大意:一棵n节点有根树,根节点为1,分别有两个数组 s[i] 顶点 i 的魅力值 c[i] 覆盖顶点 i ...
- ES的java端API操作
首先简单介绍下写这篇博文的背景,最近负责的一个聚合型的新项目要大量使用ES的检索功能,之前对es的了解还只是纯理论最多加个基于postman的索引创建操作,所以这次我得了解在java端如何编码实现:网 ...
- netty系列之:来,手把手教你使用netty搭建一个DNS tcp服务器
目录 简介 搭建netty服务器 DNS服务器的消息处理 DNS客户端消息请求 总结 简介 在前面的文章中,我们提到了使用netty构建tcp和udp的客户端向已经公布的DNS服务器进行域名请求服务. ...
- Java:String、StringBuilder、StringJoiner学习笔记
String创建的俩种方式 1.直接赋值 String str = "Hello World!"; 当使用直接赋值的方式去创建字符串的时候,虚拟机会去串池里去检查字符串是否存在,如 ...
- 《Hierarchical Text-Conditional Image Generation with CLIP Latents》阅读笔记
概括 模型总述 本篇论文主要介绍DALL·E 2模型,它是OpenAI在2022年4月推出的一款模型,OpenAI在2021年1月推出了DALL·E模型,2021年年底推出了GLIDE模型. DALL ...
- @responseBody 返回更多数据
@responseBody:注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据,需 ...
- easyUI ajax拼接样式失效
重新渲染: $.parser.parse()
- 数电第一周总结_by_yc
数电第一周总结 重点:Verilog建模方式 结构级建模: 需基于电路原理图 module mux( input data0, input data1, input sel, output out); ...