ffmpeg在android上输出滑屏问题处理

ffmpeg部分机器上有花屏的问题


原代码例如以下:

while(av_read_frame(formatCtx, &packet)>=0 && !_stop && NULL!=window && bInit) {// Is this a packet from the video stream?if(packet.stream_index==videoStream) {// Decode video frameavcodec_decode_video2(codecCtx, decodedFrame, &frameFinished,&packet);// Did we get a video frame?if(frameFinished) {// Convert the image from its native format to RGBAsws_scale(sws_ctx,(uint8_t const * const *)decodedFrame->data,decodedFrame->linesize,0,codecCtx->height,frameRGBA->data,frameRGBA->linesize);if(packet.dts == AV_NOPTS_VALUE&& decodedFrame->opaque && *(uint64_t*)decodedFrame->opaque != AV_NOPTS_VALUE){pts = *(uint64_t *)decodedFrame->opaque;LOGD("pst1: %d",pts);}else if(packet.dts != AV_NOPTS_VALUE) {pts = packet.dts;LOGD("pst2: %d",pts);} else {pts = 0;LOGD("pst3: %d",pts);}//pts = av_q2d(codecCtx->time_base) * 1000000.0 * i * 2;pts *= 1000;//LOGD("debug %d,%d,%f",pts, (long)(av_q2d(codecCtx->time_base) * 1000000.0 * i * 2), av_q2d(codecCtx->time_base));if(0 == pts || 0 == baseTime){baseTime = av_gettime() - pts;LOGD("BASETIME: %d",baseTime);}else{waitTime = (baseTime + pts) - av_gettime();LOGD("WAITTIME: %d, %d",waitTime,pts);}//waitTime = (av_q2d(codecCtx->time_base) * 1000.0 - 0.0) * 1000;if(waitTime>0)usleep(waitTime);if(!_stop){synchronized(lockWindow){if(!_stop && NULL!=window){// lock the window bufferif (ANativeWindow_lock(pWin, &windowBuffer, NULL) < 0) {LOGE("cannot lock window");} else {// draw the frame on buffer//LOGD("copy buffer %d:%d:%d", width, height, width*height*RGB_SIZE);//LOGD("window buffer: %d:%d:%d", windowBuffer.width, windowBuffer.height, windowBuffer.stride);memcpy(windowBuffer.bits, buffer,  width * height * RGB_SIZE);// unlock the window buffer and post it to displayANativeWindow_unlockAndPost(pWin);// count number of frames++i;}}}}}}
细致分析后发现 部分分辨率又可以正常展示,感觉是宽度错位导致的,分析例如以下:

ORG: 176  * 144   F
X2:  352 288   O
X3:  528 432   F
X4:  704 576   O
X6:  1056 *   O


X1.1 193 158   F
X1.2 211 172   F
X1.5 264 216   F


X0.5 88 72    F




X2?

: 352 290   O
X2?: 352 600   O
X2?: 352 720   O
X4?: 704 720   O
X6?: 1056 720   O
   


1280 ---1312
        1056
1184
1248 ok

发现分辨率依照%64+32对齐, 感觉是内存对齐造成的, 查看ANativeWindow_Buffer例如以下

typedef struct ANativeWindow_Buffer {// The number of pixels that are show horizontally.int32_t width;// The number of pixels that are shown vertically.int32_t height;// The number of *pixels* that a line in the buffer takes in// memory.  This may be >= width.int32_t stride;// The format of the buffer.  One of WINDOW_FORMAT_*int32_t format;// The actual bits.void* bits;// Do not touch.uint32_t reserved[6];
} ANativeWindow_Buffer;


输出stride和width的日志发现,假设正常显示则stride==width, 通过凝视能够看出应该是内存对齐问题导致的,调整代码:

if(packet.stream_index==videoStream) {// Decode video frameavcodec_decode_video2(codecCtx, decodedFrame, &frameFinished,&packet);// Did we get a video frame?

if(frameFinished) { // Convert the image from its native format to RGBA sws_scale ( sws_ctx, (uint8_t const * const *)decodedFrame->data, decodedFrame->linesize, 0, codecCtx->height, frameRGBA->data, frameRGBA->linesize ); if(packet.dts == AV_NOPTS_VALUE && decodedFrame->opaque && *(uint64_t*)decodedFrame->opaque != AV_NOPTS_VALUE) { pts = *(uint64_t *)decodedFrame->opaque; LOGD("pst1: %d",pts); } else if(packet.dts != AV_NOPTS_VALUE) { pts = packet.dts; LOGD("pst2: %d",pts); } else { pts = 0; LOGD("pst3: %d",pts); } //pts = av_q2d(codecCtx->time_base) * 1000000.0 * i * 2; pts *= 1000; //LOGD("debug %d,%d,%f",pts, (long)(av_q2d(codecCtx->time_base) * 1000000.0 * i * 2), av_q2d(codecCtx->time_base)); if(0 == pts || 0 == baseTime) { baseTime = av_gettime() - pts; LOGD("BASETIME: %d",baseTime); }else{ waitTime = (baseTime + pts) - av_gettime(); LOGD("WAITTIME: %d, %d",waitTime,pts); } //waitTime = (av_q2d(codecCtx->time_base) * 1000.0 - 0.0) * 1000; if(waitTime>0) usleep(waitTime); if(!_stop) { synchronized(lockWindow) { if(!_stop && NULL!=window) { // lock the window buffer if (ANativeWindow_lock(pWin, &windowBuffer, NULL) < 0) { LOGE("cannot lock window"); } else { // draw the frame on buffer //LOGD("copy buffer %d:%d:%d", width, height, width*height*RGB_SIZE); //LOGD("window buffer: %d:%d:%d", windowBuffer.width, windowBuffer.height, windowBuffer.stride); //memcpy(windowBuffer.bits, buffer, width * height * RGB_SIZE); if(windowBuffer.width >= windowBuffer.stride){ memcpy(windowBuffer.bits, buffer, width * height * RGB_SIZE); }else{ //skip stride-width 跳过padding部分内存 for(int i=0;i<height;++i) memcpy(windowBuffer.bits + windowBuffer.stride * i * RGB_SIZE , buffer + width * i * RGB_SIZE , width * RGB_SIZE); } // unlock the window buffer and post it to display ANativeWindow_unlockAndPost(pWin); // count number of frames ++i; } } } } } }


通过行拷贝方式,跳过后面对齐部分的内存, 

解决这个问题,


转载于:https://www.cnblogs.com/yangykaifa/p/6992349.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429216.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ff14拆区后哪个服务器人最多,FF14拆区可以转服吗 拆区期间转服教程

FF14拆区可以转服吗?随着FF14拆区改动的来临&#xff0c;很多玩家开始迷惘&#xff0c;毕竟自从开了跨服以后&#xff0c;跟同区不同服的亲友一起游戏的机会大大增加了。现在随着拆区改动&#xff0c;不少玩家还不知道能不能继续跟亲友玩耍&#xff0c;想知道拆区可以转服吗&a…

索引快速查询

一、索引 索引是表的目录&#xff0c;在查找内容之前可以先在目录中查找索引位置&#xff0c;以此快速定位查询数据。对于索引&#xff0c;会保存在额外的文件中。 名词&#xff1a; 覆盖索引&#xff1a; - 在索引文件中直接获取数据 索引合并&#xff1a; …

服务器红帽操作系统安装,怎么安装red hat操作系统

红帽在2014年6月发布了最新旗舰版企业操作系统——红帽企业Linux 7。基于红帽企业Linux 7操作系统&#xff0c;企业可整合裸机服务器、 虚拟机、基础设施即服务(IaaS)和平台即服务(PaaS)&#xff0c;以构建一个强大稳健的数据中心环境&#xff0c;满足不断变化的业务需求。学习…

Java中Arraylist源码分析

前言&#xff1a;ArrayList作为我们常用的一个集合数据类型&#xff0c;我们在代码中经常用它来装载数据&#xff0c;可谓是和HashMap一样常用的集合类型了。我们经常用它&#xff0c;那么就有必须知道它的内部工作原理&#xff0c;比如它是如何添加进去数据的&#xff0c;它内…

联想服务器系统安装bios设置,Windows 8操作系统如何通过Legacy BIOS与UEFI两种模式安装...

Win8系统相对于Win7系统在开机速度上有相当大的提升&#xff0c;这是因为Win8系统为了提升系统性能和对硬件的优化&#xff0c;加入了诸如开机引导及应用预缓存等技术。而其中的UEFI BIOS引导&#xff0c;则能使平台开机更智能&#xff0c;开机速度更快。对比采用传统BIOS引导启…

系统云服务器,系统云服务器

系统云服务器 内容精选换一换当云服务器密码即将过期、密码泄露或首次登录时(首次登录云服务器建议您修改初始密码)&#xff0c;您可以参考本节操作在操作系统内部修改云服务器密码。优先推荐您参考在控制台重置云服务器密码&#xff0c;在控制台重置实例的登录密码。可以登录云…

如何在Global.asax中判断是否是ajax请求

今天在一个应用场景中需要在Global.asax中判断一个请求是否是ajax请求&#xff0c;而在ASP.NET MVC中已经提供了一个现成的扩展方法IsAjaxRequest&#xff1a; namespace System.Web.Mvc {public static class AjaxRequestExtensions{public static bool IsAjaxRequest(this Ht…

csp真题 202109-2非零段划分C++代码(100分)

试题编号&#xff1a; 202109-2 试题名称&#xff1a; 非零段划分 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 512.0MB 样例1输入 11 3 1 2 0 0 2 0 4 5 0 2样例1输出 5样例1解释 p2时&#xff0c;A[3,0,2,0,0,2,0,4,5,0,2]&#xff0c;5个非零段依次为[3]、[2]、[2…

c++中四舍五入取整、向上取整和向下取整问题

方法一&#xff1a;利用c函数 四舍五入&#xff1a;round()函数 向上取整&#xff1a;ceil()函数 向下取整&#xff1a;floor()函数 #include <iostream> #include <cmath>//函数头文件 using namespace std; int main() {double a1.2;double b3.7;cout<<&q…

SQL PROMPT5.3.4.1的一些设置选项

摘自&#xff1a;http://www.cnblogs.com/furenjian/p/4519426.html sql prompt这个工具安装好之后就可以在SSMS里使用代码提示功能 园子里非常多的文章&#xff1a;例如SQLSERVER开发利器XXXXXX http://www.cnblogs.com/VAllen/archive/2012/09/08/SQLPrompt.html http://www.…

csp真题202112-1 序列查询 (100分)

#include <iostream> using namespace std; int A[1000000]{0};//c中一定一定要要记得给变量赋初始值&#xff0c;会减少很多不必要的麻烦 //尽可能将数组量大的数组定义在函数外面&#xff0c;不要在函数内部定义大数组 int main() {int n0,N0,sum0,i0;cin>>n&g…

云麦小米华为体脂秤怎么样_测评华为智能体脂秤,比小米智能体重秤贵30元到底差别在哪里?...

“流浪的好奇”每天更新最新科技资讯和产品测评内容&#xff0c;欢迎您关注订阅&#xff01;我们之前说过华为可不仅仅只有5G通讯技术和智能手机&#xff0c;华为杂货铺里的产品虽然不如小米杂货铺那么的丰富&#xff0c;但是也不是空铺一个&#xff0c;还是有一些华为主业之外…

c++中引用和指针的区别

指针是指向一块内存&#xff0c;它的内容是所指内存的地址&#xff1b; 而引用则是指向某块内存变量的一个别名&#xff0c;相当于变量的另一个名字。 例如&#xff1a; #include <stdio.h> int main() {int a2;int &ba;printf("a:%d\n",a);printf("…

什么是大数据,怎么理解和应对大数据时代

什么是大数据&#xff0c;怎么理解和应对大数据时代 在大数据与深度学习中蝶化的人工智能。当代人工智能离不开大数据和深度学习算法。我们先来了解什么是大数据&#xff0c;大数据的本质是什么&#xff0c;在大数据时代我们应该如何应对&#xff1f; 当我们谈论数据的时候我们…

android 手机获取公网ip_KSWEB 旧手机搭建网站服务

? 感谢你阅读「 Android 应用 」的第 113篇分享文章KSWEB 是一款由俄罗斯开发者开发的一款可以在 Android 手机上安装建站相关服务的应用&#xff0c;支持 Lighttpd、Nginx、Apache、MySQL、FTP、PHP 等。打开应用后点击不再提醒忽略弹窗&#xff0c;给予权限后等待片刻按照提…

phpStydy配置memcache扩展

phpStydy配置memcache扩展 先提示一点&#xff1a;我电脑是win7 64 位的&#xff0c;但我用的环境是phpstudy (php5.6nginx); 下面的下载里我下载64位软件安装后没反映&#xff0c;因为phpstudy环境是32位的,下载32位安装后memcache就成功了; 一、下载并安装memcached服务器端软…

外部仓库_仓库主要作业流程和WMS作业优化方案

仓库在人们眼中一直是低效、高成本的地方&#xff0c;即便是增加人手也很难做好仓库管理。那么我们应该采取哪些方式来管理&#xff0c;才能做到降本增效呢&#xff1f;首先我们需要先了解仓库主要作业流程及在作业中存在的痛点。1入库流程a.商品SKU太多&#xff0c;部分形状相…

java IO流(上)

1.字节流 1.1 IO流概述和分类【理解】 1.IO流介绍 IO&#xff1a;输入/输出(Input/Output)流&#xff1a;是一种抽象概念,是对数据传输的总称.也就是说数据在设备间的传输称为流,流的本质是数据传输IO流就是用来处理设备间数据传输问题的.常见的应用: 文件复制; 文件上传; 文…

《科技之巅2》序——机器智能数据智能:工具之王

原文链接 “凡是过去&#xff0c;皆为序曲。”——莎士比亚 通过不断发明工具&#xff0c;人类科技指数级进化。语言汇聚原始部落&#xff0c;马镫开启了中世纪的欧洲文明&#xff0c;“高产种子”引发人口爆炸&#xff0c;蒸汽机创造工业文明&#xff0c;大规模集成电路激活数…

一、java面向对象基础

1. 类和对象 面向对象和面向过程的思想对比 : ​ 面向过程 &#xff1a; 是一种以过程为中心的编程思想&#xff0c;实现功能的每一步&#xff0c;都是自己实现的 ​ 面向对象 &#xff1a; 是一种以对象为中心的编程思想&#xff0c;通过指挥对象实现具体的功能 1.1 类和对…