转成python 使用opencv 与gi 重写#include "mp4_lib.h"
#include <QtWidgets/QWidget>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define GST_WAYLAND_DISPLAY_HANDLE_CONTEXT_TYPE "GstWaylandDisplayHandleContextType"
struct wl_surface *surface = NULL;
struct wl_display *display = NULL;
static int video_x = 100;
static int video_y = 100;
static int video_width = 300;
static int video_height = 300;
static const char *target_ip = "192.168.1.1";
static int target_port = 554;
static bool wait_flag = 0;
Mp4_lib::Mp4_lib()
{
}
// 检查IP是否可达
bool check_ip_reachability(const char *ip, int port) {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("Socket creation error");
return false;
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip, &server_addr.sin_addr) <= 0) {
perror("Invalid address/ Address not supported");
close(sockfd);
return false;
}
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
// 连接失败,IP可能不可达
close(sockfd);
return false;
}
// 连接成功,IP可达
close(sockfd);
return true;
}
void main_loop(void* widgetPtr, int x,int y,int width,int height){
if(x>0){
video_x = x;
}
if(y>0){
video_y = y;
}
if(width>0){
video_width = width;
}
if(height>0){
video_height = height;
}
QWidget* window = static_cast<QWidget *>(widgetPtr);
gst_init(NULL, NULL);
// 测试视频:
if(!check_ip_reachability(target_ip,target_port)){
printf("RTSP URL FAIL\r\n");
wait_flag = 1;
return;
}else{
printf("RTSP URL SUCCESS\r\n");
}
GstElement *pipeline = gst_parse_launch("rtspsrc location=rtsp://192.168.3.168:554/cvbs ! decodebin ! videoconvert ! waylandsink sync=false ",NULL);
//GstElement *pipeline = gst_parse_launch("rtspsrc location=rtsp://192.168.3.168:554/cvbs ! rtpmp2tdepay ! aiurdemux ! name=d d. ! queue ! h264parse ! vpudec ! imxcompositor_g2d ! waylandsink sync=false d. ! queue ! aacparse ! beepdec ",NULL);
if(!pipeline){
printf("error!!1\r\n");
return;
}
//window->show();
GstBus *bus = gst_element_get_bus(pipeline);
gst_bus_add_watch(bus, bus_watch_function, pipeline);
gst_bus_set_sync_handler(bus, bus_sync_handler, window, nullptr);
// 释放总线引用
gst_object_unref(bus);
//printf("123\r\n");
gst_element_set_state(pipeline, GST_STATE_PLAYING);
}
gboolean bus_watch_function(GstBus *bus, GstMessage *msg, gpointer data) {
GstElement *pipeline = (GstElement *)data;
if(!check_ip_reachability(target_ip,target_port)){
printf("playing RTSP URL FAIL\r\n");
gst_element_set_state(pipeline, GST_STATE_NULL);
//gst_object_unref(pipeline);
return TRUE;
}
//printf("pipeline2 %p\r\n",pipeline);
switch (GST_MESSAGE_TYPE(msg)) {
case GST_MESSAGE_EOS:
// 播放结束
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
break;
case GST_MESSAGE_ERROR: {
// 发生错误
GError *err;
gchar *debug_info;
gst_message_parse_error(msg, &err, &debug_info);
g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error(&err);
g_free(debug_info);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
break;
}
default:
break;
}
return TRUE;
}
gboolean gst_is_wayland_display_handle_need_context_message(GstMessage *msg) {
const gchar *type = NULL;
g_return_val_if_fail(GST_IS_MESSAGE(msg), FALSE);
if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_NEED_CONTEXT && gst_message_parse_context_type(msg, &type)) {
return !g_strcmp0(type, GST_WAYLAND_DISPLAY_HANDLE_CONTEXT_TYPE);
}
return FALSE;
}
GstContext *gst_wayland_display_handle_context_new(struct wl_display *display) {
GstContext *context = gst_context_new(GST_WAYLAND_DISPLAY_HANDLE_CONTEXT_TYPE, TRUE);
gst_structure_set(gst_context_writable_structure(context), "handle", G_TYPE_POINTER, display, NULL);
return context;
}
GstBusSyncReply bus_sync_handler(GstBus *bus, GstMessage *msg, gpointer data) {
QWidget *window = (QWidget *)data;
if (gst_is_wayland_display_handle_need_context_message(msg)) {
g_print("gst_is_wayland_display_handle_need_context_message\n");
GstContext *context;
// get the wlayland display handle from Qt
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
display = static_cast<struct wl_display *>(native->nativeResourceForWindow("display", NULL));
g_print("display: %p\n", display);
context = gst_wayland_display_handle_context_new(display);
gst_element_set_context(GST_ELEMENT(GST_MESSAGE_SRC(msg)), context);
goto drop;
} else if (gst_is_video_overlay_prepare_window_handle_message(msg)) {
wait_flag = 1;
g_print("gst_is_video_overlay_prepare_window_handle_message\n");
// we can only get the handle for the top window
// the handle for videoWindow will be null !!
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
QWindow *windowHandle = window->windowHandle();
g_print("top window handle: %p\n", windowHandle);
surface = static_cast<struct wl_surface *>(native->nativeResourceForWindow("surface", windowHandle));
g_print("surface: %p\n", surface);
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(msg)), (guintptr)surface);
//QRect re = window->frameGeometry();
//g_print("window rect x: %d, y:%d, w:%d, h:%d\n", re.x(), re.y(), re.width(), re.height());
//QRect vre = window->geometry();
g_print("video window rect x: %d, y:%d, w: %d, h: %d \n", video_x, video_y, video_width, video_height);
gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(msg)),
video_x, video_y, video_width, video_height);
goto drop;
}
return GST_BUS_PASS;
drop:
gst_message_unref(msg);
return GST_BUS_DROP;
}
void helloworld(){
printf("helloworld \r\n");
}
bool wait_video_start(){
return wait_flag;
}
最新发布