[Ubuntu]Scrcpy+Zeromq实现手机屏幕yuv数据传输,并通过OpenCV实现连续播放——(二)(思路+代码解析)
????????Scrcpy在上一篇博客中有所介紹,并且使用Scrcpy實現了手機屏幕yuv數據的提取([Ubuntu]Scrcpy獲取手機屏幕yuv數據_又是誰在卷的博客-CSDN博客)。本文將介紹一個當下較為好用的消息中間件—Zeromq。通過Zeromq中間件對數據進行傳輸,我們最終通過opencv進行內存的數據讀取,并實現連續播放的效果。
??????? 往下閱讀之前,記得看我的往期博客了解如何提取yuv數據呀([Ubuntu]Scrcpy獲取手機屏幕yuv數據_又是誰在卷的博客-CSDN博客),這里就不再過多介紹yuv提取的知識了。接下里就開始實現Scrcpy+Zeromq實現手機屏幕yuv數據傳輸,并通過OpenCV實現連續播放。
目錄
1. Zeromq簡單介紹,以及如何與Scrcpy項目源碼進行對接(具體思路+代碼解析)
1.1Zeromq簡單介紹:Zeromq官網(ZeroMQ)
1.2.接下來讓我們思考和Scrcpy對接時需要思考的的問題和流程框架。
?1.3.代碼部分,針對以上結論進行實踐
?1.3.1將yuv數據通過結構體進行封裝
1.3.2將對應數據放入結構體
1.3.3在Scrcpy中創建Zeromq的PUB(發布者)
1. Zeromq簡單介紹,以及如何與Scrcpy項目源碼進行對接(具體思路+代碼解析)
1.1Zeromq簡單介紹:Zeromq官網(ZeroMQ)
??????? 簡單來說,ZeroMQ以嵌入式網絡編程庫的形式實現了一個并行開發框架。能夠提供進程內(inproc)、進程間(IPC)、網絡(TCP)和廣播方式的消息信道,并支持扇出(fan-out)、發布-訂閱(pub-sub)、任務分發(task distribution)、請求/響應(request-reply)等通信模式。與傳統的消息中間件,Zeromq大大簡化了消息傳輸的中間愛你過程,具有簡介易操作的特點。(這里簡單介紹,具體細節請參考官方文檔。)
1.2.接下來讓我們思考和Scrcpy對接時需要思考的的問題和流程框架。
??????? 如果看過我的上一篇博客,我們知道yuv數據提取的過程是有順序的。那我們就迎來了第一個需要思考的問題,
???????? 1.我們如何將正確的順序通過怎樣的載體進行運輸呢?
????????這之中可能會有很多有趣的想法(比如yuv分開發送、yuv作為編碼為字符串一起直接傳輸等等)。但是較好的方式是創建一個結構體作為yuv數據的載體,將y、u、v分別作為結構體單獨的屬性。通過結構體作為載體還有一個好處就是,我們每臺設備的分辨率是不同的,分辨率在opencv的腳本中也需要用到(用于還原yuv數據),所以可以放在結構體里一起發送。
??????? 載體選擇完之后,yuv數據包裝完畢之后,在發送之前。我們遇到了第二個問題。
??????? 2.通過了解我們知道Zeromq有四個模型,我們需要選取最合適的模型。
??????? Zeromq中最常見的三種種基礎模型
??????????????? 1. REQ/REP 請求響應模型
??????????????? 2. PUB/SUB發布訂閱模型
??????????????? 3. Pipeline pattern 管道模式
??????? 我們要根據需求對模型進行選擇。手機屏幕yuv數據的傳輸是從Scrcpy運行開始之后就源源不斷的。也就是說,不管接收者是否受到數據,我們的發送端都不會停止發送。所以顯而易見,在這里 2. 發布訂閱者更合適。發布者(PUB)設置在Scrcpy的項目端,而訂閱者(SUB)則設置在與opencv對接的python腳本中。
??????? 選定模型之后,通過Zeromq的傳輸,在另一端和python腳本對接之后通過opencv呈現即可(后面會有代碼解析)
?1.3.代碼部分,針對以上結論進行實踐
?1.3.1將yuv數據通過結構體進行封裝
??????? 因為yuv數據在scrcpy-master/app/src/decode.c文件中,所以我們將結構體創建在它的頭文件中(decode.h)。代碼如下圖所示:
# 在decode.h添加如下代碼 # 這里的576*1152是我手機分辨率除以1.875,這里算是壓縮的操作 #define yuv_buf_size 576*1152 typedef struct{int cxt_width;int cxt_height;uint8_t data_y[yuv_buf_size];uint8_t data_u[yuv_buf_size/4];uint8_t data_v[yuv_buf_size/4]; }cxt_frame;1.3.2將對應數據放入結構體
??????? 以下代碼和提取yuv數據時的操作如出一轍,也是在存有AVFrame的函數中(再次友情提醒:以下代碼如果有疑惑,請參考我的上一篇博客)。我們通過memcpy函數將yuv數據分別拷貝到結構體對應的屬性中。
# 創建結構體 cxt_frame yuv_frame; # 定義長寬 int yuv_width = decoder->codec_ctx->width; int yuv_height = decoder->codec_ctx->height; yuv_frame.cxt_width = yuv_width; yuv_frame.cxt_height = yuv_height;# buf_size_aline用于對齊,以下存儲yuv的操作和上一篇博客中提取yuv的操作如出一轍 int buf_size_aline = 0; for(int i = 0;i<yuv_height;i++){memcpy(yuv_frame.data_y + buf_size_aline,frame->data[0]+frame->linesize[0]*i,yuv_width);buf_size_aline += yuv_width;}buf_size_aline = 0;for(int i = 0;i<yuv_height/2;i++){memcpy(yuv_frame.data_u + buf_size_aline,frame->data[1]+frame->linesize[1]*i,yuv_width/2);buf_size_aline += yuv_width/2;}buf_size_aline = 0;for(int i = 0;i<yuv_height/2;i++){memcpy(yuv_frame.data_v + buf_size_aline,frame->data[2]+frame->linesize[2]*i,yuv_width/2);buf_size_aline += yuv_width/2;}# 這里是通過Zeromq進行傳輸結構體數據的操作,這里暫時先不解釋,到后面講解zeromq時會回到此處進行解析 zmq_send(responder,&yuv_frame,sizeof(yuv_frame),ZMQ_DONTWAIT);1.3.3在Scrcpy中創建Zeromq的PUB(發布者)
??????? 我們在這之前需要清楚,Scrcpy是多線程的。發送消息的指令可以寫在和yuv提取相同的位置。但是創建Zeromq發布者對象的時候不行,因為我們只要創建一次即可。寫在函數中會反復創建(無法多次創建,會沖突)。所以我們必須找到這個線程進行初始化操作的地方創建Zeromq對象。在ubuntu中,我們可以在終端輸入以下命令通過查找調用函數的位置,一步步向上層尋找。直到找到此線程的初始化位置,查找命令如下:
# 在此目錄下的.c文件中查找名為“push_frame”的位置 $ find. -name "*.c" | xargs grep -n "push_frame"?接下來在Zeromq中使用的函數可以在這篇博客里找到解析(ZeroMQ教程中文版_神馬_逗_浮云的博客-CSDN博客_zeromq中文)
經過查找,我們發現此線程的源頭在名為stream.c的文件中,我們將在開始無條件for循環之前創建zeromq對象。代碼和輸入位置如下:
#創建新的zeromq環境 void *context = zmq_ctx_new ();# 這里有一個responder對象,我是將它初始化在stream.h的文件中了 # 選擇ZMO_PUB發布訂閱模型 responder = zmq_socket (context, ZMQ_PUB);# 端口號,主機的隨便一個可用的端口都行 int rc = zmq_bind (responder, "tcp://127.0.0.1:5565");# 如果連接端口失敗,則rc返回值為0 assert (rc == 0);#最后別忘了在無限for循環之后關閉端口 zmq_close(responder);?到這里再回去看在存儲yuv數據那里的最后一行有發送yuv數據的代碼就明白了。
至此我們發布者(PUB)端就設置完畢啦。成功完成Scrcpy和Zeromq的對接,剩下的就是創建python腳本(其他語言也行,我以python為例)接收yuv數據再使用opencv進行播放啦。
剩下內容請關注我的下一篇博客
總結
以上是生活随笔為你收集整理的[Ubuntu]Scrcpy+Zeromq实现手机屏幕yuv数据传输,并通过OpenCV实现连续播放——(二)(思路+代码解析)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 最新机器人工程专业毕设选题推荐
- 下一篇: 《The C++ IO Streams
