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 frame
avcodec_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);
// unlock the window buffer and post it to display
ANativeWindow_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 frame
avcodec_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;
}
}
}
}
}
}

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

解决这个问题,

ffmpeg在android上输出滑屏问题处理的更多相关文章

  1. FFmpeg在Android上的移植之第一步

    http://blog.sina.com.cn/s/blog_69a04cf40100x1fr.html 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmpeg开发的. ...

  2. FFmpeg在Android上的移植优化步骤

    http://blog.csdn.net/feixiang_john/article/details/7894188 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmp ...

  3. android 添加左右滑屏手势

    今天要在自己的项目中添加左右滑动,实现日期的加减(原来已经做了加减按键).滑动在一个中间的layout中进行 思路:添加左右划屏幕判断,得到判断后模拟加减按键按下. 模拟按键按下用 mbotton.p ...

  4. 【Android 界面效果29】研究一下Android滑屏的功能的原理,及scrollTo和scrollBy两个方法

    Android中的滑屏功能的原理是很值得我们去研究的,在知道这两个原理之前,有必要先说说View的两个重要方法,它们就是scrollTo 和scrollBy. Android View视图是没有边界的 ...

  5. Android之滑屏动画和自定义控件

    滑屏动画 在Android系统中,通过手势识别切换界面时,通常会在界面切换时加入动画,以提高用户的体验效果,这种动画一般都采用平移动画,下一个界面进入时,上一个界面移除屏幕. 图中标识的均为左上角坐标 ...

  6. (转)【移动开发】Android中三种超实用的滑屏方式汇总(ViewPager、ViewFlipper、ViewFlow)

    转自: http://smallwoniu.blog.51cto.com/3911954/1308959 现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习 ...

  7. Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解

    前言:  虽然本文标题的有点标题党的感觉,但无论如何,通过这篇文章的学习以及你自己的实践认知,写个简单的滑屏小 Demo还是just so so的. 友情提示: 在继续往下面读之前,希望您对以下知识点 ...

  8. Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明

    今天给大家介绍下Android中滑屏功能的一个基本实现过程以及原理初探,最后给大家重点讲解View视图中scrollTo 与 scrollBy这两个函数的区别 . 首先 ,我们必须明白在Android ...

  9. Android中三种超实用的滑屏方式汇总(转载)

    Android中三种超实用的滑屏方式汇总   现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习惯性的有事没事的左右滑屏,也不知道在干什么...嘿嘿),由于 ...

随机推荐

  1. json 与其他数据 格式转换及json学习新得

    jsonobject   var a={"a","A"}   通过json都对象能很轻松的操作json数据 jsonString     var a=" ...

  2. java里面包的重要性-管理类文件

    包的必要性 包是用来给java源文件分门别类的,java中一个包在windows下就是一个文件夹.包的全限定名是从根文件夹開始的(\src文件夹)以点号作为分隔符,包名和包名之间使用点号隔开,java ...

  3. C#趣味程序---三色球问题

    问题:若一个口袋中放有12个球,3红3白和6黑,问从袋中随意取8个球,有多少种不同的颜色搭配? using System; namespace ConsoleApplication1 { class ...

  4. 在Kali上安装打印机

    在Kali 2.0上安装打印机 最近在玩儿渗透测试,就把自己的办公电脑做成了Kali,可是发现办公室的网络打印机没办法正常使用,上网查了一下,把整个过程简单的记录一下,省的忘记了 1.安装cups a ...

  5. [转]Linux常用命令学习

    转自 https://www.cnblogs.com/gaojun/p/3359355.html 1.ls命令 就是list的缩写,通过ls 命令不仅可以查看linux文件夹包含的文件,而且可以查看文 ...

  6. memcache session共享问题(ubuntu)

    memcache session共享问题 环境:三台ubuntu 12.04.5虚拟机,均安装php-fpm,并重用了之前搭建的简单的负载均衡 u1(192.168.240.130)    u2(19 ...

  7. easyui的增删改

    陈旧的开发模式PM:“我要这个功能”后端:“这个先找前端做个模板”前端:“模板做完了”后端:“我来对接一下,这里样式不对”前端:“我改完了”后端:“功能交付”PM:“春节要加这个活动”后端:“这个先找 ...

  8. zabbix-server端监控MySQL服务

    Zabbix 监控MySQL数据库 为server.zabbix,com 添加服务模块 创建MySQL服务图形 Server.zabbix.com 服务器操作 [root@server ~]# cd ...

  9. Java 面向对象详解

    0 引言 接触项目开发也有很长一段时间了,最近开始萌发出想回过头来写写以前学过的基础知识的想法. 1 面向对象 面向对象(Object Oriented)是一种新兴的程序设计方法,或者是一种新的程序设 ...

  10. 《Exception》第八次团队作业:Alpha冲刺(第一天)

    一.项目基本介绍 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 Exception 作业学习目标 1.掌握软件测试基础技术.2.学习迭代式增量软 ...