【平头哥RVB2601创意应用开发】实践9-板载屏幕播放BadApple视频
[复制链接]
上篇文章,使用TCP的方式,使RVB2601与ESP8266板子在同一局域网下无线通信,实现RVB2601对ESP8266板子LED灯进行亮灭控制。
本篇,继续使用TCP连网功能,仍使RVB2601作为客户端,笔记本电脑作为服务器器,实现RVB2601播放电脑上的视频。
1 RVB2601程序
1.1 连网后连接服务器
程序和上一篇的类似,都要在RVB2601连上网后,再连接对应的服务器:
void connect_tcp_server(char *server_ip, uint16_t port)
{
char ssid[32];
int bssid[6];
int channel;
int rssi;
w800_ap_info( ssid, bssid , &channel, &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);
}
1.2 数据接收回调函数
//自己的回调函数
void w800_data_receive_callback(int linkid, void *data, size_t len, char remote_ip[16], 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(&u8g2);
u8g2_SetFont(&u8g2, u8g2_font_wqy12_t_chinese1);
u8g2_DrawXBM(&u8g2, 0, 0, 128, 64, buf);
u8g2_SendBuffer(&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, &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(&w800_data_receive_callback); //接收回调函数的注册
netmgr_start(app_netmgr_hdl);
}
}
2 服务器端Python程序
2.1 主程序
程序的基本思想是:
-
利用OpenCV读取视频文件
-
对视频帧的图像,进行尺寸修改
-
对图像进行二值化处理
-
将二值图像转换为数组
-
将数组通过socket发送出去
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) & 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)
2.2 图像转为数组
利用OpenCV,将图像转为黑白图像:
def binary_image(image):#将图像处理为二值化的程序
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) #把输入图像灰度化
h, w =gray.shape[:2]
m = np.reshape(gray, [1,w*h])
mean = m.sum()/(w*h)
ret, binary = cv2.threshold(gray, mean, 255, cv2.THRESH_OTSU)
return binary
然后再转为数组:
def img_to_matrix(frame, endian, color_reverse):
width = frame.shape[1] #128
height = frame.shape[0] #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 > width:
re = width
for k in range(rs, re):
if frame[i, k] != 0:
if not byte_reverse:
v |= (0x01 << (k%8))
else:
v |= (0x01 << (7-(k%8)))
if color_reverse:
v ^= 0xff
matrix.append(v)
return matrix
2.3 开启socket服务
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[0])
print('IP:'+client_IP)
client_port = str(client_address[1])
print('Port:' + client_port)
return client
3 测试效果
4 总结
本篇介绍RVB2601在板载屏幕上播放视频,包括RVB2601端的图像接收与显示程序,与电脑端的Python读取视频并进行编码与数据发送程序。
|