海思3519 qt ffmpeg 软解码播放avi
在海思3519上基于qt采用ffmpeg对avi进行解码显示,其中ffmpeg的配置,qt的配置在前文中已经说明,在此不再赘述。
解码
解码在单独的线程中进行,具体的代码如下:
void VideoPlayer::run()
{
AVFormatContext *fmt_ctx = NULL;
AVCodecContext *dec_ctx = NULL;
AVFrame *pf = av_frame_alloc();
AVFrame *pfc = av_frame_alloc();
int video_stream_index;
int width, height;
av_register_all();
video_stream_index = getStream(&fmt_ctx, &dec_ctx, "./source_file/test.avi");
decoder(&fmt_ctx, &dec_ctx, video_stream_index, pf, pfc, &width, &height);
}
int VideoPlayer::decoder(AVFormatContext** fmt_ctx, AVCodecContext** dec_ctx,
int video_stream_index, AVFrame *pFrame, AVFrame *pFrameColor, int* width, int* height)
{
AVPacket packet;
int i = 0;
int frameFinished;
uint8_t *buffer;
int numBytes;
char filename[32];
numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, (*dec_ctx)->width, (*dec_ctx)->height);
buffer = (uint8_t*)av_malloc(numBytes);
avpicture_fill((AVPicture *)pFrameColor, buffer, AV_PIX_FMT_RGB24, (*dec_ctx)->width, (*dec_ctx)->height);
while (av_read_frame(*fmt_ctx, &packet) >= 0) {
if (packet.stream_index == video_stream_index) {
avcodec_decode_video2(*dec_ctx, pFrame, &frameFinished, &packet);
if (frameFinished)
{
struct SwsContext *img_convert_ctx = NULL;
img_convert_ctx = sws_getCachedContext(img_convert_ctx, (*dec_ctx)->width,
(*dec_ctx)->height, (*dec_ctx)->pix_fmt,
(*dec_ctx)->width, (*dec_ctx)->height,
AV_PIX_FMT_RGB24, SWS_BICUBIC,
NULL, NULL, NULL);
if (!img_convert_ctx) {
fprintf(stderr, "Cannot initialize sws conversion context\n");
exit(1);
}
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data,
pFrame->linesize, 0, (*dec_ctx)->height, pFrameColor->data,
pFrameColor->linesize);
QImage tmpImg((uchar *)buffer,(*dec_ctx)->width,(*dec_ctx)->height,QImage::Format_RGB888);
QImage image = tmpImg.copy();
emit sig_GetOneFrame(image);
}
}
av_free_packet(&packet);
}
printf("finished");
av_free(buffer);
av_free(pFrameColor);
av_free(pFrame);
avcodec_close(*dec_ctx);
avformat_close_input(fmt_ctx);
}
int VideoPlayer::getStream(AVFormatContext **fmt_ctx, AVCodecContext **dec_ctx, char* file_name)
{
int video_stream_index = -1;
int ret;
bool decoder_init = false;
if ((ret = avformat_open_input(fmt_ctx, file_name, NULL, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "fail to open input file.\n");
return ret;
}
if ((ret = avformat_find_stream_info(*fmt_ctx, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "fail to find stream information.\n");
avformat_close_input(fmt_ctx);
return ret;
}
for (int i = 0; i < (*fmt_ctx)->nb_streams; i++) {
if ((*fmt_ctx)->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
if (!decoder_init) {
*dec_ctx = (*fmt_ctx)->streams[i]->codec;
AVCodec *cod = avcodec_find_decoder((*dec_ctx)->codec_id);
if (!cod) {
av_log(NULL, AV_LOG_ERROR, "fail to find decoder.\n");
avformat_close_input(fmt_ctx);
return 1;
}
if (avcodec_open2(*dec_ctx, cod, NULL) != 0) {
av_log(NULL, AV_LOG_ERROR, "fail to open codecer.\n");
avformat_close_input(fmt_ctx);
return 2;
}
decoder_init = true;
}
}
return 0;
}
return video_stream_index;
}
解码后将数据转换成RGB并进一步转换成QImage,每解码一帧数据后发送一个信号用于更新图像显示
QImage tmpImg((uchar *)buffer,(*dec_ctx)->width,(*dec_ctx)->height,QImage::Format_RGB888);
QImage image = tmpImg.copy();
emit sig_GetOneFrame(image);
显示
具体代码如下:
void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setBrush(Qt::black);
painter.drawRect(0, 0, this->width(), this->height()); //先画成黑色
if (mImage.size().width() <= 0) return;
QImage img = mImage.scaled(this->size(),Qt::KeepAspectRatio);
int x = this->width() - img.width();
int y = this->height() - img.height();
x /= 2;
y /= 2;
painter.drawImage(QPoint(x,y),img); //画出图像
}
void MainWindow::slotGetOneFrame(QImage img)
{
mImage = img;
update();
}
总结:
编译后能够在板子上成功运行,但是显示比较缓慢,这块具体的原因没有进一步分析,因为后来才用了硬解码的方式,所以放弃了深入研究,参考代码获取
海思3519 qt ffmpeg 软解码播放avi的更多相关文章
- 海思3559A QT 5.12移植(带webengine 和 opengl es)
海思SDK版本:Hi3559AV100_SDK_V2.0.1.0 编译器版本:aarch64-himix100-linux-gcc 6.3.0(这个版本有点小问题,使用前需要先清除本地化设置) $ e ...
- 海思3519A 移植ffmpeg
文件下载 下载x264 git clone git://git.videolan.org/x264.git 下载ffmpeg git clone git://source.ffmpeg.org/ffm ...
- Qt + FFmpeg 本地音频播放器
http://pan.baidu.com/s/1hqoYXrI
- FFmpeg开发笔记(十):ffmpeg在ubuntu上的交叉编译移植到海思HI35xx平台
FFmpeg和SDL开发专栏(点击传送门) 上一篇:<FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放>下一篇:敬请期待 前言 将ffmpeg移植到海思H ...
- OpenCV开发笔记(七十四):OpenCV3.4.1+ffmpeg3.4.8交叉编译移植到海思平台Hi35xx平台
前言 移植opencv到海思平台,opencv支持对视频进行解码,需要对应的ffmpeg支持. Ffmpeg的移植 Ffmpeg的移植请参考之前的文章:<FFmpeg开发笔记(十): ...
- (转)海思平台HI35XX系列内存设置
海思平台的内存分为两部分,一部分给系统使用,另外的一部分给多媒体使用.可以通过cat /proc/meminfo查看系统内存和cat /proc/media-mem 查看多媒体内存使用情况. /pro ...
- 海思3519A 移植 Qt 5.5.1
源码下载 网址:qt-everywhere-opensource-src-5.5.1.tar.gz 配置生成MakeFile 文件 解压源码包,在源码包路径下生成配置 MakeFile : ./con ...
- 使用C#+FFmpeg+DirectX+dxva2硬件解码播放h264流
本文门槛较高,因此行文看起来会乱一些,如果你看到某处能会心一笑请马上联系我开始摆龙门阵 如果你跟随这篇文章实现了播放器,那你会得到一个高效率,低cpu占用(单路720p视频解码播放占用1%左右cpu) ...
- 海思HI35xx平台软件开发快速入门之H264解码实例学习
ref :https://blog.csdn.net/wytzsjzly/article/details/82500277 前言 H264视频编码技术诞生于2003年,至今已有十余载,技术相当成熟 ...
随机推荐
- null与“ ”的区别
null是空对象,""是空字符串 null可以赋值给任何对象 ""只能赋值给字符串对象 String s=null; string.trim()就会抛出为空的e ...
- .NET三种异步模式(APM、EAP、TAP)
APM模式: .net 1.0时期就提出的一种异步模式,并且基于IAsyncResult接口实现BeginXXX和EndXXX类似的方法. .net中有很多类实现了该模式(比如HttpWebReque ...
- Java System.getProperty vs System.getenv
转自:https://www.baeldung.com/java-system-get-property-vs-system-getenv 1. Introduction The package ja ...
- 生成指定python项目中所有的依赖文件
一. pipreqs工具 这个工具的好处是可以通过对项目目录的扫描,自动发现使用了那些类库,自动生成依赖清单. 缺点是可能会有些偏差,需要检查并自己调整下. 安装: pip install pipre ...
- MySQL实战45讲学习笔记:第二十讲
一.引子 在上一篇文章最后,我给你留了一个关于加锁规则的问题.今天,我们就从这个问题说起吧. 为了便于说明问题,这一篇文章,我们就先使用一个小一点儿的表.建表和初始化语句如下(为了便于本期的例子说明, ...
- 文件夹如何添加备注(保证可以WIN7 WIN10测试通过)
网上很多方法都有人说试过了,不可以.其实不是不可以,他们都没有说完整 今天自己弄了下,弄出来了,废话不多说先上图 如果需要用备注排序,那么就需要把排序的选项加上备注的分类 1.获得desktop.in ...
- Oracle RAC 修改SPFILE路径 文件查看
在spfile场景下创建pfile: SQL> create pfile='/opt/oracle/init_pfile.ora'; 创建新spfile: SQL> create spfi ...
- WebAPI 使用控制台启动
using System; using System.Web.Http; using System.Web.Http.SelfHost; namespace UAC_OAuth2Center { pu ...
- 框架之jQuery妙用
1.jQuery介绍 jQuery是一个轻量级的.兼容多浏览器的JavaScript库. jQuery使用户能够更方便地处理HTML Document.Events.实现动画效果.方便地进行Ajax交 ...
- linux 安装jdk 和tomcat
#创建用户是为了区分操作权限,如果不区分的话可以直接用root用户执行文件目录为 /usr/lcdc #创建lcdc用户, #其中-d和-m选项用来为登录名lcdc, /usr/lcdc(/usr为默 ...