最近一直加班加點進行基于Hi3559AV100平臺的BOXER-8410AI板載開發,在開發的程序中,遇到了相當多的問題,其一是板載的開發資料沒有且功能不完整,廠家不提供太多售后技術支持,廠家對部分硬體沒有進行開發,如MIPI介面沒有進行開發,且最基本的SDK版本包及環境搭建也需要自己去網上找且從頭弄,好在之前有Hi3519A平臺的開發經驗,但還是遇到了很多問題;其二是網上相關H3559AV100平臺開發資料很少,也導致了開發的周期拉長;其三是個人專案經驗還是相對較少(雖然之前搞過電賽、robmaster等都拿了國獎,但是知識儲備還是不夠),之后將陸續記錄基于Hi3559AV100平臺的開發程序,希望能給您帶來一些技術支持,早之前開發的記錄將稍后推出,今天和大家說下關于pthread_create()下MJPEG格式的select監聽,
參考man pthread_create,pthread_create()函式在呼叫中啟動一個新執行緒處理,給出pthread_create的特征:
1 #include <pthread.h> 2 3 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 4 void *(*start_routine) (void *), void *arg); 5 //例如在VDEC 向視頻解碼通道發送碼流資料 對函式 HI_MPI_VDEC_SendStream()進行操作時 6 pthread_create(&pVdecThread[i], 0, SAMPLE_COMM_VDEC_SendStream, (HI_VOID *)&pstVdecSend[i]);
新的執行緒通過呼叫start_routine()來開始執行,在此處,start_routine()為SAMPLE_COMM_VDEC_SendStream,arg<------->pstVdecSend[i]作為start_routine()的唯一引數傳遞;而thread這個識別符號是用來參考在后續呼叫其他pthread功能,成功創建執行緒后,回傳0,
執行緒分兩類,一類是joinable,一類是detached,對于joinable執行緒,需要用pthread_join()來等待執行緒結束并獲取狀態;而對于detached執行緒終止,其所用的資源系統會自動回收的,不需要進行操作,對于執行緒創建來說,默認是joinable執行緒,如果大家需要detached執行緒,則需要修改attr引數,
創建SAMPLE_COMM_VDEC_SendStream執行緒后,其主要是實作了PT_MJPEG解碼協議型別資料的幀頭幀尾判別及資料發送,但是在執行緒中用了V4L2介面:
1 ioctl(video_fd, VIDIOC_DQBUF, &readbuffer)
出現了VIDIOC_DQBUF /capture data failed及Segmentation fault等等:

Segmentation fault的原因很大程度上是陣列的索引超界了,根據自己的程式修改相應的位置,我改的位置為:
1 pu8Buf = malloc(pic_size); //6144002 //pu8Buf = malloc(pstVdecThreadParam->s32MinBufSize);
而關于VIDIOC_DQBUF fault,網上說可能是使用非阻塞方式打開設備檔案造成的,即對應用程式進行一些非阻塞(non-blocking)操作(對檔案或者socket),如果使用非阻塞模式呼叫視頻設備,即使尚未捕獲到資訊,驅動依舊會把快取(DQBUFF)里的東西回傳給應用程式,例如,以O_NONBLOCK的標志打開檔案/socket/FIFO,如果你連續做read操作而沒有資料可讀,此時程式不會阻塞起來等待資料準備就緒回傳,read函式會回傳一個error,
因此open設備節點的時候(如open /dev/video*時),不建議用非阻塞形式打開,因為MJEPG格式時,每次去讀取資料,底層資料不一定就緒了,因此會回傳錯誤,串口會有茫茫多的錯誤列印,建議是阻塞方式打開,用select去監聽所有的fd,
1 /* According to POSIX.1-2001, POSIX.1-2008 */ 2 #include <sys/select.h> 3 4 /* According to earlier standards */ 5 #include <sys/time.h> 6 #include <sys/types.h> 7 #include <unistd.h> 8 9 int select(int nfds, fd_set *readfds, fd_set *writefds, 10 fd_set *exceptfds, struct timeval *timeout);
首先和大家說一下select監聽的機制:用阻塞的方式去open設備節點,select去監聽所有的fd;select函式用于在非阻塞中,當一個套接字或一組套接字有信號時通知你,系統提供select函式來實作多路復用輸入/輸出模型,select一旦發現監聽的設備都不可用(不可讀、也不可寫、也沒有例外),那么主行程進入休眠狀態,一旦監聽的設備中,只要有一個設備可用(可讀或者可寫或者有例外)都會喚醒休眠的主行程,select也就會回傳,注意這個函式僅僅起到一個監聽的功能,資料的后續處理,通過read,write,ioctl來進行的,本專案中測驗實作:
1 s_value = https://www.cnblogs.com/iFrank/p/select(fdmax + 1, &fds, NULL, NULL, &tv); 2 3 if(s_value =https://www.cnblogs.com/iFrank/p/= -1) 4 { 5 if(EINTR == errno) 6 { 7 perror("select"); 8 continue; 9 } 10 SAMPLE_PRT("Fail to select\n"); 11 break; 12 } 13 if(s_value =https://www.cnblogs.com/iFrank/p/= 0) 14 { 15 SAMPLE_PRT("select Timeout\n"); 16 continue; 17 }
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/256268.html
標籤:其他
上一篇:Jenkins 構建及回滾任務
