DDZZ669 发表于 2022-5-30 22:44

【平头哥RVB2601创意应用开发】实践9-板载屏幕播放BadApple视频

<p cid="n0" mdtype="paragraph"><a href="https://bbs.eeworld.com.cn/thread-1204965-1-1.html" target="_blank">上篇文章</a>,使用TCP的方式,使RVB2601与ESP8266板子在同一局域网下无线通信,实现RVB2601对ESP8266板子LED灯进行亮灭控制。</p>

<p cid="n0" mdtype="paragraph">&nbsp;</p>

<p cid="n2" mdtype="paragraph">本篇,继续使用TCP连网功能,仍使RVB2601作为客户端,笔记本电脑作为服务器器,实现RVB2601播放电脑上的视频。</p>

<p cid="n2" mdtype="paragraph"></p>

<h1 cid="n3" mdtype="heading">1 RVB2601程序</h1>

<h2 cid="n4" mdtype="heading">1.1 连网后连接服务器</h2>

<p cid="n5" mdtype="paragraph">程序和上一篇的类似,都要在RVB2601连上网后,再连接对应的服务器:</p>

<pre>
<code class="language-cpp">void connect_tcp_server(char *server_ip, uint16_t port)
{
    char ssid;
    int bssid;
    int channel;
    int rssi;
   
   
    w800_ap_info( ssid, bssid , &amp;channel,  &amp;rssi);
    printf("ssid: %s\r\n", ssid);
    printf("channel: %d\r\n", channel);
    printf("rssi: %d\r\n", rssi);
   
    w800_connect_remote(0, NET_TYPE_TCP_CLIENT, server_ip, port);
}

static void network_event(uint32_t event_id, const void *param, void *context)
{
   switch(event_id) {
   case EVENT_NETMGR_GOT_IP:
      LOGD(TAG, "net got ip");
      connect_tcp_server("192.168.5.100", 8080); //测试视频播放
       break;
   case EVENT_NETMGR_NET_DISCON:
      LOGD(TAG, "net disconnect");
       break;
 }

   /*do exception process */
   app_exception_event(event_id);
}</code></pre>

<pre cid="n6" lang="c" mdtype="fences" spellcheck="false">


&nbsp;</pre>

<h2 cid="n7" mdtype="heading">1.2 数据接收回调函数</h2>

<pre>
<code class="language-cpp">//自己的回调函数
void w800_data_receive_callback(int linkid, void *data, size_t len, char remote_ip, uint16_t remote_ports)
{
    uint8_t *buf;
    buf = (uint8_t *)data;
    if(len == 0)
    {
      return;
    }
    printf("receive data len: %d\r\n",len);

   //将接收到的视频帧数据,借助U8g2库在屏幕上显示出来
    u8g2_ClearBuffer(&amp;u8g2);
    u8g2_SetFont(&amp;u8g2, u8g2_font_wqy12_t_chinese1);
    u8g2_DrawXBM(&amp;u8g2, 0, 0, 128, 64, buf);
    u8g2_SendBuffer(&amp;u8g2);
}

static void network_init()
{
   w800_wifi_param_t w800_param;
   /* init wifi driver and network */
   w800_param.reset_pin      = PA21;
   w800_param.baud           = 1*1000000;
   w800_param.cs_pin         = PA15;
   w800_param.wakeup_pin     = PA25;
   w800_param.int_pin        = PA22;
   w800_param.channel_id     = 0;
   w800_param.buffer_size    = 4*1024;

   wifi_w800_register(NULL, &amp;w800_param);
   app_netmgr_hdl = netmgr_dev_wifi_init();

   if (app_netmgr_hdl) {
       utask_t *task = utask_new("netmgr", 2 * 1024, QUEUE_MSG_COUNT, AOS_DEFAULT_APP_PRI);
       netmgr_service_init(task);
      netmgr_config_wifi(app_netmgr_hdl, "MERCURY_3394", 12, "XXXXXXXXXXX", 11);
       w800_packet_input_cb_register(&amp;w800_data_receive_callback); //接收回调函数的注册
       netmgr_start(app_netmgr_hdl);
 }
}</code></pre>

<h1 cid="n9" mdtype="heading">2 服务器端Python程序</h1>

<h2 cid="n16" mdtype="heading">2.1 主程序</h2>

<p cid="n17" mdtype="paragraph">程序的基本思想是:</p>

<ul cid="n18" data-mark="-" mdtype="list">
        <li cid="n19" mdtype="list_item">
        <p cid="n20" mdtype="paragraph">利用OpenCV读取视频文件</p>
        </li>
        <li cid="n21" mdtype="list_item">
        <p cid="n22" mdtype="paragraph">对视频帧的图像,进行尺寸修改</p>
        </li>
        <li cid="n23" mdtype="list_item">
        <p cid="n24" mdtype="paragraph">对图像进行二值化处理</p>
        </li>
        <li cid="n25" mdtype="list_item">
        <p cid="n26" mdtype="paragraph">将二值图像转换为数组</p>
        </li>
        <li cid="n27" mdtype="list_item">
        <p cid="n28" mdtype="paragraph">将数组通过socket发送出去</p>
        </li>
</ul>

<pre>
<code class="language-python">video_path="badapple_320240_xvid.mp4"
   
def PlayVideo(video_path, client):
   endian          = 'L'
   color_reverse   = 'false'
   
   c = 0#累计帧数
   timeF = 8#隔x帧截一次图
   
   video = cv2.VideoCapture(video_path) #打开视频
   player = MediaPlayer(video_path) #打开音频
   while True:
       grabbed, frame= video.read()
       audio_frame, val = player.get_frame()
       if not grabbed:
           print("End of video")
           break
       if cv2.waitKey(28) &amp; 0xFF == ord("q"):
           break
       cv2.imshow("Video", frame)
       if val != 'eof' and audio_frame is not None:
           img, t = audio_frame

       if (c % timeF == 0):  # 每隔timeF帧进行存储操作
           frame = cv2.resize(frame,(128,64))#调整尺寸
           frame = binary_image(frame)#二值化
           matrix = img_to_matrix(frame, endian, color_reverse)
           data = bytes(matrix)
           client.send(data)

       c = c + 1
       #time.sleep(0.2)
       #cv2.waitKey(1)
           
   video.release()
   cv2.destroyAllWindows()

###############
client = 0
client = socket_start()
PlayVideo(video_path, client)</code></pre>

<h2 cid="n30" mdtype="heading">2.2 图像转为数组</h2>

<p cid="n31" mdtype="paragraph">利用OpenCV,将图像转为黑白图像:</p>

<pre>
<code class="language-python">def binary_image(image):#将图像处理为二值化的程序
   gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)  #把输入图像灰度化
   h, w =gray.shape[:2]
   m = np.reshape(gray, )
   mean = m.sum()/(w*h)
   ret, binary =  cv2.threshold(gray, mean, 255, cv2.THRESH_OTSU)
   return binary</code></pre>

<p cid="n33" mdtype="paragraph">然后再转为数组:</p>

<pre>
<code class="language-python">def img_to_matrix(frame, endian, color_reverse):
   width = frame.shape #128
   height = frame.shape #64

   if endian == 'B':
       byte_reverse = True
   else:
       byte_reverse = False

   if color_reverse == 'true':
       color_reverse = True
   else:
       color_reverse = False

   unalign = 0
   matrix = list()
   
   if (width%8) != 0:
       unalign = 1
   for i in range(0, height): #64
       for j in range(0, (width//8)+unalign): #128/8=16
           v = 0x00
           rs = 8*j      
           re = 8*(j+1)  
           if re &gt; width:
               re = width
           for k in range(rs, re):
               if frame != 0:
                   if not byte_reverse:
                       v |= (0x01 &lt;&lt; (k%8))
                   else:
                       v |= (0x01 &lt;&lt; (7-(k%8)))
           if color_reverse:
               v ^= 0xff
           matrix.append(v)

   return matrix</code></pre>

<h2 cid="n35" mdtype="heading">2.3 开启socket服务</h2>

<pre>
<code class="language-python">def socket_start():
   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   host = socket.gethostbyname(socket.gethostname())
   port = 8080

   host = '192.168.5.100'
   print(host)
   print(port)
   s.bind((host,port))
   s.listen(5)

   print('等待客户端连接中…')

   client,client_address = s.accept()
   print('新连接')
   client_IP = str(client_address)
   print('IP:'+client_IP)
   client_port = str(client_address)
   print('Port:' + client_port)

   return client</code></pre>

<h1 cid="n10" mdtype="heading">3 测试效果</h1>

<p cid="n39" mdtype="paragraph"><iframe __idm_id__="516097" allowfullscreen="true" frameborder="0" height="450" src="//player.bilibili.com/player.html?bvid=1J34y177ci&amp;page=1" style="background:#eee;margin-bottom:10px;" width="700"></iframe><br />
&nbsp;</p>

<h1 cid="n11" mdtype="heading">4 总结</h1>

<p cid="n40" mdtype="paragraph">本篇介绍RVB2601在板载屏幕上播放视频,包括RVB2601端的图像接收与显示程序,与电脑端的Python读取视频并进行编码与数据发送程序。</p>

<p cid="n41" mdtype="paragraph">&nbsp;</p>

<p cid="n13" mdtype="paragraph">&nbsp;</p>

Jacktang 发表于 2022-5-31 07:36

<p>看了多遍</p>

<p>不错</p>

<p> &nbsp;</p>

nmg 发表于 2022-5-31 08:53

<p><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/lol.gif" width="48" />那几条黑线,让我想起了跳皮筋</p>

wangerxian 发表于 2022-5-31 20:15

本帖最后由 wangerxian 于 2022-5-31 20:28 编辑

<p>哈哈,终究逃不过,bad apple</p>

DDZZ669 发表于 2022-5-31 22:35

nmg 发表于 2022-5-31 08:53
那几条黑线,让我想起了跳皮筋

<p>手机录像,就出现了黑线<img height="28" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/upside-down-face_1f643.png" width="28" /></p>

freebsder 发表于 2022-5-31 23:42

Jacktang 发表于 2022-5-31 07:36
看了多遍

不错

&nbsp;

<p>这个背景是有什么说法?</p>

weiwei22844 发表于 2023-8-10 17:10

<p>为什么源码中myTest目录为空,能给提供一下源码吗?</p>

DDZZ669 发表于 2023-8-12 21:58

weiwei22844 发表于 2023-8-10 17:10
为什么源码中myTest目录为空,能给提供一下源码吗?

<p>重新提交代码了</p>

weiwei22844 发表于 2023-8-15 14:37

DDZZ669 发表于 2023-8-12 21:58
重新提交代码了

<p>谢谢,已经跑起来了,最新的toolchain 2.6.1编译有问题,用2.2.4编译才没有问题</p>
页: [1]
查看完整版本: 【平头哥RVB2601创意应用开发】实践9-板载屏幕播放BadApple视频