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服务). 铺垫: 文件上传是 ...
随机推荐
- springboot添加swagger2组件
swagger2是一个可以构建和调试RESTful API文档的组件,利用swagger2的注解可以快速的在项目中构建Api文档,并且提供了测试API的功能 1,引入依赖 <dependency ...
- Chrome浏览器读写系统剪切板
IE浏览器支持直接读写剪切板内容: window.clipboardData.clearData(); window.clipboardData.setData('Text', 'abcd'); 但是 ...
- 200行Java代码搞定计算器程序
发现了大学时候写的计算器小程序,还有个图形界面,能够图形化展示表达式语法树,哈哈;) 只有200行Java代码,不但能够计算加减乘除,还能够匹配小括号~ 代码点评: 从朴素的界面配色到简单易懂错误提示 ...
- NIO相关基础篇二
转载请注明原创出处,谢谢! 上篇NIO相关基础篇一,主要介绍了一些基本的概念以及缓冲区(Buffer)和通道(Channel),本篇继续NIO相关话题内容,主要就是文件锁.以及比较关键的Selecto ...
- Spring之AOP一
面向切片式编程不仅在Java中存在,在其他语言也是存在,例如asp.net的管道模型中,可以利用aop来进行自定义一些操作,比如权限认证.日志等.今天主要是引入AOP,具体它涉及到的专有名词先不做解释 ...
- C++map类型 之 简单介绍
一:map的前世今生 (1)从关联容器与顺序容器说起.关联容器通过键(key)存储和读取元素.而顺序容器则通过元素在容器中的位置顺序存储和訪问元素(vector,queue,stack,list等). ...
- Cocos2d-x 3.1.1 学习日志10--一进来你就知道了Box2D了
error LNK2019: 无法解析的外部符号 "public: __thiscall b2Draw::b2Draw(void)" (? ?0b2Draw@@QAE@XZ),该符 ...
- HTTP Status 500 - Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement
1.什么操作出现:当我在项目中添加产品或者修改时,浏览器出现HTTP Status 500 - Request processing failed; nested exception is org.h ...
- 企业级PPTP服务器
第一个里程碑:检查系统是否支持ppp [root@m01 ~]# cat /dev/ppp cat: /dev/ppp: No such device or address 如果出现以上提示则说明pp ...
- hibernate框架(4)---主键生成策略
主键生成策略 常见的生成策略分为六种 1.increment 由Hibernate从数据库中取出主键的最大值(每个session只取1次),以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的 ...