關於IMX6Dl 芯片使用硬編解碼的問題記錄

NXP出了IMX6系列芯片(如今應該是9系列最新了),性能至關於咱們嵌入式行業,已經很是優秀(能夠作不少事情)緩存

同時,IMX6DL IMX6Q 自帶vpu硬編解碼,用來處理下視頻也是很是不錯的,對於咱們來講的確很是合適異步

 

衆所周知,mxc_vpu_test.out 是官方提供的測試程序,用於測試各類功能,源碼也提供,函數

可是系統裏面源碼是跟其餘測試程序整合在一塊兒的,每每咱們想要在此基礎上改改弄弄,而後從新編譯是件困難的事情(大神除外)性能

固然,也能夠從網上下載 mxc_vpu_test.out 的源碼,貌似也有(csdn就有),但可能跟你板子的庫文件版本不一致,會致使各類問題測試

總之這是一個繞不過去的坑(編譯過不算,正常運行編解碼纔算)編碼

 

以上問題,困擾好久,後來版本搞對了,纔算順利過去。 ---- 記一下,若是用測試程序 編譯沒有問題,但測試解碼時候,出現段錯誤,每每是你所用h文件跟板子so庫用的h文件版本不同,也就是某些結構體size不同。spa

 

另一個問題:線程

假設在同一塊板子上,先採集USB攝像頭的數據,而後vpu編碼產生h264流,而後經過「管道」發送給解碼線程,解碼線程收到h264流,而後調用vpu的解碼,而後再顯示。固然這個步驟是異步的,兩個線程(進程),中間涉及到數據交互的。code

源代碼是參考 mxc_vpu_test.out 的源碼視頻

ps: 說到這裏,可能有些人會說,既然是一塊板子,那麼直接顯示USB攝像頭上的數據,不是更好的?嗯,我舉的例子,的確這樣作更好,但不要忘記現實的項目多是這樣的需求:在本終端上顯示的畫面是其餘終端傳過來的h264數據,而本終端須要將本身的視頻流傳輸給對方(就比如視頻對講),這樣就須要一臺板子上同時編解碼(固然此時用的通道確定是兩個)

 

 

 

 

貌似應該沒有問題,也說得通,只要編解碼自己沒有問題,那麼問題就沒有。但現實每每是骨感的,的確是碰到問題

一開始懷疑管道寫錯了,但管道的確沒有問題

 

經過步驟printf 的方式,發現卡在:

 

 

 

也就是說 開始編碼的時候,就再也不返回。

分析了dec.c 的源碼:

dec這邊最後一步是出現這裏:

 

dec_fill_bsbuffer 其實是去讀取管道數據(因爲是阻塞式管道,不阻塞不行,不阻塞的話,這裏返回是0,那麼dec這邊會認爲「沒有數據」 天然退出)。此時卡住了。

緣由:

解碼這邊,在讀取管道數據以前,先調用 vpu_DecStartOneFrame ,這個函數會佔據vpu資源,

致使解碼那邊調用 vpu_EncStartOneFrame 函數卡死(由於獲取不到vpu資源,從而也沒有往下走)

這樣就造成了「死鎖」,編碼這邊等待vpu資源釋放(纔能有數據往管道里放),解碼這邊等待管道里有數據(才能完成解碼,從而才能釋放vpu資源)

 

也許,把 vpu_DecStartOneFrame 放在 dec_fill_bsbuffer 以後,是否可行?也不行,只是機率問題。

 

從現象來看,咱們也知道同一塊板子若是同時 vpu_DecStartOneFrame vpu_EncStartOneFrame是不行的

 

固然惟一的辦法就是錯時。

個人辦法也很簡單,利用一個緩衝,錯時,若是緩衝裏沒有數據,解碼這邊就不調用 vpu_DecStartOneFrame,線程等待就行了。

固然這個緩衝也有點小複雜,不是簡簡單單加個鎖就好了,仍是要考慮到各類狀況的。

 

下面亮出個人代碼:

 1 static char *m_pPipeBuf = NULL;  2 static int m_nNowPos = 0;  3 static int m_nGetPos = 0;  4 static pthread_mutex_t m_lock;  5 
 6 //創建緩存區
 7 void Safe_InitBuff()  8 {  9     if(m_pPipeBuf != NULL)  10  Safe_UnInitBuff();  11 
 12     pthread_mutex_init(&m_lock,NULL);  13     m_pPipeBuf = (char*)malloc(PIPE_LENTH + 1024);  14     m_nNowPos = 0;  15     m_nGetPos = 0;  16 }  17 
 18 void Safe_UnInitBuff()  19 {  20     if(m_pPipeBuf != NULL)  21  {  22         free(m_pPipeBuf);  23         m_pPipeBuf = NULL;  24 
 25         pthread_mutex_destroy(&m_lock);  26         m_nNowPos = 0;  27         m_nGetPos = 0;  28  }  29 }  30 
 31 //剩餘能夠存放 多少空間
 32 static int GetLastTemp()  33 {  34     int nLast = 0;  35 
 36     if(m_nNowPos >= m_nGetPos)  37  {  38         nLast = PIPE_LENTH - (m_nNowPos - m_nGetPos);  39  }  40     else
 41  {  42 
 43  }  44     return nLast;  45 }  46 
 47 static int AddToPipeBuf(void *pBuf,int nLen)  48 {  49     int nRes = -1;  50     if(m_pPipeBuf != NULL)  51  {  52         int nPos = m_nNowPos % PIPE_LENTH;  53         if ((nPos + nLen) > PIPE_LENTH)  54  {  55             int nCpLen = (PIPE_LENTH - nPos);  56             memcpy(&m_pPipeBuf[nPos],pBuf,nCpLen);  57 
 58             nPos = 0;  59             memcpy(&m_pPipeBuf[0],&pBuf[nCpLen],nLen - nCpLen);  60  }  61         else
 62  {  63             memcpy(&m_pPipeBuf[nPos],pBuf,nLen);  64  }  65 
 66         m_nNowPos = m_nNowPos + nLen;  67         nRes = nLen;  68  }  69 
 70     return nRes;  71 }  72 
 73 static int GetSavedLen()  74 {  75     int nLen = 0;  76     if (m_nNowPos == m_nGetPos)  77  {  78         nLen = 0;  79  }  80     else if(m_nNowPos > m_nGetPos)  81  {  82         nLen = m_nNowPos - m_nGetPos;  83  }  84     else
 85  {  86         //異常,不存在
 87  }  88 
 89     return nLen;  90 }  91 
 92 static int GetFromPipeBuf(void *pBuf,int nLen)  93 {  94     int nPos = (m_nGetPos % PIPE_LENTH);  95     int nRes = -1;  96 
 97     if (nLen > 0)  98  {  99         if ((nPos + nLen) > PIPE_LENTH) 100  { 101             int nCpLen = PIPE_LENTH - nPos; 102             //先拷貝末尾
103             memcpy(pBuf,&m_pPipeBuf[nPos],nCpLen); 104             nPos = 0; 105             memcpy(&pBuf[nCpLen], &m_pPipeBuf[0], nLen - nCpLen); 106  } 107         else
108  { 109             memcpy(pBuf,&m_pPipeBuf[nPos],nLen); 110  } 111 
112         nRes = nLen; 113         m_nGetPos = m_nGetPos + nLen; 114  } 115 
116     return nRes; 117 } 118 
119 //添加數據(若是數據已滿,等待)
120 int Safe_AddBuf(char *pBuf,int nLen) 121 { 122     int nRes = -1; 123     if(((nLen + 4) > PIPE_LENTH) || (m_pPipeBuf == NULL)) 124  { 125         return nRes; 126  } 127 
128     int bIsSaved = 0; 129     while (bIsSaved == 0) 130  { 131         pthread_mutex_lock(&m_lock); 132         int nLast = GetLastTemp(); 133 
134         if(nLast >= (nLen + 4)) 135  { 136             char strNUM[5]; 137             memcpy(strNUM, &nLen, 4); 138             AddToPipeBuf(strNUM, 4); 139 
140             nRes = AddToPipeBuf(pBuf, nLen); 141             bIsSaved = 1; 142  } 143 
144         pthread_mutex_unlock(&m_lock); 145 
146         if(bIsSaved == 0) 147  { 148             //< delay 10ms .continue waited
149             printf("Safe_SaveBuf: delay 10ms .continue waited\n"); 150             usleep(10000); 151  } 152  } 153 
154     return nRes; 155 } 156 
157 //提取數據(若是沒有數據,等待)
158 int Safe_GetBuf(char *pBuf,int nLen) 159 { 160     static int lastReadAll = 1;     ///< 取完 161  static int nLastRead = 0; ///< 還有多少個沒讀完 162 
163     int nRes = -1; 164     if((nLen <= 0) || (m_pPipeBuf == NULL)) 165  { 166         return 0; 167  } 168 
169     int bIsGet = 0; 170     while (bIsGet == 0) 171  { 172         pthread_mutex_lock(&m_lock); 173         int nSaved = GetSavedLen(); 174         int nframe_length = 0; 175 
176         if(nSaved > 0) 177  { 178             if(lastReadAll == 1) 179  { 180                 if(nSaved > 4) 181  { 182                     GetFromPipeBuf(&nframe_length,4); 183 
184                     if(nframe_length > nLen) 185  { 186                         lastReadAll = 0; 187 
188                         nLastRead = nframe_length - nLen; 189                         nframe_length = nLen; 190                         //外部存儲 不夠(先無論,除非長度寫錯了)
191  } 192                     else
193  { 194                         //取走這幀
195                         lastReadAll = 1; 196                         nLastRead = 0; 197  } 198  } 199                 else
200  { 201                     //錯誤---
202  } 203  } 204             else
205  { 206                 //繼續-
207                 if(nLen >= nLastRead) 208  { 209                     //此次空間夠了
210                     if(nSaved >= nLastRead) 211  { 212                         //把上次未取走的 所有取走
213                         nframe_length = nLastRead; 214                         nLastRead = 0; 215                         lastReadAll = 1; 216  } 217                     else
218  { 219                         nframe_length = nSaved; 220                         nLastRead = nLastRead - nSaved; 221                         lastReadAll = 0; 222  } 223  } 224                 else
225  { 226                     //空間不夠 nLastRead
227                     if(nSaved >= nLen) 228  { 229                         nframe_length = nLen; 230                         nLastRead = nLastRead - nLen; 231                         lastReadAll = 0; 232  } 233                     else
234  { 235                         nframe_length = nSaved; 236                         nLastRead = nLastRead - nSaved; 237                         lastReadAll = 0; 238  } 239  } 240  } 241 
242             if(nframe_length > 0) 243  { 244                 nRes = GetFromPipeBuf(pBuf, nframe_length); 245                 bIsGet = 1; 246  } 247  } 248 
249         pthread_mutex_unlock(&m_lock); 250 
251         if(bIsGet == 0) 252  { 253             //< delay 100ms .continue waited
254             printf("Safe_GetBuf: delay 10ms .continue waited\n"); 255             usleep(10000); 256  } 257  } 258     return nRes; 259 } 260 
261 int Safe_IsHaveData() 262 { 263     int nSaved = 0; 264     pthread_mutex_lock(&m_lock); 265     nSaved = GetSavedLen(); 266     pthread_mutex_unlock(&m_lock); 267     return nSaved; 268 }

 

題外話,問題也解決了,效率很是高,cpu僅佔3%~5%左右,性能上也很強勁,這款cpu不錯

很流暢,延時不多(100ms~200ms左右,感受!)

相關文章
相關標籤/搜索