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 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上输出滑屏问题处理的更多相关文章
- FFmpeg在Android上的移植之第一步
http://blog.sina.com.cn/s/blog_69a04cf40100x1fr.html 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmpeg开发的. ...
- FFmpeg在Android上的移植优化步骤
http://blog.csdn.net/feixiang_john/article/details/7894188 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmp ...
- android 添加左右滑屏手势
今天要在自己的项目中添加左右滑动,实现日期的加减(原来已经做了加减按键).滑动在一个中间的layout中进行 思路:添加左右划屏幕判断,得到判断后模拟加减按键按下. 模拟按键按下用 mbotton.p ...
- 【Android 界面效果29】研究一下Android滑屏的功能的原理,及scrollTo和scrollBy两个方法
Android中的滑屏功能的原理是很值得我们去研究的,在知道这两个原理之前,有必要先说说View的两个重要方法,它们就是scrollTo 和scrollBy. Android View视图是没有边界的 ...
- Android之滑屏动画和自定义控件
滑屏动画 在Android系统中,通过手势识别切换界面时,通常会在界面切换时加入动画,以提高用户的体验效果,这种动画一般都采用平移动画,下一个界面进入时,上一个界面移除屏幕. 图中标识的均为左上角坐标 ...
- (转)【移动开发】Android中三种超实用的滑屏方式汇总(ViewPager、ViewFlipper、ViewFlow)
转自: http://smallwoniu.blog.51cto.com/3911954/1308959 现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习 ...
- Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解
前言: 虽然本文标题的有点标题党的感觉,但无论如何,通过这篇文章的学习以及你自己的实践认知,写个简单的滑屏小 Demo还是just so so的. 友情提示: 在继续往下面读之前,希望您对以下知识点 ...
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
今天给大家介绍下Android中滑屏功能的一个基本实现过程以及原理初探,最后给大家重点讲解View视图中scrollTo 与 scrollBy这两个函数的区别 . 首先 ,我们必须明白在Android ...
- Android中三种超实用的滑屏方式汇总(转载)
Android中三种超实用的滑屏方式汇总 现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习惯性的有事没事的左右滑屏,也不知道在干什么...嘿嘿),由于 ...
随机推荐
- Ubuntu14.04编译WebRTC For Android代码 2014-07-24
整整快一年没有写博客了.近期基于Google开源的WebRTC项目做了一款音视频聊天的即时通信项目,期间在下载WebRTC代码时就碰到了一些问题.在此以作记录,也希望可以帮助到正在下载编译WebRTC ...
- js 获取手机浏览器类型,修改css文件的class的值
/*========================================= 函数功能:获取浏览器类型 =========================================*/ ...
- lightoj--1294--Largest Box(三分)
Largest Box Time Limit: 2000MS Memory Limit: 32768KB 64bit IO Format: %lld & %llu Submit Sta ...
- db file sequential read等待事件 --转载
db file sequential read db file sequential read等待事件有3个参数:file#,first block#,和block数量.在10g中,这等待事件受到用户 ...
- PHP中出现Notice: Undefined index的三种解决办法
前一段做的一个PHP程序在服务器运行正常,被别人拿到本机测试的时候总是出现“Notice: Undefined index:”这样的警告,这只是一个因为PHP版本不同而产生的警告(NOTICE或者WA ...
- Qt-窗口部件概念介绍
前言:包括基础窗口部件QWidget.对话框QDialog.QFrame类族 .按钮部件.行编辑器.数值设定框以及滑块部件. 一.基础窗口部件QWidget 窗口部件(Widget)是Qt中建立用户界 ...
- Oracle中的数据字典技术及常用数据字典总结
一.Oracle数据字典 数据字典是Oracle存放有关数据库信息的地方,其用途是用来描述数据的.比如一个表的创建者信息,创建时间信息,所属表空间信息,用户访问权限信息等.当用户在对数据库中的数据进行 ...
- 使用DWR实现JS调用服务端Java代码
DWR简介 DWR全称Direct Web Remoting,是一款非常优秀的远程过程调用(Remote Procedure Call)框架,通过浏览器提供的Ajax引擎实现在前端页面的JS代码中调用 ...
- mysql update join优化update in查询效率
数据库版本:5.6.16 update in 修改数据,结果执行时间过慢,一直不出结果. SQL语句及执行计划如下: UPDATE erp_order_extra SET last_time=1231 ...
- here.less
<html><head><title>Test Less</title><link rel="stylesheet/less" ...