標籤:bsp mod pac term net androi number syn val
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 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);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 displayANativeWindow_unlockAndPost(pWin);// count number of frames++i;}}}}}}
通過行拷貝方式,跳過後面對齊部分的記憶體,
解決這個問題,
ffmpeg在android上輸出滑屏問題處理