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服务). 铺垫: 文件上传是 ...
随机推荐
- mysql 系统性浅聊 myisam 存储引擎【原创】
>>思维导图 >>介绍 mysql中的存储引擎都是以插件的形式存在,目前用的最多存储引擎就是innodb和myisam.MySQL5.5.5以后(包括5.5.5)默认使用Inn ...
- HDU1018-Big Number
Big Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
- Linux下编译memecaced
安装memecached的时候要先把依赖的软件全部的安装上! 第一步: 在limux编译memcached需要 :yum install gcc make libtool autoconf 着 ...
- javascript算法题判断输入年份是否是闰年
用户输入一个年份,判断这个年是否是闰年.判断闰年条件:① 非整百年数除以4,无余为闰,有余不闰:② 整百年数除以400,无余为闰,有余不闰.比如:2000年,整百数年,就要用②公式,除以400,无余数 ...
- 基本MarkDown语法
引言 字符串作为一种常见的数据类型,在日常中我们面临各式各样的字符串处理问题,那么,这就要求我们必须掌握一些常用的字符串处理函数.本文尽量囊括常用的字符串处理函数,此文也作为个人的小总结. Pytho ...
- PCA, SVD以及代码示例
本文是对PCA和SVD学习的整理笔记,为了避免很多重复内容的工作,我会在介绍概念的时候引用其他童鞋的工作和内容,具体来源我会标记在参考资料中. 一.PCA (Principle component a ...
- MySQL用户管理及SQL语句详解
1.1 MySQL用户管理 1.1.1 用户的定义 用户名+主机域 mysql> select user,host,password from mysql.user; +--------+--- ...
- 【NOIP2013提高组】火柴排队
https://www.luogu.org/problem/show?pid=1966 Σ(ai-bi)2=Σai2+Σbi2-2Σai*bi,要使Σ(ai-bi)2最小,则需2Σai*bi最大. 由 ...
- 关于C#中函数的认识
对于C#语言中的函数,大概分之为函数的声明及其调用. 函数的声明: 1.函数的声明是指给一段代码取名称. 2.函数的声明位置必须在类中. 3.函数声明的语法: 函数声明的语法:static void ...
- 递归回溯 UVa140 Bandwidth宽带
本题题意:寻找一个排列,在此排序中,带宽的长度最小(带宽是指:任意一点v与其距离最远的且与v有边相连的顶点与v的距离的最大值),若有多个,按照字典序输出最小的哪一个. 解题思路: 方法一:由于题目说结 ...