2018-11-04 10:19:17 -05:00
/*******************************************************************************
* plugins / VOIP / gui / QVideoDevice . cpp *
* *
* Copyright ( C ) 2012 by Retroshare Team < retroshare . project @ gmail . com > *
* *
* This program is free software : you can redistribute it and / or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation , either version 3 of the *
* License , or ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU Affero General Public License for more details . *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program . If not , see < https : //www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-07-13 09:57:25 -04:00
# include <QTimer>
# include <QPainter>
2021-05-12 03:40:42 -04:00
# include <QImageReader>
# include <QBuffer>
# include <QCamera>
# include <QCameraInfo>
# include <QCameraImageCapture>
2014-07-13 09:57:25 -04:00
# include "QVideoDevice.h"
# include "VideoProcessor.h"
2021-05-27 15:21:26 -04:00
// #define DEBUG_QVIDEODEVICE 1
2014-07-13 09:57:25 -04:00
QVideoInputDevice : : QVideoInputDevice ( QWidget * parent )
2015-05-11 15:40:07 -04:00
: QObject ( parent )
2014-07-13 09:57:25 -04:00
{
_timer = NULL ;
_capture_device = NULL ;
2015-08-14 16:44:20 -04:00
_video_processor = NULL ;
2014-07-13 09:57:25 -04:00
_echo_output_device = NULL ;
}
2021-05-12 03:40:42 -04:00
QVideoInputDevice : : ~ QVideoInputDevice ( )
{
stop ( ) ;
_video_processor = NULL ;
delete _image_capture ;
delete _capture_device ;
delete _timer ;
}
2021-05-27 15:45:56 -04:00
bool QVideoInputDevice : : stopped ( ) const
2015-09-02 22:14:04 -04:00
{
return _timer = = NULL ;
}
2014-07-13 09:57:25 -04:00
void QVideoInputDevice : : stop ( )
{
2021-05-27 15:21:26 -04:00
_capture_device_info = QCameraInfo ( ) ;
2014-07-13 09:57:25 -04:00
if ( _timer ! = NULL )
{
2021-05-12 03:40:42 -04:00
_capture_device - > stop ( ) ;
2014-07-13 09:57:25 -04:00
_timer - > stop ( ) ;
delete _timer ;
_timer = NULL ;
}
if ( _capture_device ! = NULL )
{
2015-10-03 22:08:24 -04:00
// the camera will be deinitialized automatically in VideoCapture destructor
2021-05-12 03:40:42 -04:00
delete _image_capture ;
delete _capture_device ;
2014-07-13 09:57:25 -04:00
_capture_device = NULL ;
2021-05-12 03:40:42 -04:00
_image_capture = NULL ;
}
2021-05-27 15:21:26 -04:00
if ( _echo_output_device ! = NULL )
_echo_output_device - > showFrameOff ( ) ;
2014-07-13 09:57:25 -04:00
}
2021-05-15 15:37:11 -04:00
void QVideoInputDevice : : getAvailableDevices ( QList < QString > & device_desc )
{
device_desc . clear ( ) ;
QList < QCameraInfo > dev_list = QCameraInfo : : availableCameras ( ) ;
for ( auto & cam : dev_list )
device_desc . push_back ( cam . deviceName ( ) ) ;
}
void QVideoInputDevice : : start ( const QString & description )
2014-07-13 09:57:25 -04:00
{
2015-10-03 22:08:24 -04:00
// make sure everything is re-initialised
2014-07-13 09:57:25 -04:00
//
stop ( ) ;
2021-05-15 15:37:11 -04:00
QCameraInfo caminfo ;
if ( description . isNull ( ) )
caminfo = QCameraInfo : : defaultCamera ( ) ;
else
{
auto cam_list = QCameraInfo : : availableCameras ( ) ;
for ( auto & s : cam_list )
if ( s . deviceName ( ) = = description )
caminfo = s ;
}
2014-07-13 09:57:25 -04:00
2021-05-12 03:40:42 -04:00
if ( caminfo . isNull ( ) )
{
std : : cerr < < " No video camera available in this system! " < < std : : endl ;
return ;
}
2021-05-27 15:21:26 -04:00
_capture_device_info = caminfo ;
2021-05-12 03:40:42 -04:00
_capture_device = new QCamera ( caminfo ) ;
2014-07-13 09:57:25 -04:00
2021-05-12 03:40:42 -04:00
if ( _capture_device - > error ( ) ! = QCamera : : NoError )
{
emit cameraCaptureInfo ( CANNOT_INITIALIZE_CAMERA , _capture_device - > error ( ) ) ;
std : : cerr < < " Cannot initialise camera. Something's wrong. " < < std : : endl ;
return ;
}
_capture_device - > setCaptureMode ( QCamera : : CaptureStillImage ) ;
if ( _capture_device - > error ( ) = = QCamera : : NoError )
emit cameraCaptureInfo ( CAMERA_IS_READY , QCamera : : NoError ) ;
_image_capture = new QCameraImageCapture ( _capture_device ) ;
if ( ! _image_capture - > isCaptureDestinationSupported ( QCameraImageCapture : : CaptureToBuffer ) )
{
emit cameraCaptureInfo ( CAMERA_IS_READY , QCamera : : NoError ) ;
2014-07-13 09:57:25 -04:00
2021-05-12 03:40:42 -04:00
delete _capture_device ;
delete _image_capture ;
return ;
}
_image_capture - > setCaptureDestination ( QCameraImageCapture : : CaptureToBuffer ) ;
QObject : : connect ( _image_capture , SIGNAL ( imageAvailable ( int , QVideoFrame ) ) , this , SLOT ( grabFrame ( int , QVideoFrame ) ) ) ;
QObject : : connect ( this , SIGNAL ( cameraCaptureInfo ( CameraStatus , QCamera : : Error ) ) , this , SLOT ( errorHandling ( CameraStatus , QCamera : : Error ) ) ) ;
_timer = new QTimer ;
QObject : : connect ( _timer , SIGNAL ( timeout ( ) ) , _image_capture , SLOT ( capture ( ) ) ) ;
_timer - > start ( 50 ) ; // 10 images per second.
_capture_device - > start ( ) ;
2014-07-13 09:57:25 -04:00
}
2021-05-12 03:40:42 -04:00
void QVideoInputDevice : : errorHandling ( CameraStatus status , QCamera : : Error error )
2014-07-13 09:57:25 -04:00
{
2021-05-27 15:21:26 -04:00
# ifdef DEBUG_QVIDEODEVICE
2021-05-12 03:40:42 -04:00
std : : cerr < < " Received msg from camera capture: status= " < < ( int ) status < < " error= " < < ( int ) error < < std : : endl ;
2022-01-03 18:39:13 -05:00
# else
Q_UNUSED ( error ) ;
2021-05-27 15:21:26 -04:00
# endif
2021-05-12 03:40:42 -04:00
if ( status = = CANNOT_INITIALIZE_CAMERA )
2015-08-09 18:09:17 -04:00
{
2021-05-12 03:40:42 -04:00
std : : cerr < < " Cannot initialize camera. Make sure to install package libqt5multimedia5-plugins, as this is a common cause for camera not being found. " < < std : : endl ;
2015-08-09 18:09:17 -04:00
}
2021-05-12 03:40:42 -04:00
}
2015-10-03 22:08:24 -04:00
2021-05-12 03:40:42 -04:00
void QVideoInputDevice : : grabFrame ( int id , QVideoFrame frame )
{
if ( frame . size ( ) . isEmpty ( ) )
2015-08-09 18:09:17 -04:00
{
2021-05-12 03:40:42 -04:00
std : : cerr < < " Empty frame! " ;
return ;
2015-08-09 18:09:17 -04:00
}
2014-07-13 09:57:25 -04:00
2021-05-12 03:40:42 -04:00
frame . map ( QAbstractVideoBuffer : : ReadOnly ) ;
QByteArray data ( ( const char * ) frame . bits ( ) , frame . mappedBytes ( ) ) ;
QBuffer buffer ;
buffer . setData ( data ) ;
buffer . open ( QIODevice : : ReadOnly ) ;
QImageReader reader ( & buffer , " JPG " ) ;
reader . setScaledSize ( QSize ( 640 , 480 ) ) ;
QImage image ( reader . read ( ) ) ;
2021-05-27 15:21:26 -04:00
# ifdef DEBUG_QVIDEODEVICE
2021-05-12 03:40:42 -04:00
std : : cerr < < " Frame " < < id < < " . Pixel format: " < < frame . pixelFormat ( ) < < " . Size: " < < image . size ( ) . width ( ) < < " x " < < image . size ( ) . height ( ) < < std : : endl ; // if(frame.pixelFormat() != QVideoFrame::Format_Jpeg)
2022-01-03 18:39:13 -05:00
# else
Q_UNUSED ( id ) ;
2021-05-27 15:21:26 -04:00
# endif
2014-07-13 09:57:25 -04:00
2015-10-03 22:08:24 -04:00
if ( _video_processor ! = NULL )
2015-08-09 18:09:17 -04:00
{
2015-10-03 22:08:24 -04:00
_video_processor - > processImage ( image ) ;
2015-08-09 18:09:17 -04:00
2015-10-03 22:08:24 -04:00
emit networkPacketReady ( ) ;
2015-08-09 18:09:17 -04:00
}
2015-10-03 22:08:24 -04:00
if ( _echo_output_device ! = NULL )
_echo_output_device - > showFrame ( image ) ;
2014-07-13 09:57:25 -04:00
}
2015-05-11 15:40:07 -04:00
bool QVideoInputDevice : : getNextEncodedPacket ( RsVOIPDataChunk & chunk )
2014-07-15 16:04:31 -04:00
{
2015-09-02 22:14:04 -04:00
if ( ! _timer )
return false ;
2015-10-03 22:08:24 -04:00
2015-08-14 16:44:20 -04:00
if ( _video_processor )
2015-10-03 22:08:24 -04:00
return _video_processor - > nextEncodedPacket ( chunk ) ;
else
2015-08-24 21:15:33 -04:00
return false ;
}
uint32_t QVideoInputDevice : : currentBandwidth ( ) const
{
2021-05-27 15:45:56 -04:00
if ( stopped ( ) )
return 0 ;
else
return _video_processor - > currentBandwidthOut ( ) ;
2014-07-15 16:04:31 -04:00
}
2014-07-13 09:57:25 -04:00
QVideoOutputDevice : : QVideoOutputDevice ( QWidget * parent )
2015-10-03 22:08:24 -04:00
: QLabel ( parent )
2014-07-20 16:50:36 -04:00
{
showFrameOff ( ) ;
}
void QVideoOutputDevice : : showFrameOff ( )
2014-07-13 09:57:25 -04:00
{
2015-10-02 20:11:52 -04:00
setPixmap ( QPixmap ( " :/images/video-icon-big.png " ) . scaled ( QSize ( height ( ) * 4 / 3 , height ( ) ) , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) ) ;
2015-10-06 19:35:31 -04:00
setAlignment ( Qt : : AlignCenter ) ;
2014-07-13 09:57:25 -04:00
}
void QVideoOutputDevice : : showFrame ( const QImage & img )
{
2021-05-27 15:21:26 -04:00
# ifdef DEBUG_QVIDEODEVICE
2015-08-08 18:46:49 -04:00
std : : cerr < < " img.size = " < < img . width ( ) < < " x " < < img . height ( ) < < std : : endl ;
2021-05-27 15:21:26 -04:00
# endif
2015-10-03 22:08:24 -04:00
setPixmap ( QPixmap : : fromImage ( img ) . scaled ( QSize ( height ( ) * 4 / 3 , height ( ) ) , Qt : : IgnoreAspectRatio , Qt : : SmoothTransformation ) ) ;
2014-07-13 09:57:25 -04:00
}