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;

} // }}}