added max bandwidth test preview and in/out bw estimate. Still missing the logic inside the codec

This commit is contained in:
csoler 2015-08-24 21:15:33 -04:00
parent 79aac23b6c
commit 3f1ebca803
8 changed files with 120 additions and 45 deletions

View file

@ -120,6 +120,8 @@ AudioInputConfig::AudioInputConfig(QWidget * parent, Qt::WindowFlags flags)
videoProcessor = new VideoProcessor() ; videoProcessor = new VideoProcessor() ;
videoProcessor->setDisplayTarget(NULL) ; videoProcessor->setDisplayTarget(NULL) ;
videoProcessor->setMaximumBandwidth(ui.availableBW_SB->value()) ;
videoInput->setVideoProcessor(videoProcessor) ; videoInput->setVideoProcessor(videoProcessor) ;
graph_source = new voipGraphSource ; graph_source = new voipGraphSource ;
@ -130,6 +132,13 @@ AudioInputConfig::AudioInputConfig(QWidget * parent, Qt::WindowFlags flags)
graph_source->start() ; graph_source->start() ;
QObject::connect(ui.showEncoded_CB,SIGNAL(toggled(bool)),this,SLOT(togglePreview(bool))) ; QObject::connect(ui.showEncoded_CB,SIGNAL(toggled(bool)),this,SLOT(togglePreview(bool))) ;
QObject::connect(ui.availableBW_SB,SIGNAL(valueChanged(double)),this,SLOT(updateAvailableBW(double))) ;
}
void AudioInputConfig::updateAvailableBW(double r)
{
std::cerr << "Setting max bandwidth to " << r << " KB/s" << std::endl;
videoProcessor->setMaximumBandwidth((uint32_t)(r*1024)) ;
} }
void AudioInputConfig::togglePreview(bool b) void AudioInputConfig::togglePreview(bool b)

View file

@ -95,6 +95,7 @@ class AudioInputConfig : public ConfigPage
virtual QString helpText() const { return ""; } virtual QString helpText() const { return ""; }
private slots: private slots:
void updateAvailableBW(double r);
void loadSettings(); void loadSettings();
void emptyBuffer(); void emptyBuffer();
void togglePreview(bool) ; void togglePreview(bool) ;

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1155</width> <width>1155</width>
<height>713</height> <height>832</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
@ -391,6 +391,39 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Available bandwidth:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="availableBW_SB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use this field to simulate the maximum bandwidth available so as to preview what the encoded video will look like with the corresponding compression rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="suffix">
<string>KB/s</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>5.000000000000000</double>
</property>
<property name="maximum">
<double>200.000000000000000</double>
</property>
<property name="value">
<double>30.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QCheckBox" name="showEncoded_CB"> <widget class="QCheckBox" name="showEncoded_CB">
<property name="toolTip"> <property name="toolTip">

View file

@ -13,9 +13,6 @@ QVideoInputDevice::QVideoInputDevice(QWidget *parent)
_capture_device = NULL ; _capture_device = NULL ;
_video_processor = NULL ; _video_processor = NULL ;
_echo_output_device = NULL ; _echo_output_device = NULL ;
_estimated_bw = 0 ;
_total_encoded_size = 0 ;
_last_bw_estimate_TS = time(NULL) ;
} }
void QVideoInputDevice::stop() void QVideoInputDevice::stop()
@ -80,27 +77,7 @@ void QVideoInputDevice::grabFrame()
if(_video_processor != NULL) if(_video_processor != NULL)
{ {
uint32_t encoded_size ; _video_processor->processImage(image,0) ;
_video_processor->processImage(image,0,encoded_size) ;
#ifdef DEBUG_VIDEO_OUTPUT_DEVICE
std::cerr << "Encoded size = " << encoded_size << std::endl;
#endif
_total_encoded_size += encoded_size ;
time_t now = time(NULL) ;
if(now > _last_bw_estimate_TS)
{
_estimated_bw = uint32_t(0.75*_estimated_bw + 0.25 * (_total_encoded_size / (float)(now - _last_bw_estimate_TS))) ;
_total_encoded_size = 0 ;
_last_bw_estimate_TS = now ;
#ifdef DEBUG_VIDEO_OUTPUT_DEVICE
std::cerr << "new bw estimate: " << _estimated_bw << std::endl;
#endif
}
emit networkPacketReady() ; emit networkPacketReady() ;
} }
@ -116,6 +93,11 @@ bool QVideoInputDevice::getNextEncodedPacket(RsVOIPDataChunk& chunk)
return false ; return false ;
} }
uint32_t QVideoInputDevice::currentBandwidth() const
{
return _video_processor->currentBandwidthOut() ;
}
QVideoInputDevice::~QVideoInputDevice() QVideoInputDevice::~QVideoInputDevice()
{ {
stop() ; stop() ;

View file

@ -45,7 +45,7 @@ class QVideoInputDevice: public QObject
// gets the estimated current bandwidth required to transmit the encoded data, in B/s // gets the estimated current bandwidth required to transmit the encoded data, in B/s
// //
uint32_t currentBandwidth() const { return _estimated_bw ; } uint32_t currentBandwidth() const ;
// control // control
@ -66,9 +66,5 @@ class QVideoInputDevice: public QObject
QVideoOutputDevice *_echo_output_device ; QVideoOutputDevice *_echo_output_device ;
std::list<RsVOIPDataChunk> _out_queue ; std::list<RsVOIPDataChunk> _out_queue ;
uint32_t _estimated_bw ;
time_t _last_bw_estimate_TS;
uint32_t _total_encoded_size ;
}; };

View file

@ -365,7 +365,7 @@ void VOIPChatWidgetHolder::botMouseLeave()
void VOIPChatWidgetHolder::setAcceptedBandwidth(uint32_t bytes_per_sec) void VOIPChatWidgetHolder::setAcceptedBandwidth(uint32_t bytes_per_sec)
{ {
videoProcessor->setMaximumFrameRate(bytes_per_sec) ; videoProcessor->setMaximumBandwidth(bytes_per_sec) ;
} }
void VOIPChatWidgetHolder::addAudioData(const RsPeerId &peer_id, QByteArray* array) void VOIPChatWidgetHolder::addAudioData(const RsPeerId &peer_id, QByteArray* array)

View file

@ -32,9 +32,19 @@ VideoProcessor::VideoProcessor()
//_encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO; //_encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO;
//_encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_DDWT_VIDEO; //_encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_DDWT_VIDEO;
_encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO; _encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO;
_estimated_bandwidth_in = 0 ;
_estimated_bandwidth_out = 0 ;
_target_bandwidth_out = 0 ;
_total_encoded_size_in = 0 ;
_total_encoded_size_out = 0 ;
_last_bw_estimate_in_TS = time(NULL) ;
_last_bw_estimate_out_TS = time(NULL) ;
} }
bool VideoProcessor::processImage(const QImage& img,uint32_t size_hint,uint32_t& encoded_size) bool VideoProcessor::processImage(const QImage& img,uint32_t size_hint)
{ {
VideoCodec *codec ; VideoCodec *codec ;
@ -52,16 +62,29 @@ bool VideoProcessor::processImage(const QImage& img,uint32_t size_hint,uint32_t&
// std::cerr << "reducing to " << _frame_size.width() << " x " << _frame_size.height() << std::endl; // std::cerr << "reducing to " << _frame_size.width() << " x " << _frame_size.height() << std::endl;
encoded_size = 0 ;
if(codec) if(codec)
{ {
RsVOIPDataChunk chunk ; RsVOIPDataChunk chunk ;
if(codec->encodeData(img.scaled(_encoded_frame_size,Qt::IgnoreAspectRatio,Qt::SmoothTransformation),size_hint,chunk) && chunk.size > 0) if(codec->encodeData(img.scaled(_encoded_frame_size,Qt::IgnoreAspectRatio,Qt::SmoothTransformation),size_hint,chunk) && chunk.size > 0)
{ {
encoded_size = chunk.size ;
_encoded_out_queue.push_back(chunk) ; _encoded_out_queue.push_back(chunk) ;
_total_encoded_size_out += chunk.size ;
}
time_t now = time(NULL) ;
if(now > _last_bw_estimate_out_TS)
{
_estimated_bandwidth_out = uint32_t(0.75*_estimated_bandwidth_out + 0.25 * (_total_encoded_size_out / (float)(now - _last_bw_estimate_out_TS))) ;
_total_encoded_size_out = 0 ;
_last_bw_estimate_out_TS = now ;
#ifdef DEBUG_VIDEO_OUTPUT_DEVICE
std::cerr << "new bw estimate: " << _estimated_bw << std::endl;
#endif
} }
return true ; return true ;
@ -134,6 +157,21 @@ void VideoProcessor::receiveEncodedData(const RsVOIPDataChunk& chunk)
return ; return ;
} }
_total_encoded_size_in += chunk.size ;
time_t now = time(NULL) ;
if(now > _last_bw_estimate_in_TS)
{
_estimated_bandwidth_in = uint32_t(0.75*_estimated_bandwidth_in + 0.25 * (_total_encoded_size_in / (float)(now - _last_bw_estimate_in_TS))) ;
_total_encoded_size_in = 0 ;
_last_bw_estimate_in_TS = now ;
#ifdef DEBUG_VIDEO_OUTPUT_DEVICE
std::cerr << "new bw estimate (in): " << _estimated_bandwidth_in << std::endl;
#endif
}
if(!codec->decodeData(chunk,img)) if(!codec->decodeData(chunk,img))
{ {
std::cerr << "No image decoded. Probably in the middle of something..." << std::endl; std::cerr << "No image decoded. Probably in the middle of something..." << std::endl;
@ -144,9 +182,10 @@ void VideoProcessor::receiveEncodedData(const RsVOIPDataChunk& chunk)
_decoded_output_device->showFrame(img) ; _decoded_output_device->showFrame(img) ;
} }
void VideoProcessor::setMaximumFrameRate(uint32_t bytes_per_sec) void VideoProcessor::setMaximumBandwidth(uint32_t bytes_per_sec)
{ {
std::cerr << "Video Encoder: maximum frame rate is set to " << bytes_per_sec << " Bps" << std::endl; std::cerr << "Video Encoder: maximum frame rate is set to " << bytes_per_sec << " Bps" << std::endl;
_target_bandwidth_out = bytes_per_sec ;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////

View file

@ -117,7 +117,7 @@ class VideoProcessor
// returns the current (measured) frame rate in bytes per second. // returns the current (measured) frame rate in bytes per second.
// //
uint32_t currentDecodingFrameRate() const; uint32_t currentBandwidthIn() const { return _estimated_bandwidth_in ; }
private: private:
QVideoOutputDevice *_decoded_output_device ; QVideoOutputDevice *_decoded_output_device ;
@ -130,15 +130,19 @@ class VideoProcessor
public: public:
// Takes the next image to be encoded. // Takes the next image to be encoded.
// //
bool processImage(const QImage& Image, uint32_t size_hint, uint32_t &encoded_size) ; bool processImage(const QImage& Image, uint32_t size_hint) ;
bool encodedPacketReady() const { return !_encoded_out_queue.empty() ; } bool encodedPacketReady() const { return !_encoded_out_queue.empty() ; }
bool nextEncodedPacket(RsVOIPDataChunk& ) ; bool nextEncodedPacket(RsVOIPDataChunk& ) ;
// Used to tweak the compression ratio so that the video can stream ok. // Used to tweak the compression ratio so that the video can stream ok.
// //
void setMaximumFrameRate(uint32_t bytes_per_second) ; void setMaximumBandwidth(uint32_t bytes_per_second) ;
void setInternalFrameSize(QSize) ; void setInternalFrameSize(QSize) ;
// returns the current encoding frame rate in bytes per second.
//
uint32_t currentBandwidthOut() const { return _estimated_bandwidth_out ; }
protected: protected:
std::list<RsVOIPDataChunk> _encoded_out_queue ; std::list<RsVOIPDataChunk> _encoded_out_queue ;
QSize _encoded_frame_size ; QSize _encoded_frame_size ;
@ -152,5 +156,16 @@ class VideoProcessor
FFmpegVideo _mpeg_video_codec ; FFmpegVideo _mpeg_video_codec ;
uint16_t _encoding_current_codec ; uint16_t _encoding_current_codec ;
time_t _last_bw_estimate_in_TS;
time_t _last_bw_estimate_out_TS;
uint32_t _total_encoded_size_in ;
uint32_t _total_encoded_size_out ;
float _estimated_bandwidth_in ;
float _estimated_bandwidth_out ;
float _target_bandwidth_out ;
}; };