📄 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;} // }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -