当前位置: 首页 > news >正文

西安建设网站首页合肥瑶海区天气

西安建设网站首页,合肥瑶海区天气,网站信管局备案,哪个公司做农村产权交易网站0.本节内容 本节是将前面学习的 XThread 和 实际解封装的代码结合起来。 1.解封装回顾 前面我们对于一个mp4文件的第一步就是解封装。 流程如下: /// 1.解封装,在XDemux.h 定义Open方法,返回值就是 AVFormatContext*const char* in_url_400 …

0.本节内容

本节是将前面学习的 XThread 和 实际解封装的代码结合起来。

1.解封装回顾

前面我们对于一个mp4文件的第一步就是解封装。

流程如下:

    /// 1.解封装,在XDemux.h 定义Open方法,返回值就是 AVFormatContext*const char* in_url_400 = "./120/400_300_25.mp4";XDemux xdemux1;/// 1.1打开 解封装上下文AVFormatContext* inavformatContext = xdemux1.Open(in_url_400);/// 1.2 设置解封装上下文到 xformat.h的成员变量中的xdemux1.setAVFormatContext(inavformatContext);

AVFormatContext* XDemux::Open(const char* url) {AVFormatContext* in_avformatContext = nullptr;int ret = avformat_open_input(&in_avformatContext,url, nullptr, nullptr);if (ret < 0 ) {cout << "func XDemux::Open error because avformat_open_input error, so return nullptr" << endl;PrintErr(ret);return nullptr;}ret = avformat_find_stream_info(in_avformatContext, nullptr);if (ret < 0) {cout << "func XDemux::Open error because avformat_find_stream_info error, so return nullptr" << endl;avformat_close_input(&in_avformatContext);PrintErr(ret);return nullptr;}//打印输入封装信息av_dump_format(in_avformatContext, 0, url, 0);return in_avformatContext;}

void XFormat::setAVFormatContext(AVFormatContext* avformatContext) {unique_lock<mutex> lock(mux_);//1. 清空上一次保存的 this->avformatContext_if (this->avformatContext_) {//1.1 判断是 解封装上下文,即通过avformat_open_input方法创建出来的 avformatcontext,则通过 avformat_close_input方法 释放 this->avformatContext_if (this->avformatContext_->iformat) {avformat_close_input(&this->avformatContext_);this->avformatContext_ = nullptr;}//1.2 判断是 封装上下文,即通过avformat_alloc_output_context2方法创建出来的 avformatcontext,则通过avformat_free_context()//实际 代码测试,如果this->avformatContext_中的pb是打开的,也要释放。else if (this->avformatContext_->oformat) {if (this->avformatContext_->pb) {avio_closep(&this->avformatContext_->pb);}avformat_free_context(this->avformatContext_);this->avformatContext_ = nullptr;}else {avformat_free_context(this->avformatContext_);this->avformatContext_ = nullptr;}}//2. 将参数传递过来的 avformatContext 保存 到内部变量this->avformatContext_ = avformatContext;//3. 注意的是,传递过来的参数 avformatContext有可能是nullptr,如果是nullptr,就是清理 保存的avformatContext_,那么到这里就returnif (this->avformatContext_ == nullptr) {return;}// 4. 之所以前面会有return,是因为后面在 this->avformatContext 不为nullptr的情况下,还需要从 this->avformatContext_ 中记录其他参数。//4.1 记录 audio_index,video_index,audiostreambasetime,videostreambasetime,audiocodeid,videocodeidfor (int i = 0; i < this->avformatContext_->nb_streams;i++) {if (this->avformatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {this->video_index_ = i; //记录video_indexthis->video_codec_id_ = this->avformatContext_->streams[i]->codecpar->codec_id; //记录 videocodeidthis->video_stream_timebase_.num = this->avformatContext_->streams[i]->time_base.num; //记录video timebase.numthis->video_stream_timebase_.den = this->avformatContext_->streams[i]->time_base.den; //记录video timebase.denthis->video_width_ = this->avformatContext_->streams[i]->codecpar->width;this->video_height_ = this->avformatContext_->streams[i]->codecpar->height;this->video_pixformat_ = this->avformatContext_->streams[i]->codecpar->format;this->video_avg_frame_rate_.num = this->avformatContext_->streams[i]->avg_frame_rate.num;this->video_avg_frame_rate_.den = this->avformatContext_->streams[i]->avg_frame_rate.den;cout << "video avg_frame_rate.num = " << this->avformatContext_->streams[i]->avg_frame_rate.num << endl; //25cout << "video avg_frame_rate.den = " << this->avformatContext_->streams[i]->avg_frame_rate.den << endl; //1// avg_frame_rate 和 r_frame_rate的不同,前者是平均 frame_rate; 后者不是,cout << "video r_frame_rate.num = " << this->avformatContext_->streams[i]->r_frame_rate.num << endl;//25cout << "video r_frame_rate.den = " << this->avformatContext_->streams[i]->r_frame_rate.den << endl;//1}if (this->avformatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {this->audio_index_ = i;//记录audio_indexthis->audio_codec_id_ = this->avformatContext_->streams[i]->codecpar->codec_id; //记录 audiocodeidthis->audio_stream_timebase_.num = this->avformatContext_->streams[i]->time_base.num;//记录audio timebase.numthis->audio_stream_timebase_.den = this->avformatContext_->streams[i]->time_base.den;//记录audio timebase.denthis->audio_channel_layout_ = this->avformatContext_->streams[i]->codecpar->channel_layout;//AV_CH_LAYOUT_STEREOthis->audio_sample_rate_ = this->avformatContext_->streams[i]->codecpar->format;//AV_SAMPLE_FMT_S16this->audio_channels_ = this->avformatContext_->streams[i]->codecpar->channels;//2this->audio_sample_rate_ = this->avformatContext_->streams[i]->codecpar->sample_rate;//44100///channels 和 channel_layout这两个参数再ffmpeg7.0都已经删除了,在4.3上可以通过如下的函数转化 /// int av_get_channel_layout_nb_channels(uint64_t channel_layout);/// int64_t av_get_default_channel_layout(int nb_channels);/// cout << "audio avg_frame_rate.num = " << this->avformatContext_->streams[i]->avg_frame_rate.num << endl; //0cout << "audio avg_frame_rate.den = " << this->avformatContext_->streams[i]->avg_frame_rate.den << endl; //0cout << "audio r_frame_rate.num = " << this->avformatContext_->streams[i]->r_frame_rate.num << endl; //0cout << "audio r_frame_rate.den = " << this->avformatContext_->streams[i]->r_frame_rate.den << endl; //0}}
}

内部实现的核心函数如下:

int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);

url参数不仅仅指本地文件,也可以是网络文件。本节主要是对于 监控摄像头 使用 RTSP 协议时候的处理问题 学习。

FFmpeg 4.3 H265 二十二.3,avformat_open_input 支持打开的协议-CSDN博客

2. 那么我们首先要将前面的 url 改成 rtsp监控摄像头 的url.

之前的 url 是 本地文件下的一个MP4

const char* in_url_400 = "./120/400_300_25.mp4";

我们当前是使用笔记本摄像头,通过VLC转换成 RTSP协议的数据。

对应的url 要换成 

const char* in_url_400 = "rtsp://:8554/111";

FFmpeg 4.3 H265 二十二.4,使用计算机摄像头,通过VCL软件, 模拟 监控摄像头 的 RTSP 流-CSDN博客

3.监控摄像头RTSP解封装的线程问题:

3.1 断线问题--程序启动的时候,监控摄像头就没有打开

3.2 断线问题--程序在执行的时候,网络信号不好,甚至是网络断开了

3.3 断线问题--程序在执行的时候,监控摄像头断开了

av_dict_set("&options","stimeout","1000000",0);//这个timecout是对于 socket 本身的设定。对于不同的平台这个参数 并不可靠,代码兼容性不强,因此此行代码不能解决核心问题,应该想其他方法。

实际上AVFormatContext 结构体中,给我们提供概率 AVIOInterruptCB 这个回调结构体:

    /*** Custom interrupt callbacks for the I/O layer.** demuxing: set by the user before avformat_open_input().* muxing: set by the user before avformat_write_header()* (mainly useful for AVFMT_NOFILE formats). The callback* should also be passed to avio_open2() if it's used to* open the file.*/AVIOInterruptCB interrupt_callback;

/*** Callback for checking whether to abort blocking functions.* AVERROR_EXIT is returned in this case by the interrupted* function. During blocking operations, callback is called with* opaque as parameter. If the callback returns 1, the* blocking operation will be aborted.** No members can be added to this struct without a major bump, if* new elements have been added after this struct in AVFormatContext* or AVIOContext.*/
typedef struct AVIOInterruptCB {int (*callback)(void*);void *opaque;
} AVIOInterruptCB;

其中 callback 是中断的回调函数, opaque是回调函数的参数。

调用时机:

在读取数据的时候,或者是在connect 建立连接的时候,每次等待都会调用 callback函数。

如何控制,我们使用callback的返回值来控制。

如果callback函数 。return 0,则 读取数据的函数会继续等待,这个读取数据的函数应该就是int av_read_frame(AVFormatContext *s, AVPacket *pkt)。如果 return 1,那么读取数据的函数就会退出,不会一直阻塞。 

如果我们设定了 avformatContext 的AVIOInterruptCB 

http://www.dtcms.com/a/489513.html

相关文章:

  • 网站备案人的法律风险旅行社网站的建设开题报告
  • 网站注册商标网站出现乱码怎么办
  • 一般的学校网站怎么做wordpress会员登录界面美化
  • Wordpress虚拟资源下载类主题seo在线排名优化
  • 电商网站的对比网页制作平台哪个最好
  • 做网站编辑有人带吗网页版网游
  • 免费做四年级题的网站微信小程序制作软件哪个好
  • 专业建站公司建站系统该规划哪些内容建筑工程信息价哪里可以查询
  • 网站备案能不能出现世界学设计哪个网站好
  • 赣州做网站的直播开放平台登陆
  • 宜昌网站建设设计wordpress怎样弄栏目
  • 图片设计网站免费桔子建站是什么平台
  • 推荐好的设计网站404网站页面进入
  • 网站开发 用户角色贵州建设监督管理局网站
  • 焦作网站开发公司电话平凉哪家做企业网站
  • 网站为什么没有排名了水溶花边外发加工网
  • wordpress网站下方网站 中国最早做网站的
  • 网站建设与网页制作盒子模型做商城网站需要在北京注册公司吗
  • 中国住房和城乡建设网网站网站建设实训心得体会300字
  • 企业网站页脚信息wordpress链接样式表
  • 我的家乡网页制作素材二十个优化
  • 免费网站建设的wordpress主题少儿教育类
  • 卖磁铁的网站怎么做莱芜网站建设设计外包
  • 备案期间网站能用吗全球咨询公司最新排名
  • wordpress 下载站模板汽车配件加工网
  • 自动优化网站建设咨询wordpress配置伪静态
  • 网站的栏目设计怎么做企业网站的建设目的有哪些
  • 手工艺品出口网站建设策划书做一个英文的公司网站多少钱
  • 网站开发之后如何上传源码外贸网站如何做外链
  • 企业网站建设三网合一网站建设公司如何签单