国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

發(fā)燒友實測 | i.MX8MP 基于HTTP網(wǎng)頁服務(wù)器和UDP上位機的MJPG碼流傳輸(mjpg-steamer)

飛凌嵌入式 ? 2022-01-10 16:30 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

作者|donatello1996

來源 | 電子發(fā)燒友

題圖|飛凌嵌入式

本文采用的硬件板卡為飛凌嵌入式OKMX8MP-C開發(fā)板,系統(tǒng)版本Linux5.4.70+Qt5.15.0,主要介紹基于HTTP網(wǎng)頁服務(wù)器和UDP上位機的MJPG碼流傳輸

MJPG格式作為一種持續(xù)傳輸?shù)囊曨l碼流,在遠(yuǎn)程監(jiān)控領(lǐng)域中應(yīng)用較廣,而實現(xiàn)這種遠(yuǎn)程監(jiān)控的第三方應(yīng)用最常見的有兩種:瀏覽器HTTP網(wǎng)頁、UDP上位機。

7d22b602-6fd6-11ec-86cf-dac502259ad0.png

兩者各有優(yōu)勢,對比鮮明,其中:

  • UDP上位機:傳輸效率高,上位機編寫方便。

  • HTTP網(wǎng)頁方式:客戶端無需安裝上位機,只需要一個瀏覽器應(yīng)用即可;客戶端訪問服務(wù)器支持跨平臺支持,無論是電腦、平板、手機,還是Linux系統(tǒng)、Windows系統(tǒng)及安卓系統(tǒng)都可以,只要有瀏覽器應(yīng)用都可訪問,而UDP上位機則受限于目標(biāo)平臺,不易移植。

這兩種應(yīng)用各有優(yōu)缺點,對于嵌入式開發(fā)者來說,兩者都必須掌握。

一、HTTP網(wǎng)頁服務(wù)器

先說下HTTP網(wǎng)頁服務(wù)器獲取MJPG碼流的代碼,首先是OKMX8MP-C在開發(fā)板端建立TCP服務(wù)器:

int TCP_Server_Found(socklen_t* socket_found , char* ip , int port){    struct sockaddr_in servaddr;    socklen_t addrsize = sizeof(struct sockaddr);
    bzero(&servaddr , sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_addr.s_addr = inet_addr(ip);    servaddr.sin_port = htons(port);
    int ret;    IF( (*socket_found = socket(AF_INET , SOCK_STREAM , 0)) == -1)        {            printf("Create socket error: %s (errno :%d)\n",strerror(errno),errno);            return -1;        }
    int on = 1;    if(setsockopt(*socket_found , SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)    {        printf("setsockopt error\n");    }
    ret = bind(*socket_found , (struct sockaddr *)&servaddr , addrsize);    if(ret == -1)    {            printf("Tcp bind faiLED!\n");            return -1;    }
    if(listen(*socket_found , 5) == -1)    {            printf("Listen failed!\n");            return -1;    }    return 0;}
左右滑動查看完整代碼

其中setsockopt()函數(shù)是可選的,一般只用于規(guī)避socket()函數(shù)的建立錯誤。

建立了TCP服務(wù)器后,返回的socklen_t型實參在后面的HTTP網(wǎng)頁服務(wù)器中需要用到。

HTTP網(wǎng)頁服務(wù)器所屬的TCP操作是需要另起輪詢線程來讓客戶端進行accept()握手操作的,accept()之前的listen()倒是只需要執(zhí)行一次即可,accept()握手操作和recv()接收操作需要創(chuàng)建一個死循環(huán)線程:

pthread_create(&tid_tcp_web_recv , NULL , Thread_TCP_Web_Recv , NULL);
void * Thread_TCP_Web_Recv(void *arg){。。。while(1){            fd_socket_conn = accept(socket_web_server , (struct sockaddr *)&sockaddr_in_conn , &addrsize);           printf("fd_socket_conn = accept()\n");    。。。    recv(fd_socket_conn , recvbuf , 1000 , 0);}。。。}
左右滑動查看完整代碼

MJPG幀可以使用Grab操作獲取,獲取到的MJPG幀需要在TCP線程中讀,在Grab操作線程中寫,這種被多個線程訪問的資源需要加鎖防止讀寫沖突,即資源被Grab操作寫入時,需要上鎖,不允許其它線程訪問,操作完成時需要解鎖,允許其它線程訪問:

    pthread_mutex_lock(&pmt);
    pic_tmpbuffer = pic.tmpbuffer;    pic.tmpbytesused = buff.bytesused;    pic_tmpbytesused = pic.tmpbytesused;
    pthread_cond_broadcast(&pct);    pthread_mutex_unlock(&pmt);

左右滑動查看完整代碼

線程互斥鎖使用之前需要初始化:

pthread_mutex_t pmt;pthread_cond_t pct;
int main(int argc, char* argv[]){...TCP_Server_Found(&socket_web_server , (char*)argv[2] , PORT_TCP);pthread_mutex_init(&pmt , NULL);
    pthread_create(&tid_tcp_web_recv , NULL , Thread_TCP_Web_Recv , NULL);
    pthread_create(&tid_tcp_web_send , NULL , Thread_TCP_Web_Send , NULL);...    while(1)    {        V4l2_Grab_Mjpeg(false , MJPEG_FILE_NAME);...    }...}
左右滑動查看完整代碼

然后是發(fā)送的細(xì)節(jié),發(fā)送圖片文件之前,需要先發(fā)送HTTP標(biāo)準(zhǔn)頭,這個相當(dāng)于給發(fā)送圖片或者其它類型的流數(shù)據(jù)鋪路:

#define STD_HEADER "Connection: close\r\n" \    "Server: MJPG-Streamer/0.2\r\n" \    "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n" \    "Pragma: no-cache\r\n" \    "Expires: Mon, 3 Jan 2000 1256 GMT\r\n"
#define BOUNDARY "boundarydonotcross"
    printf("preparing header\n");    sprintf(buffer, "HTTP/1.0 200 OK\r\n" \            "Access-Control-Allow-Origin: *\r\n" \            STD_HEADER \            "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" \            "\r\n" \            "--" BOUNDARY "\r\n");
    if(write(fd, buffer, strlen(buffer)) < 0)    {        free(frame);        return;    }
左右滑動查看完整代碼

發(fā)送完HTTP標(biāo)準(zhǔn)頭之后,就需要發(fā)送內(nèi)容頭(Content-Type),這處的Content-Type為image/jpeg,同樣,HTTP標(biāo)準(zhǔn)協(xié)議里面image支持的類型遠(yuǎn)不止jpeg一種,發(fā)送完內(nèi)容頭之后就是正文和boundary結(jié)尾,這樣幀完整的HTTP頭發(fā)送到指定的TCP GET地址,就會在瀏覽器中顯示剛剛發(fā)送的圖片:

       sprintf(buffer, "Content-Type: image/jpeg\r\n" \                "Content-Length: %d\r\n" \                "X-Timestamp: %d.%06d\r\n" \                "\r\n", frame_size, (int)timestamp.tv_sec, (int)timestamp.tv_usec);
        printf("sending intemdiate header\n");        if(write(fd, buffer, strlen(buffer)) < 0)            break;
        printf("sending frame\n");        if(write(fd, frame, frame_size) < 0)            break;
        printf("sending boundary\n");        sprintf(buffer, "\r\n--" BOUNDARY "\r\n");        if(write(fd, buffer, strlen(buffer)) < 0)            break;
左右滑動查看完整代碼

另外需要說明的是,TCP服務(wù)器線程在發(fā)送MJPEG流的時候是死循環(huán)發(fā)送的,因此TCP客戶端在發(fā)送完GET指令之后,就會收到TCP服務(wù)器循環(huán)發(fā)送的圖像緩存,TCP客戶端會陷入忙等待狀態(tài)無法再對外發(fā)送任何GET或者POST指令,從客戶端使用者角度來看的效果就是網(wǎng)頁一直在等待。

7d4341f6-6fd6-11ec-86cf-dac502259ad0.jpg

7d72d344-6fd6-11ec-86cf-dac502259ad0.png

二、UDP上位機

UDP發(fā)送操作,同樣需要先建立UDP Socket:

int UDP_Send_Found(socklen_t* socket_found , struct sockaddr_in *addr , char* ip , int port){    *socket_found = socket(AF_INET, SOCK_DGRAM, 0);
    if(*socket_found == (~0))    {        printf("Create udp send socket failed!\n");        return -1;    }
    addr->sin_family = AF_INET;    addr->sin_addr.s_addr = inet_addr(ip);    addr->sin_port = htons(port);    memset(addr->sin_zero, 0, 8);    return 0;}
左右滑動查看完整代碼

而UDP文件發(fā)送則要比HTTP發(fā)送簡單得多,只需要將文件切片,每一片為固定長度的UDP幀長度,逐幀發(fā)送即可:

while(fend > 0){memset(picture.data , 0 , sizeof(picture.data));fread(picture.data , UDP_FRAME_LEN , 1, fp);if(fend >= UDP_FRAME_LEN){picture.length = UDP_FRAME_LEN;picture.fin = 0;}else{picture.length = fend;picture.fin = 1;}
//printf("sendbytes = %d \n",sendbytes);
sendbytes = sendto(socket_send, (char *)&picture, sizeof(struct Package), 0, (struct sockaddr*)&addr,addr_len);
if(sendbytes == -1){printf("Send Picture Failed!d\n");return -1;}else{fend -= UDP_FRAME_LEN;}}
左右滑動查看完整代碼

7dd5dec6-6fd6-11ec-86cf-dac502259ad0.jpg

作者簡介

donatello1996,某大型企業(yè)資深嵌入式工程師,電子發(fā)燒友論壇技術(shù)大牛,同時也是飛凌嵌入式多年鐵粉,曾基于飛凌多款板卡產(chǎn)出過優(yōu)質(zhì)測評文章或使用心得。本期三篇文章為donatello1996在使用OKMX8MP-C開發(fā)板過程中精心產(chǎn)出的干貨,在此對donatello1996表示感謝。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    14

    文章

    10251

    瀏覽量

    91480
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    電子發(fā)燒友榮獲電子工業(yè)出版社博文視點 “2025 年度卓越合作伙伴”

    推廣服務(wù),為推動電子技術(shù)知識傳播所做出的突出貢獻。 電子發(fā)燒友作為國內(nèi)電子技術(shù)領(lǐng)域的專業(yè)媒體平臺,自成立以來,始終致力于為廣大電子技術(shù)愛好者、工程師等提供最新、最專業(yè)的電子科技資訊和深度技術(shù)內(nèi)容
    發(fā)表于 02-06 11:58

    ESP32開發(fā)板創(chuàng)建同步WebServer網(wǎng)頁服務(wù)器

    ESP32 內(nèi)置了 Wi-Fi 功能,能夠作為網(wǎng)頁服務(wù)器(Web Server)向網(wǎng)絡(luò)中的其他設(shè)備提供服務(wù)。通過在 ESP32 上運行網(wǎng)頁服務(wù)器
    的頭像 發(fā)表于 01-30 11:36 ?214次閱讀
    ESP32開發(fā)板創(chuàng)建同步WebServer<b class='flag-5'>網(wǎng)頁</b><b class='flag-5'>服務(wù)器</b>

    電子發(fā)燒友積分如何兌換獎勵?

    電子發(fā)燒友積分如何兌換獎勵?
    發(fā)表于 11-19 09:34

    [投票評選]2025電子發(fā)燒友開發(fā)板測評大賽--最受歡迎開發(fā)板

    2025電子發(fā)燒友開發(fā)板測評大賽--最受歡迎開發(fā)板 大賽詳情: 電子發(fā)燒友攜手 16 家生態(tài)廠商發(fā)起開發(fā)板測評大賽,設(shè) OpenHarmony、RISC - V、Rockchip 三大賽道,共計
    發(fā)表于 10-13 16:25

    【上海晶珩睿莓1開發(fā)板試用體驗】2、視頻監(jiān)控監(jiān)控系統(tǒng)

    感謝電子發(fā)燒友論壇 1、系統(tǒng)說明 硬件準(zhǔn)備:睿莓板卡、網(wǎng)線、路由、攝像頭、用于遠(yuǎn)程看監(jiān)控的手機 系統(tǒng)功能:睿莓板卡驅(qū)動攝像頭獲取監(jiān)控流媒體,手機遠(yuǎn)程查看監(jiān)控視頻 2、硬件連接 如下圖,攝像頭通過
    發(fā)表于 09-14 19:16

    電子發(fā)燒友工程師看!電子領(lǐng)域評職稱,技術(shù)之路更扎實

    論壇分享,沒評職稱前只能做基礎(chǔ)電路調(diào)試;評上 “中級電子工程師” 后,被納入公司傳感研發(fā)組,主導(dǎo)的低功耗電路設(shè)計方案,還被收錄到電子發(fā)燒友 “優(yōu)質(zhì)參考設(shè)計庫”,薪資漲幅達 35%,同時獲得了 TI
    發(fā)表于 08-20 13:53

    ESP32-運行網(wǎng)頁服務(wù)器(Web Server)-實用篇

    在前一篇文章《ESP32-運行網(wǎng)頁服務(wù)器(WebServer)-入門篇》,我們介紹了ESP32運行網(wǎng)頁服務(wù)器(WebServer)的原理,然后我們基于ESP32實現(xiàn)了一個demo代碼;
    的頭像 發(fā)表于 07-28 18:05 ?3647次閱讀
    ESP32-運行<b class='flag-5'>網(wǎng)頁</b><b class='flag-5'>服務(wù)器</b>(Web Server)-實用篇

    教你如何手搓一個樹莓派網(wǎng)絡(luò)服務(wù)器

    使用樹莓派的定義和好處網(wǎng)絡(luò)服務(wù)器是指利用HTTP及其他協(xié)議進行數(shù)據(jù)傳輸,處理通過萬維網(wǎng)提交的客戶端請求的軟硬件組合。網(wǎng)絡(luò)服務(wù)器的主要功能是存儲、處理并向客戶端(通常是
    的頭像 發(fā)表于 07-12 08:23 ?634次閱讀
    教你如何手搓一個樹莓派網(wǎng)絡(luò)<b class='flag-5'>服務(wù)器</b>!

    如何在米爾TI AM62開發(fā)板上部署流媒體服務(wù)實現(xiàn)監(jiān)控功能

    這塊開發(fā)板上部署流媒體服務(wù),通過USB攝像頭實現(xiàn)監(jiān)控功能。 一、軟件準(zhǔn)備 要在Linux上面部署流媒體服務(wù)mjpg-streamer是最合適的。 首先,在應(yīng)用開發(fā)環(huán)境中,進行 mjpg
    發(fā)表于 07-03 18:32

    新進發(fā)燒友

    今天注冊成為了電子發(fā)燒友,多學(xué)習(xí),多交流,多進步
    發(fā)表于 06-10 10:59

    電子發(fā)燒友積分能換什么?

    電子發(fā)燒友積分能換什么?
    發(fā)表于 06-10 05:55

    i.MX8MP使用最新的BSP (6.6.52-2.2.0) 映像安裝TA失敗,為什么?

    我正在為 i.MX8MP 測試最新的 BSP image(),發(fā)現(xiàn)在嘗試安裝 TA 時會出現(xiàn)以下錯誤 root@imx8mpevk:~# xtest --install-ta /usr/lib
    發(fā)表于 03-28 07:40

    將Deepseek移植到i.MX 8MP|93 EVK的步驟

    測試了不同模型對不同電路板的影響。需要注意的是,限制模型在電路板上運行的最大障礙是內(nèi)存。包括 CPU 和內(nèi)存使用情況在內(nèi)的測試結(jié)果如下: a. i.MX8mp 深度搜索-r1-蒸餾
    發(fā)表于 03-26 06:08

    如何在IMX8MP上配置單通道內(nèi)存?

    我正在使用 i.MX 8M Plus 評估套件。測試 2 通道 LPDDR4 設(shè)備很好。但是,配置 1 個通道 LPDDR4 很困難,因為根據(jù)原理圖,i.MX8MP 側(cè)的通道 A 連接到 LPDDR4 側(cè)的通道 B。如何在此交換
    發(fā)表于 03-17 07:00

    ESP32運行網(wǎng)頁服務(wù)器 (Web-Server)-入門篇

    什么是ESP32WebServer?ESP32WebServer是在ESP32微控制上運行的一個嵌入式網(wǎng)頁服務(wù)器。它能夠處理HTTP請求并作出響應(yīng),使用戶可以通過網(wǎng)絡(luò)瀏覽
    的頭像 發(fā)表于 03-09 14:24 ?7555次閱讀
    ESP32運行<b class='flag-5'>網(wǎng)頁</b><b class='flag-5'>服務(wù)器</b> (Web-Server)-入門篇