ffempg支持文件解码
在做一个数据通道
要求有两个
1.支持打开实时流,解码得到图片
2.支持打开视频文件,得到解码图片
第一个要求前任已经实现
bool FfmpegStreamChr::Open(const char *pstrFilename)
{
Close();
avformat_network_init();
av_register_all(); std::string tempfile = pstrFilename;
AVDictionary* options = NULL;
if (tempfile.size() > )
{
if (memcmp(tempfile.c_str() + tempfile.size() - , "#tcp", ) == )
{
av_dict_set(&options, "rtsp_transport", "tcp", );
tempfile.erase(tempfile.size() - );
}
} //format_context_ = avformat_alloc_cotext(); av_dict_set(&options, "stimeout","", );
if (avformat_open_input(&format_context_, tempfile.c_str(), NULL, &options) < )
return false; if (avformat_find_stream_info(format_context_, nullptr) < )
return false; av_dump_format(format_context_, , tempfile.c_str(), ); video_stream_index_ = -; pts_first = true;
duration = format_context_->duration / AV_TIME_BASE; int video_stream_idx = av_find_best_stream(format_context_, AVMEDIA_TYPE_VIDEO, -, -, NULL, );
video_st = format_context_->streams[video_stream_idx]; for (unsigned int i = ; i < format_context_->nb_streams; i++)
{
AVCodecParameters *enc = format_context_->streams[i]->codecpar;
if (!enc)
continue;
if (AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream_index_ < )
{
width_ = enc->width;
height_ = enc->height; codec_ = avcodec_find_decoder(enc->codec_id);
if (!codec_)
return false;
codec_context_ = avcodec_alloc_context3(codec_);
if (!codec_context_)
return false;
if (avcodec_open2(codec_context_, codec_, NULL) < )
{
avcodec_free_context(&codec_context_);
return false;
} if (width_ && (enc->width != width_))
enc->width = width_; if (height_ && (enc->height != height_)) enc->height = height_; video_stream_index_ = i;
}
}
if (video_stream_index_ == -)
return false; yuv_frame_ = av_frame_alloc();
memset(rgb_data_, , sizeof(uint8_t *) * );
memset(rgb_line_size_, , sizeof(int) * );
rgb_line_size_[] = * width_;
DecodeToImage();
return true;
}
bool FfmpegStreamChr::DecodeToImage(){
if (!format_context_ ||!codec_context_)
return false;
int count_no_video_stream = ;
int continue_counts = ;
const int max_number_of_attempts = ;
// const int max_number_of_video_stream_attempts = 1 << 16;
for (;;)
{
TempImg = cv::Mat();
if (continue_counts > max_number_of_attempts)
return false;
// opt_time = GetTickCount();
int ret = av_read_frame(format_context_, &packet_);
if (ret == AVERROR(EAGAIN))
{
++continue_counts;
continue;
}
if (ret < )
continue;
if (packet_.stream_index != video_stream_index_)
{
// count_no_video_stream++;
//if (count_no_video_stream > max_number_of_video_stream_attempts)
// return false;
av_packet_unref(&packet_);
TempImg.release();
continue;
}
// std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();
ret = avcodec_send_packet(codec_context_, &packet_);
if (avcodec_receive_frame(codec_context_, yuv_frame_) == )
{
//std::chrono::system_clock::time_point t2 = std::chrono::system_clock::now();
if (!y2r_sws_context_)
{
y2r_sws_context_ = sws_getContext(width_, height_,
codec_context_->pix_fmt, codec_context_->width, codec_context_->height, /*video_stream_->codec->pix_fmt*/ AV_PIX_FMT_BGR24, /*SWS_BICUBIC*/ SWS_BILINEAR, NULL, NULL, NULL);
if (!y2r_sws_context_)
{
av_packet_unref(&packet_);
TempImg.release();
continue;
}
}
if (!TempImg.data)
TempImg.create(height_, width_, CV_8UC3);
rgb_data_[] = TempImg.data;
if (sws_scale(y2r_sws_context_, yuv_frame_->data, yuv_frame_->linesize, , codec_context_->height, rgb_data_, rgb_line_size_) <= )
{
av_packet_unref(&packet_);
TempImg.release();
av_frame_unref(yuv_frame_);
return false;
}
// std::chrono::system_clock::time_point t3 = std::chrono::system_clock::now();
//printf("decode : %d , switch : %d\n", std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count(), std::chrono::duration_cast<std::chrono::milliseconds>(t3 - t2).count());
if (pts_first)
{
bg_pts = packet_.pts;
pts_first = false;
}
//timestamp = yuv_frame_->pts*av_q2d(video_st->time_base);
// timestamp = (packet_.pts - bg_pts)*av_q2d(video_st->time_base);
// durationstamp = duration;
av_packet_unref(&packet_);
av_frame_unref(yuv_frame_);
// return true;
LOG_DEBUG() << "SendToAll \n";
SendToAll(TempImg);
}
++continue_counts;
av_packet_unref(&packet_);
}
}
解码文件的时候报如下错
Error splitting the input into NAL units
加入如下代码添加到open函数的54行后面,正常解码文件
//TODO:: add to hanldle file
if (avcodec_parameters_to_context(codec_context_, enc) < ){
return false;
}
ffempg支持文件解码的更多相关文章
- RPC基于http协议通过netty支持文件上传下载
本人在中间件研发组(主要开发RPC),近期遇到一个需求:RPC基于http协议通过netty支持文件上传下载 经过一系列的资料查找学习,终于实现了该功能 通过netty实现文件上传下载,主要在编解码时 ...
- CListCtrlEx:一个支持文件拖放和实时监视的列表控件——用未公开API函数实现Shell实时监视
一.需求无论何时,当你在Explorer窗口中创建.删除或重命名一个文件夹/文件,或者插入拔除移动存储器时,Windows总是能非常快速地更新它所有的视图.有时候我们的程序中也需要这样的功能,以便当用 ...
- HDFS只支持文件append操作, 而依赖HDFS的HBase如何完成数据的增删改查
转:http://www.th7.cn/db/nosql/201510/135382.shtml 1. HDFS的文件append功能 早期版本的HDFS不支持任何的文件更新操作,一旦一个文件创建.写 ...
- Openresty + nginx-upload-module支持文件上传
0. 说明 这种方式其实复杂,麻烦!建议通过这个方式搭建Openresty文件上传和下载服务器:http://www.cnblogs.com/lujiango/p/9056680.html 1. 包下 ...
- 修改Typora的代码以支持文件夹和文件混合排序
用Markdown文件写笔记,用文件夹做分类,整个笔记文档项目构成了一个树形结构.笔记文章之间.文章与分类之间经常有特定的先后顺序,于是就在文件名前面加上数字前缀来控制排序.但是,Windows的文件 ...
- java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 使用过程 和servlet差不多
java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 也仿照着 netty处理了NIO的空轮询BUG 本项目并不复杂 代码不多 ...
- 【Linux_Fedora_应用系列】_2_如何安装视频播放器和视频文件解码
在前面的一篇博文中,我们进行了音乐播放器的安装和解码器的安装.[Linux_Fedora_应用系列]_1_如何安装音乐播放器和mp3解码 这里我们来进行视频播放器的安装.我们还是通过yum方式安装. ...
- FFmpeg4.0笔记:本地媒体文件解码、帧格式转换、重采样、编码、封装、转封装、avio、硬解码等例子
Github https://github.com/gongluck/FFmpeg4.0-study/blob/master/official%20example/my_example.cpp #in ...
- springmvc学习笔记--支持文件上传和阿里云OSS API简介
前言: Web开发中图片上传的功能很常见, 本篇博客来讲述下springmvc如何实现图片上传的功能. 主要讲述依赖包引入, 配置项, 本地存储和云存储方案(阿里云的OSS服务). 铺垫: 文件上传是 ...
随机推荐
- HDU5983Pocket Cube
Pocket Cube Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Tota ...
- MYSQL常见运算符和函数
字符函数 (1)CONCAT():字符连接 SELECT CONCAT('IMOOC','-','MySQL');//IMOOC-MySQL SELECT CONCAT (first_name,las ...
- Scala中的override
Scala中的override override是覆盖的意思,在很多语言中都有,在scala中,override是非常常见的,在类继承方面,它和java不一样,不是可写可不写的了,而是必须写的.如果不 ...
- 深入理解java虚拟机_第三章(上)----->垃圾收集器与内存分配策略
1. 前言 这一版块内容比较多,分为两篇文章来做笔记.本文讲述上半部分垃圾收集部分;下一篇文章写内存分配部分. 概述 对象已死吗? 引用技术算法 可达性分析算法 再谈引用 两次标记 回收方法区 2. ...
- 集训 D1T1 clique
将点(xi,wi)看成区间(xi-wi,xi+wi),那么两个点有连边当且仅当两个区间没有公共点.删去所有包含其它区间的区间,在剩下的区间中每次贪心取一个能取的坐标最小的区间. #include< ...
- Java 面试宝典
1. 类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,他们的执行顺序 答:先静态.先父后子. 先静态:父静态 > 子静态 优先级:父类 > 子类 静态代码块 ...
- SSIS中循环遍历组件[Foreach Loop Container]
背景 每月给业务部门提取数据,每个分公司都要提取一般,先跑SQL,再粘贴到Excel中,然后发邮件给相关的人员.费时费力,还容易粘贴错位.因此,需要通过一个程序完成这些步骤.我首先想到的是通过SSIS ...
- Struts2学习笔记整理(一)
最近在学习框架,很多人建议我直接学SSM,SSM看了一段时间后发现很多东西虽然可以用了,但是并不是很了解,所以我打算重新来过.从SSH开始学习,前面已经大致的学习了Hibernate,对于Hibern ...
- leetcode第一刷_Populating Next Right Pointers in Each Node II
很自然的推广,假设去掉全然二叉树的条件呢?由于这个条件不是关键,因此不会影响整体的思路.做法依旧是每次找到一层的起点,然后一层一层的走. 假设是全然二叉树的话,每层的起点就是上一层起点的左孩子,兄弟之 ...
- Java高级开发工程师面试——多线程
来自:Sanesee 链接:http://www.sanesee.com/article/java-engineer-interview-of-thread 1.进程和线程的区别? 进程是一个具有独立 ...