av_read_frame 阻塞卡死解決辦法
阿新 • • 發佈:2019-02-10
參考:http://www.mamicode.com/info-detail-561129.html
FFmpeg長時間無響應的解決方法
需要解決的問題
1、FFmpeg去連線的時候相機不線上導致avformat_open_input等函式一直死等,造成程式卡死
2、av_read_frame的過程中相機斷開連線導致讀取碼流一直死等
解決方法
開啟流媒體之前註冊FFmpeg回撥函式
AVFormatContext *m_pRtspFmt = avformat_alloc_context(); m_pRtspFmt->interrupt_callback.callback = AVInterruptCallBackFun; m_pRtspFmt->interrupt_callback.opaque = this;
回撥函式型別為:
typedef struct AVIOInterruptCB {int (*callback)(void*);void *opaque;} AVIOInterruptCB;
回撥函式中返回1則代表ffmpeg結束阻塞可以將操縱權交給使用者執行緒並返回錯誤碼
回撥函式中返回0則代表ffmpeg繼續阻塞直到ffmpeg正常工作為止
所以要退出死等則需要返回1
虛擬碼如下:
//相機連線類 class CIPCamera { public: CIPCamera(); ~CIPCamera(); //AVReadFrame超時回撥函式 static int AVInterruptCallBackFun(void *ctx); //讀取rtsp碼流執行緒 static DWORD WINAPI ReadStreamThread(LPVOID param); //心跳監控執行緒--監控執行緒是否死掉 static DWORD WINAPI MonitorThread(LPVOID param); }; int CIPCamera::AVInterruptCallBackFun(void *param) { CIPCamera *pCamera = (CIPCamera*)param; if (NULL == pCamera) return 0; if (pCamera->m_bQuitFFmpegBlock) { //通知FFMpeg可以從阻塞工作執行緒中釋放操作 return 1; } else { //通知FFMpeg繼續阻塞工作 return 0; } } //連線相機 讀取rtsp碼流執行緒 DWORD WINAPI CIPCamera::ReadStreamThread(LPVOID param) { CIPCamera *pCapture = (CIPCamera*)param; if (NULL == pCapture) return -1; pCapture->ConnectCamera(); while (pCapture->m_bWorkOK) { //FFmpeg讀取碼流 pCapture->ReadStream(); //傳送心跳 pCapture->HeartBeat(); Sleep(1); } return TRUE; } //監控執行緒 DWORD WINAPI CIPCamera::MonitorThread(LPVOID param) { CIPCamera *pCamera = (CIPCamera*)param; if (NULL == pCamera) return -1; while (pCamera->m_bReWork) { //如果心跳超時 if ( OK != pCamera->GetState(&nTimeOut);) { //則通知ffmpeg返回 pCamera->m_bWorkOK = FALSE; pCamera->m_bQuitFFmpegBlock = TRUE; } else { //ffmpeg繼續工作 pCamera->m_bWorkOK = TRUE; } Sleep(100); } return 0; }