Chinaunix首页 | 论坛 | 博客
  • 博客访问: 521791
  • 博文数量: 197
  • 博客积分: 2071
  • 博客等级: 上尉
  • 技术积分: 1307
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-02 09:49
个人简介

prothes 专注嵌入式的ARM linux

文章分类

全部博文(197)

文章存档

2014年(3)

2013年(16)

2012年(108)

2011年(70)

分类: LINUX

2011-09-06 13:40:31

本例是用QT编写的视频监控界面。由主窗口的两个按钮可以分别调用观看两个摄像头的视频内容。加主线程共3个线程。两个视频显示窗口用Qtimer 来控制。视频图片显示使用lable控件。此程序主要讲解本地图片多线程传输,暂时不用多次刷新显示连续帧。待USB冲突解决后方可实现。

Client端:

    用QT设计界面。其中包括main.cpp, mainWindow_main.cpp, video_thread1.cpp, video_thread2.cpp, video_client.cpp及其对应的*.h文件。

     1.mainWindow_main.cpp

     此为主窗口的功能实现代码。该主窗口包含两个pushButton, 点击按钮pushBtn_video1则调用video_thread1.cpp, 点击按钮pushBtn_video2则调用video_thread2.cpp.

该mainWindow_main.cpp功能实现很简单,只是实现一个窗口调用。

void mainWindow_main::on_pushBtn_video1_clicked()

{

       MainWindow_thread1 *show_video1 = new MainWindow_thread1();

       show_video1->show();

}

void mainWindow_main::on_pushBtn_video2_clicked()

{

       MainWindow_thread2 *show_video2 = new MainWindow_thread2();

       show_video2->show();

}

    2. video_thread1.cpp和 video_thread2.cpp

    此为点击主界面两个按钮时出现的两个窗口所执行的代码。这两个文件的代码很相似,只用全局变量所标识的线程号thread_Num有所不同。

程序执行伊始,设全局变量temp=0。temp为开启 / 关闭视频的全局标识变量。

update( )。便于随时刷新,它可自动调用paint事件重绘显示屏幕。

   1)编写单击开始按钮的槽on_bottonStart1_clicked( )。

    {temp=0;//如果是stop按钮的话,就设为1

    thread_Num=1;

    thread1.video_start(temp, thread_Num);}

    线程2同理。只需改动thread_Num为2即可。

   2)编写paint事件paintEvent(QPaintEvent *e)

      如果不用QT的事件机制来画图的话,图片是不能被正常显示在lable中的。

       QPainter paint(this);

       QImage image("init_thread1.jpg");//显示传送过来的图片

       paint.drawImage(QRect(0,0,640,480),image);

       QWidget::paintEvent(e);

        3.video_start( int temp, int thread_Num )的实现

        (自己定义一个新类video_client,在video_thread1.cpp和 video_thread2.cpp中分别定义一个对象,然后在video_thread1.cpp和 video_thread2.cpp中使用。)

1)先判断temp的值。为1,跳出;为0,向下执行。

       2)struct sockaddr_in sin;

       sin.sin_family = AF_INET;

       sin.sin_addr.s_addr = htonl(INADDR_ANY);//链接本机

       //sin.sin_addr.s_addr = inet_addr("192.168.47.23");//指定的服务器端地址(但服务器端不用指明客户端地址)

       if(thread_Num == 1)

       {sin.sin_port = 8000;}

       else

       {sin.sin_port = 8001;}

    3)sockfd=socket(AF_INET, SOCK_STREAM, 0);// 建立socket

    4)::connect(sockfd, (sockaddr *)&sin, sizeof(sin));//请求连接,对应server的accept( )

    5)新建init_thread1.jpg和init_thread1.jpg,用于写入接收到的图片数据。

      if(thread_Num==1)

      {fd_frame = fopen("init_thread1.jpg","wb");      }

      else

      {fd_frame = fopen("init_thread2.jpg","wb");}

开始数据传输:

    1)  接收所传图片的一共需要传送的次数times;

    2)  做times次循环;

    3)  ::memset( buff, 0, 1024 ); 不把暂存数组清零会出错误;

    4)  每次接收1024字节len1 = recv(sockfd, buff, 1024, 0);

    5)  每次接收后在传输过程中,接收一次,就顺序写入init_thread1.jpg和init_thread1.jpg

len = fwrite(buff, 1024, 1, fd_frame);

    6)给server端应答信号:len2 = send(sockfd, buf, 10,0);

    7)同理接收最后的小于1024字节的数据(即前面取余所得值)。

    关闭写入图片的指针fclose( fd_frame );

    关闭socket。即::close( sockfd );

阅读(860) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~