关于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左右,感受!)

相关文章
相关标签/搜索