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

ffmpeg在android上输出滑屏问题处理相关推荐

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

    从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmpeg开发的.如今最火的智能手机操作系统Android上的很多第三方视频播放器也是基于FFmpeg实现全格式支持.由于A ...

  2. android上hdmi投屏TV未铺满,让4K电视满血重生 手机投屏体验比一比

    在路上第3季我们来到了美丽的惠州,海岛风情的轻松舒适,遇上俄罗斯世界杯正式开幕,当然少不了小伙伴们的彻夜娱乐.看完球赛有什么娱乐项目,该不是各自在床上开黑吃鸡?这次我们教你更爽的玩法. 面板技术升级, ...

  3. 在android上启动分屏的方法

    android7.0上已经支持分屏,但是国内有的手机虽然升到了7.0,但是还不能使用分屏功能. 在这种情况下,可以使用命令启动分屏, 并且是无需root的. 首先要先连接adb,不会连接的请自行百度. ...

  4. 欢乐鼠标自动点击器_使用ESP32 DIY蓝牙自动点击器,滑屏器

    前言 因为爱薅羊毛,然后正好最近免费车一趟接一趟,咪咕开完,京东开,京东开完掌阅开,下一个不知道是谁,,,,可我又不是什么很有耐心的人,虽然我喜欢看书,但是如果规定时间,加上页数限制我就很烦,所以我还 ...

  5. android 使用shell模拟触屏_Appium常用操作之「微信滑屏、触屏操作」

    坚持原创输出,点击蓝字关注我吧 作者:清菡 博客:oschina.云+社区.知乎等各大平台都有. 目录 一.滑屏操作 1.访问之后,马上就滑屏可以吗? 2.连续实现 2 次滑屏 3.代码 二.模拟触屏 ...

  6. Android中三种超实用的滑屏方式汇总(ViewPager、ViewFlipper、ViewFlow)

    现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习惯性的有事没事的左右滑屏,也不知道在干什么...嘿嘿),由于前段时间项目的需要,所以也对其研究了一下,总的 ...

  7. Android中实现Launcher功能之四---滑屏初探 scrollTo 以及 scrollBy方法使用说明

     本文原创 ,转载必须注明出处 :http://blog.csdn.net/qinjuning 今天给大家介绍下Android中滑屏功能的一个基本实现过程以及原理初探,最后给大家重点讲解View视图中 ...

  8. android 滑屏功能,Android 滑屏效果实现方式汇总

    Android的滑屏,最近在研究这个东西,发现新浪微博的客户端.腾讯微博的客户端都有这个功能.目前到今天为止,腾讯和微博的客户端都是使用viewPager控件写的,可能重写了一些地方.而腾讯老版本的q ...

  9. android 滑动取值_Android中滑屏实现

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

最新文章

  1. 安装网页图形界面管理Linux
  2. 测试计划和自动化测试思考
  3. python opencv 腐蚀_opencv 图像的腐蚀(erode)和膨胀(dilate) 开运算以及闭运算
  4. 互换两个变量,不使用中间变量
  5. 台湾国立大学郭彦甫Matlab教程笔记(18) root finding(symbolic)
  6. [你必须知道的.NET]第二十回:学习方法论
  7. qt5 窗体显示完毕信号_iPhone手机信号不好?试试这样设置,随时随地让你的手机信号满格...
  8. Connectivity Matrices(连通矩阵)
  9. shell中$(( )) 与 $( ) 还有${ }的区别
  10. Java Web底层(1)
  11. 升压和升降压拓扑中IDC与IO的关系推导 // 《精通开关电源设计》P41式2-2
  12. 《深度学习推荐系统》读书笔记
  13. 宁波市重点首版次软件认定申报,区块链可申请 | 产业区块链发展周报
  14. 终级免杀之PcShare Vs KV2006
  15. java商品销售管理系统_基于SSM框架下的JAVA商场销售管理系统
  16. Excel如何批量添加邮箱后缀
  17. 关于TDataSet和TFDJsonDataSets在处理数据库字段的字符集和执行效率方面的比较
  18. 集体照的拍摄与后期合成处理
  19. ddr3写操作app_wdf_end说明
  20. 职中计算机基础教学案例,浅淡职中计算机专业教学

热门文章

  1. 查看zookeeper版本
  2. vmware安装centos问题
  3. [转载来之雨松:NGUI研究院之为什么打开界面太慢(十三)]
  4. jacob 实现Office Word文件格式转换
  5. QuickPart应用系列
  6. 1、jeecg 笔记开篇
  7. 浅析dedecms织梦网站留言板提交时验证码错误的解决办法
  8. 使用session保持登录状态,cookie保存用户账号密码
  9. js bom and dom
  10. 树控件,多条件组合查询与混合数据源