mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-09-22 13:54:55 -04:00
added bandwidth measurement for video. Still needs codec to accound for it
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7463 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
9c3266fdd9
commit
c6103b7535
15 changed files with 157 additions and 73 deletions
|
@ -24,8 +24,6 @@ void PluginGUIHandler::ReceivedVoipAccept(const QString& /*peer_id*/)
|
|||
|
||||
void PluginGUIHandler::ReceivedVoipData(const QString& qpeer_id)
|
||||
{
|
||||
std::cerr << "****** Plugin GUI handler: received VoipData!" << std::endl;
|
||||
|
||||
RsPeerId peer_id(qpeer_id.toStdString()) ;
|
||||
std::vector<RsVoipDataChunk> chunks ;
|
||||
|
||||
|
@ -54,10 +52,7 @@ void PluginGUIHandler::ReceivedVoipData(const QString& qpeer_id)
|
|||
if(chunks[chunkIndex].type == RsVoipDataChunk::RS_VOIP_DATA_TYPE_AUDIO)
|
||||
acwh->addAudioData(QString::fromStdString(peer_id.toStdString()),&qb);
|
||||
else if(chunks[chunkIndex].type == RsVoipDataChunk::RS_VOIP_DATA_TYPE_VIDEO)
|
||||
{
|
||||
acwh->addVideoData(QString::fromStdString(peer_id.toStdString()),&qb);
|
||||
std::cerr << "data triaged as video." << std::endl;
|
||||
}
|
||||
else
|
||||
std::cerr << "Unknown data type received. type=" << chunks[chunkIndex].type << std::endl;
|
||||
}
|
||||
|
@ -75,3 +70,32 @@ void PluginGUIHandler::ReceivedVoipData(const QString& qpeer_id)
|
|||
}
|
||||
}
|
||||
|
||||
void PluginGUIHandler::ReceivedVoipBandwidthInfo(const QString& qpeer_id,int bytes_per_sec)
|
||||
{
|
||||
RsPeerId peer_id(qpeer_id.toStdString()) ;
|
||||
|
||||
ChatDialog *di = ChatDialog::getExistingChat(peer_id) ;
|
||||
|
||||
std::cerr << "PluginGUIHandler::received bw info for peer " << qpeer_id.toStdString() << ": " << bytes_per_sec << " Bps" << std::endl;
|
||||
if(!di)
|
||||
{
|
||||
std::cerr << "Error: received bandwidth info for a chat dialog that does not stand VOIP (Peer id = " << peer_id.toStdString() << "!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
ChatWidget *cw = di->getChatWidget();
|
||||
if(!cw)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
const QList<ChatWidgetHolder*> &chatWidgetHolderList = cw->chatWidgetHolderList();
|
||||
|
||||
foreach (ChatWidgetHolder *chatWidgetHolder, chatWidgetHolderList)
|
||||
{
|
||||
VOIPChatWidgetHolder *acwh = dynamic_cast<VOIPChatWidgetHolder*>(chatWidgetHolder) ;
|
||||
|
||||
if (acwh)
|
||||
acwh->setAcceptedBandwidth(QString::fromStdString(peer_id.toStdString()),bytes_per_sec);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
// in the main GUI thread.
|
||||
//
|
||||
|
||||
#include <stdint.h>
|
||||
#include <QObject>
|
||||
|
||||
class PluginGUIHandler: public QObject
|
||||
|
@ -16,4 +17,5 @@ class PluginGUIHandler: public QObject
|
|||
void ReceivedVoipData(const QString& peer_id) ;
|
||||
void ReceivedVoipHangUp(const QString& peer_id) ;
|
||||
void ReceivedVoipAccept(const QString& peer_id) ;
|
||||
void ReceivedVoipBandwidthInfo(const QString& peer_id,int) ;
|
||||
};
|
||||
|
|
|
@ -16,3 +16,7 @@ void PluginNotifier::notifyReceivedVoipHangUp(const RsPeerId &peer_id)
|
|||
{
|
||||
emit voipHangUpReceived(QString::fromStdString(peer_id.toStdString())) ;
|
||||
}
|
||||
void PluginNotifier::notifyReceivedVoipBandwidth(const RsPeerId &peer_id,uint32_t bytes_per_sec)
|
||||
{
|
||||
emit voipBandwidthInfoReceived(QString::fromStdString(peer_id.toStdString()),bytes_per_sec) ;
|
||||
}
|
||||
|
|
|
@ -17,10 +17,13 @@ class PluginNotifier: public QObject
|
|||
void notifyReceivedVoipInvite(const RsPeerId &peer_id) ;
|
||||
void notifyReceivedVoipHangUp(const RsPeerId& peer_id) ;
|
||||
void notifyReceivedVoipAccept(const RsPeerId &peer_id) ;
|
||||
void notifyReceivedVoipBandwidth(const RsPeerId &peer_id,uint32_t bytes_per_sec) ;
|
||||
|
||||
signals:
|
||||
void voipInvitationReceived(const QString&) ; // signal emitted when an invitation has been received
|
||||
void voipDataReceived(const QString&) ; // signal emitted when some voip data has been received
|
||||
void voipHangUpReceived(const QString& peer_id) ; // emitted when the peer closes the call (i.e. hangs up)
|
||||
void voipAcceptReceived(const QString& peer_id) ; // emitted when the peer accepts the call
|
||||
void voipBandwidthInfoReceived(const QString& peer_id,int bytes_per_sec) ; // emitted when measured bandwidth info is received by the peer.
|
||||
};
|
||||
|
||||
|
|
|
@ -95,17 +95,17 @@ QVideoInputDevice::~QVideoInputDevice()
|
|||
|
||||
QVideoOutputDevice::QVideoOutputDevice(QWidget *parent)
|
||||
: QLabel(parent)
|
||||
{
|
||||
showFrameOff() ;
|
||||
}
|
||||
|
||||
void QVideoOutputDevice::showFrameOff()
|
||||
{
|
||||
setPixmap(QPixmap(":/images/video-icon-big.png").scaled(170,128,Qt::KeepAspectRatio,Qt::SmoothTransformation)) ;
|
||||
}
|
||||
|
||||
void QVideoOutputDevice::showFrame(const QImage& img)
|
||||
{
|
||||
//std::cerr << "Displaying frame!!" << std::endl;
|
||||
|
||||
//QPainter painter(this) ;
|
||||
//painter.drawImage(QPointF(0,0),img) ;
|
||||
|
||||
setPixmap(QPixmap::fromImage(img).scaled(minimumSize(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ class QVideoOutputDevice: public QLabel
|
|||
QVideoOutputDevice(QWidget *parent) ;
|
||||
|
||||
void showFrame(const QImage&) ;
|
||||
void showFrameOff() ;
|
||||
};
|
||||
|
||||
// Responsible for grabbing the video from the webcam and sending it to the
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget)
|
||||
: QObject(), ChatWidgetHolder(chatWidget)
|
||||
{
|
||||
std::cerr << "****** VOIPLugin: Creating new VOIPChatWidgetHolder !!" << std::endl;
|
||||
|
||||
QIcon icon ;
|
||||
icon.addPixmap(QPixmap(":/images/audio-volume-muted-22.png")) ;
|
||||
icon.addPixmap(QPixmap(":/images/audio-volume-medium-22.png"),QIcon::Normal,QIcon::On) ;
|
||||
|
@ -136,7 +134,6 @@ VOIPChatWidgetHolder::~VOIPChatWidgetHolder()
|
|||
|
||||
void VOIPChatWidgetHolder::toggleAudioListen()
|
||||
{
|
||||
std::cerr << "******** VOIPLugin: Toggling audio listen!" << std::endl;
|
||||
if (audioListenToggleButton->isChecked()) {
|
||||
audioListenToggleButton->setToolTip(tr("Mute yourself"));
|
||||
} else {
|
||||
|
@ -150,22 +147,19 @@ void VOIPChatWidgetHolder::toggleAudioListen()
|
|||
|
||||
void VOIPChatWidgetHolder::hangupCall()
|
||||
{
|
||||
std::cerr << "******** VOIPLugin: Hangup call!" << std::endl;
|
||||
|
||||
disconnect(inputAudioProcessor, SIGNAL(networkPacketReady()), this, SLOT(sendAudioData()));
|
||||
if (inputAudioDevice) {
|
||||
inputAudioDevice->stop();
|
||||
}
|
||||
if (outputAudioDevice) {
|
||||
outputAudioDevice->stop();
|
||||
}
|
||||
audioListenToggleButton->setChecked(false);
|
||||
audioCaptureToggleButton->setChecked(false);
|
||||
disconnect(inputAudioProcessor, SIGNAL(networkPacketReady()), this, SLOT(sendAudioData()));
|
||||
if (inputAudioDevice) {
|
||||
inputAudioDevice->stop();
|
||||
}
|
||||
if (outputAudioDevice) {
|
||||
outputAudioDevice->stop();
|
||||
}
|
||||
audioListenToggleButton->setChecked(false);
|
||||
audioCaptureToggleButton->setChecked(false);
|
||||
}
|
||||
|
||||
void VOIPChatWidgetHolder::toggleAudioCapture()
|
||||
{
|
||||
std::cerr << "******** VOIPLugin: Toggling audio mute capture!" << std::endl;
|
||||
if (audioCaptureToggleButton->isChecked()) {
|
||||
//activate audio output
|
||||
audioListenToggleButton->setChecked(true);
|
||||
|
@ -199,8 +193,6 @@ void VOIPChatWidgetHolder::toggleAudioCapture()
|
|||
}
|
||||
void VOIPChatWidgetHolder::toggleVideoCapture()
|
||||
{
|
||||
std::cerr << "******** VOIPLugin: Toggling video capture!" << std::endl;
|
||||
|
||||
if (videoCaptureToggleButton->isChecked())
|
||||
{
|
||||
//activate video input
|
||||
|
@ -216,6 +208,7 @@ void VOIPChatWidgetHolder::toggleVideoCapture()
|
|||
{
|
||||
inputVideoDevice->stop() ;
|
||||
videoCaptureToggleButton->setToolTip(tr("Activate camera"));
|
||||
outputVideoDevice->showFrameOff();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,6 +217,11 @@ void VOIPChatWidgetHolder::addVideoData(const QString name, QByteArray* array)
|
|||
outputVideoProcessor->receiveEncodedData((unsigned char *)array->data(),array->size()) ;
|
||||
}
|
||||
|
||||
void VOIPChatWidgetHolder::setAcceptedBandwidth(const QString name, uint32_t bytes_per_sec)
|
||||
{
|
||||
inputVideoProcessor->setMaximumFrameRate(bytes_per_sec) ;
|
||||
}
|
||||
|
||||
void VOIPChatWidgetHolder::addAudioData(const QString name, QByteArray* array)
|
||||
{
|
||||
if (!audioCaptureToggleButton->isChecked()) {
|
||||
|
@ -288,10 +286,7 @@ void VOIPChatWidgetHolder::sendVideoData()
|
|||
RsVoipDataChunk chunk ;
|
||||
|
||||
while(inputVideoDevice && inputVideoDevice->getNextEncodedPacket(chunk))
|
||||
{
|
||||
std::cerr << "Video data ready: sending it" << std::endl;
|
||||
rsVoip->sendVoipData(mChatWidget->getPeerId(),chunk) ;
|
||||
}
|
||||
}
|
||||
|
||||
void VOIPChatWidgetHolder::sendAudioData()
|
||||
|
|
|
@ -25,6 +25,7 @@ public:
|
|||
|
||||
void addAudioData(const QString name, QByteArray* array) ;
|
||||
void addVideoData(const QString name, QByteArray* array) ;
|
||||
void setAcceptedBandwidth(const QString name, uint32_t bytes_per_sec) ;
|
||||
|
||||
private slots:
|
||||
void toggleAudioListen();
|
||||
|
|
|
@ -7,21 +7,13 @@
|
|||
#include "VideoProcessor.h"
|
||||
#include "QVideoDevice.h"
|
||||
|
||||
//bool VideoDecoder::getNextImage(QImage& image)
|
||||
//{
|
||||
// if(_image_queue.empty())
|
||||
// return false ;
|
||||
//
|
||||
// image = _image_queue.front() ;
|
||||
// _image_queue.pop_front() ;
|
||||
//
|
||||
// return true ;
|
||||
//}
|
||||
VideoDecoder::VideoDecoder()
|
||||
{
|
||||
_output_device = NULL ;
|
||||
}
|
||||
|
||||
bool VideoEncoder::addImage(const QImage& img)
|
||||
{
|
||||
std::cerr << "VideoEncoder: adding image." << std::endl;
|
||||
|
||||
encodeData(img) ;
|
||||
|
||||
return true ;
|
||||
|
@ -48,10 +40,7 @@ QImage JPEGVideoDecoder::decodeData(const unsigned char *encoded_image_data,uint
|
|||
QByteArray qb((char*)encoded_image_data,size) ;
|
||||
QImage image ;
|
||||
if(image.loadFromData(qb,"JPEG"))
|
||||
{
|
||||
std::cerr << "image decoded successfully" << std::endl;
|
||||
return image ;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "image.loadFromData(): returned an error.: " << std::endl;
|
||||
|
@ -59,6 +48,12 @@ QImage JPEGVideoDecoder::decodeData(const unsigned char *encoded_image_data,uint
|
|||
}
|
||||
}
|
||||
|
||||
void VideoEncoder::setMaximumFrameRate(uint32_t bytes_per_sec)
|
||||
{
|
||||
std::cerr << "Video Encoder: maximum frame rate is set to " << bytes_per_sec << " Bps" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void JPEGVideoEncoder::encodeData(const QImage& image)
|
||||
{
|
||||
QByteArray qb ;
|
||||
|
@ -67,8 +62,6 @@ void JPEGVideoEncoder::encodeData(const QImage& image)
|
|||
buffer.open(QIODevice::WriteOnly) ;
|
||||
image.save(&buffer,"JPEG") ;
|
||||
|
||||
//destination_decoder->receiveEncodedData((unsigned char *)qb.data(),qb.size()) ;
|
||||
|
||||
RsVoipDataChunk voip_chunk ;
|
||||
voip_chunk.data = malloc(qb.size());
|
||||
memcpy(voip_chunk.data,qb.data(),qb.size()) ;
|
||||
|
@ -76,7 +69,5 @@ void JPEGVideoEncoder::encodeData(const QImage& image)
|
|||
voip_chunk.type = RsVoipDataChunk::RS_VOIP_DATA_TYPE_VIDEO ;
|
||||
|
||||
_out_queue.push_back(voip_chunk) ;
|
||||
|
||||
std::cerr << "sending encoded data. size = " << std::dec << qb.size() << std::endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ class QVideoOutputDevice ;
|
|||
class VideoDecoder
|
||||
{
|
||||
public:
|
||||
VideoDecoder() { _output_device = NULL ;}
|
||||
VideoDecoder() ;
|
||||
|
||||
// Gets the next image to be displayed. Once returned, the image should
|
||||
// be cleared from the incoming queue.
|
||||
|
@ -21,6 +21,10 @@ class VideoDecoder
|
|||
|
||||
virtual void receiveEncodedData(const unsigned char *data,uint32_t size) ;
|
||||
|
||||
// returns the current (measured) frame rate in bytes per second.
|
||||
//
|
||||
uint32_t currentFrameRate() const;
|
||||
|
||||
private:
|
||||
QVideoOutputDevice *_output_device ;
|
||||
|
||||
|
@ -30,12 +34,12 @@ class VideoDecoder
|
|||
//
|
||||
virtual QImage decodeData(const unsigned char *encoded_image,uint32_t encoded_image_size) = 0 ;
|
||||
|
||||
// This buffer accumulated incoming encoded data, until a full packet is obtained,
|
||||
// since the stream might not send images at once. When incoming images are decoded, the
|
||||
// data is removed from the buffer.
|
||||
//
|
||||
unsigned char *buffer ;
|
||||
uint32_t buffer_size ;
|
||||
// // This buffer accumulated incoming encoded data, until a full packet is obtained,
|
||||
// // since the stream might not send images at once. When incoming images are decoded, the
|
||||
// // data is removed from the buffer.
|
||||
// //
|
||||
// unsigned char *buffer ;
|
||||
// uint32_t buffer_size ;
|
||||
};
|
||||
|
||||
// This class encodes video using a video codec (possibly homemade, or based on existing codecs)
|
||||
|
@ -52,6 +56,11 @@ class VideoEncoder
|
|||
|
||||
bool packetReady() const { return !_out_queue.empty() ; }
|
||||
bool nextPacket(RsVoipDataChunk& ) ;
|
||||
|
||||
// Used to tweak the compression ratio so that the video can stream ok.
|
||||
//
|
||||
void setMaximumFrameRate(uint32_t bytes_per_second) ;
|
||||
|
||||
protected:
|
||||
//virtual bool sendEncodedData(unsigned char *mem,uint32_t size) = 0 ;
|
||||
virtual void encodeData(const QImage& image) = 0 ;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue