ffmpeg在android上輸出滑屏問題處理

來源:互聯網
上載者:User

標籤: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上輸出滑屏問題處理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.