www.gusucode.com > 嵌入式linux系统的网络编程源码程序 > 嵌入式linux系统的网络编程源码程序/视频会议源码/video_player.cpp
/////////////////////////////////////////////////////// // FileName: video_player.cpp // Author: b1gm0use // Project: myvideo #include <qpainter.h> #include <iostream> #include <qdatetime.h> #include <qimage.h> #include "video_player.h" #include "capture_event.h" #include "video_cap_thread.h" #include "video.h" #include "avi.h" using namespace std; extern int jpeg_decompress(unsigned char *dst, unsigned char *src, int size, int *w, int *h); extern void dump_image ( const BUFF * image, size_t size, const char * filename ); /////////////////////////////////////////////////////// // Public Functions /////////////////////////////////////////////////////// // 构造函数 // sfr 为是否显示帧数, zoom_in 为是否放大 // 其余三个为widget的子类要求的参数 VideoPlayer::VideoPlayer( avi * avi_ptr_in, bool sfr, bool zoom_in, QWidget *parent, const char *name, int wFlags ) : QWidget( parent, name, wFlags ), conversion_flags( PreferDither ) // {{{ { verbose_output( 2, "create VideoPlayer." ); alloc_context = 0; image = NULL; ct = NULL; repaint_timer = new QTime(); repaint_interval = 0; painter = new QPainter( this ); show_frame_rate = sfr; zoom_image[0] = zoom_image[1] = NULL; recv_image = NULL; jpeg_temp = NULL; frame = 0; zoom = zoom_in; image_mutex = NULL; avi_ptr = avi_ptr_in; is_running = false; } // }}} // 析构函数 VideoPlayer::~VideoPlayer( void ) // {{{ { verbose_output( 2, "delete VideoPlayer." ); if ( NULL != ct ) { if ( ct->running() ) { ct->terminate(); } delete ct; } if ( NULL != repaint_timer ) { delete repaint_timer; } if ( alloc_context ) { QColor::destroyAllocContext( alloc_context ); } delete image; delete repaint_timer; delete painter; delete [] zoom_image[0]; delete [] zoom_image[1]; delete image_mutex; delete [] jpeg_temp; delete [] recv_image; delete image_mutex; } // }}} // 初始化函数 int VideoPlayer::init ( void ) // {{{ { verbose_output( 2, "init VideoPlayer." ); zoom_image[0] = new BUFF[ avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor * avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor * 4 ]; zoom_image[1] = new BUFF[ avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor * avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor * 4 ]; recv_image = new BUFF[ avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor * avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor * 3 ]; if ( NULL == zoom_image[0] || NULL == zoom_image[1] ) { cerr << "No enough memory, exit..." << endl; exit( 1 ); } jpeg_temp = new BUFF[ avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor * avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor * 4 ]; if ( NULL == jpeg_temp ) { cerr << "Not enough memory, exit..." << endl; exit( 1 ); } image_mutex = new QMutex(); return 0; } // }}} void VideoPlayer::begin_running ( void ) // {{{ { verbose_output( 2, "VideoPlayer begin running." ); if ( avi_ptr->net_mode != CONNECT ) { ct = new video_cap_thread ( avi_ptr, this ); ct->start(); } repaint_timer->start(); is_running = true; return; } // }}} bool VideoPlayer::running ( void ) // {{{ { return is_running; } // }}} /////////////////////////////////////////////////////// // Protected Functions /////////////////////////////////////////////////////// // 内部方法,当发生重绘事件时被调用 void VideoPlayer::paintEvent( QPaintEvent *e ) // {{{ { verbose_output( 4, "VideoPlayer repaint." ); // 如果当前的图像可用,则用当前图像绘制 if ( NULL != image && !image->isNull() ) { //计算上次重绘到现在经历了多长时间 repaint_interval += repaint_timer->elapsed(); repaint_timer->restart(); if ( repaint_interval < 60 ) { return; } painter->setClipRect(e->rect()); //image_mutex->lock(); painter->drawImage( 0, 0, *image ); //image_mutex->unlock(); if ( show_frame_rate ) { char tmp[5]; snprintf( tmp, 5, "%2.1f", 1000/static_cast < double > ( repaint_interval ) ); tmp[4] = '\0'; painter->setPen( green ); painter->setFont( QFont::QFont( "Times", 20 ) ); painter->drawText( 0, 15, QString::QString( tmp ) ); repaint_interval = 0; } return; } else { //painter->setClipRect(e->rect()); //painter->setPen( black ); //painter->setFont( QFont::QFont( "Times", 15, QFont::Bold ) ); //painter->drawText( 20, 20, QString::QString( "No Image Avaliable" ) ); //painter->drawText( 20, 70, QString::QString( "Please Waiting" ) ); } repaint_timer->restart(); } // }}} // 内部函数,用于接收自定义的事件 // 在本事件中,对接收的原始图像进行放大处理 void VideoPlayer::customEvent ( QCustomEvent * e ) // {{{ { verbose_output( 4, "VideoPlayer change image event." ); // 判断事件类型,是否正确 if ( e->type() == VIDEO_EVENT ) { capture_event * ce = ( capture_event * ) e; BUFF * temp = ce->get_buff(); int size = ce->get_size(); QImage * img = NULL; QImage * img_temp = NULL; (*(avi_ptr->video_send_semaphore))++; memcpy( recv_image, temp, size ); (*(avi_ptr->video_send_semaphore))--; //判断是否要放大 int w, h; unsigned short int * header = (unsigned short*) recv_image; if ( (*header) != JPEG_HEAD_MAGIC ) { cerr << "Warning! Bad JPEG file" << endl; return; } // JPEG解压缩 int result = jpeg_decompress( jpeg_temp, recv_image, size, &w, &h); if ( result == -1 ) { cerr << "Warning! decompress too few data" << endl; } if ( w != avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor || h!= avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor ) { cerr << "Warning! the size of picture is not expected!" << endl; } temp = jpeg_temp; //能识别的大小,由3byte 转为4byte //复制 for ( register int i=0; i< avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor * avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor; i++ ) { for ( register int j=0; j<4; j++ ) { zoom_image[frame][i*4+j] = temp[i*3+j]; } } img_temp = new QImage( zoom_image[frame], avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor, avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor, 32, 0, 65535, QImage::BigEndian ); if( zoom ) { img = new QImage( img_temp->smoothScale( avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor * 2, avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor * 2, QImage::ScaleMax ) ); } else { img = img_temp; } if ( NULL == img || img->isNull() ) { cerr << "Can't load image" << endl; return; } setImage( img ); frame ^= 1; if ( zoom ) { // 非放大时,指会指向相同对象,不可删除。 delete img_temp; } } } // }}} /////////////////////////////////////////////////////// // Private Functions /////////////////////////////////////////////////////// // 设置当前图像,并重绘屏幕 void VideoPlayer::setImage(const QImage * newimage) // {{{ { //delete image; image = newimage; reconvertImage(); repaint( image->hasAlphaBuffer() ); } // }}} // 目的不明 bool VideoPlayer::reconvertImage() // {{{ { verbose_output( 3, "reconvert image" ); if ( alloc_context ) { QColor::destroyAllocContext( alloc_context ); alloc_context = 0; } if ( zoom ) { resize( avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor * 2, avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor * 2 ); } else { resize( avi_ptr->video_opt.min_width * avi_ptr->video_opt.factor, avi_ptr->video_opt.min_height * avi_ptr->video_opt.factor ); } return true; } // }}}