chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

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

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

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

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

內(nèi)個(gè)老胡 ? 2022-01-10 16:30 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

作者|donatello1996

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

題圖|飛凌嵌入式

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

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

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

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

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

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

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

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

先說(shuō)下HTTP網(wǎng)頁(yè)服務(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;}
左右滑動(dòng)查看完整代碼

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

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

HTTP網(wǎng)頁(yè)服務(wù)器所屬的TCP操作是需要另起輪詢線程來(lái)讓客戶端進(jìn)行accept()握手操作的,accept()之前的listen()倒是只需要執(zhí)行一次即可,accept()握手操作和recv()接收操作需要?jiǎng)?chuàng)建一個(gè)死循環(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);}。。。}
左右滑動(dòng)查看完整代碼

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

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

左右滑動(dòng)查看完整代碼

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

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);...    }...}
左右滑動(dòng)查看完整代碼

然后是發(fā)送的細(xì)節(jié),發(fā)送圖片文件之前,需要先發(fā)送HTTP標(biāo)準(zhǔn)頭,這個(gè)相當(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;    }
左右滑動(dòng)查看完整代碼

發(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地址,就會(huì)在瀏覽器中顯示剛剛發(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;
左右滑動(dòng)查看完整代碼

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

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

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

二、UDP上位機(jī)

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;}
左右滑動(dòng)查看完整代碼

而UDP文件發(fā)送則要比HTTP發(fā)送簡(jiǎn)單得多,只需要將文件切片,每一片為固定長(zhǎng)度的UDP幀長(zhǎng)度,逐幀發(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;}}
左右滑動(dòng)查看完整代碼

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

作者簡(jiǎn)介

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

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

    關(guān)注

    14

    文章

    10355

    瀏覽量

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

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

    在基于 i.MX8MP 的定制板上使用 MAX98090 音頻編解碼,面臨耳機(jī)插孔檢測(cè)問題求解

    我們?cè)诨?i.MX8MP 的定制板上使用 MAX98090 音頻編解碼。我們面臨的問題是耳機(jī)插孔檢測(cè). 在MAX98090編解碼驅(qū)動(dòng)程序中,插孔檢測(cè)似乎可以正常工作——插入或拔下插孔時(shí),我可以
    發(fā)表于 04-23 09:36

    將 Linux BSP 用于 i.MX8M Plus 或 i.MX8 Quad Max 平臺(tái),遇到的幾個(gè)問題求解

    我計(jì)劃將 Linux BSP 用于 i.MX8M Plus 或 i.MX8 Quad Max 平臺(tái)。我有幾個(gè)問題: - 對(duì)于 Linux BSP,它是否支持 1 Gbps 以太網(wǎng)并允許將視頻流傳輸
    發(fā)表于 04-20 10:25

    國(guó)產(chǎn)高端電感實(shí)測(cè)!RH105技術(shù)拆解+選型實(shí)操,發(fā)燒友必看

    RH105(CDRH105系列),憑借自主磁材配方和精密結(jié)構(gòu)設(shè)計(jì),實(shí)現(xiàn)了對(duì)標(biāo)國(guó)際一線的性能表現(xiàn),且性價(jià)比更具優(yōu)勢(shì)。本文聚焦核心技術(shù)拆解、實(shí)測(cè)參數(shù)、應(yīng)用場(chǎng)景及實(shí)操選型指南,全程干貨無(wú)冗余,助力發(fā)燒友快速上手、精準(zhǔn)選型。
    的頭像 發(fā)表于 04-17 15:36 ?148次閱讀
    國(guó)產(chǎn)高端電感<b class='flag-5'>實(shí)測(cè)</b>!RH105技術(shù)拆解+選型實(shí)操,<b class='flag-5'>發(fā)燒友</b>必看

    技術(shù)分享 | I.MX8MP如何適配CUPS打印機(jī)

    Linux中對(duì)打印機(jī)的支持比較有限,很多打印機(jī)廠家也很少有專門針對(duì)Linux適配的相關(guān)驅(qū)動(dòng),今天以I.MX8MP平臺(tái)為例,介紹如何適配cups打印協(xié)議,該協(xié)議支持常見打印機(jī)通訊協(xié)議,無(wú)需復(fù)雜的廠商
    的頭像 發(fā)表于 04-16 17:24 ?925次閱讀
    技術(shù)分享 | <b class='flag-5'>I.MX8MP</b>如何適配CUPS打印機(jī)

    解碼初始化失敗,在 i.MX8MP (imx-vpu-hantro) 上使用 hevcdec 失敗怎么解決?

    解碼時(shí),我遇到解碼初始化失敗。 以下是詳細(xì)信息: - Platform: i.MX8MP - 內(nèi)核:6.6.52 - 封裝:imx-vpu-hantro - 測(cè)試臺(tái):hevcdec - 輸入
    發(fā)表于 04-08 07:13

    使用 i.MX8MP GStreamer Pipeline 進(jìn)行 12MP 捕獲中的圖像偽影,偽影在最終圖像中顯示為損壞,怎么解決?

    我正在為 i.MX8MP 開發(fā)一個(gè) Qt 應(yīng)用程序,該應(yīng)用程序針對(duì) 12MP 圖像捕獲設(shè)備,并在捕獲的 PNG 圖像中遇到圖像偽影。 硬件/軟件環(huán)境: SoC: NXP i.MX8MP
    發(fā)表于 03-27 07:32

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

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

    電子發(fā)燒友積分如何兌換獎(jiǎng)勵(lì)?

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

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

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

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

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

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

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

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

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

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

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

    新進(jìn)發(fā)燒友

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

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

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