mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-06 13:48:59 -04:00
added variable bitrate and attempt to control it.
This commit is contained in:
parent
da69db39d6
commit
68918bf9c1
4 changed files with 47 additions and 17 deletions
|
@ -412,7 +412,7 @@
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<double>5.000000000000000</double>
|
<double>2.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>200.000000000000000</double>
|
<double>200.000000000000000</double>
|
||||||
|
|
|
@ -77,7 +77,7 @@ void QVideoInputDevice::grabFrame()
|
||||||
|
|
||||||
if(_video_processor != NULL)
|
if(_video_processor != NULL)
|
||||||
{
|
{
|
||||||
_video_processor->processImage(image,0) ;
|
_video_processor->processImage(image) ;
|
||||||
|
|
||||||
emit networkPacketReady() ;
|
emit networkPacketReady() ;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ VideoProcessor::VideoProcessor()
|
||||||
|
|
||||||
_estimated_bandwidth_in = 0 ;
|
_estimated_bandwidth_in = 0 ;
|
||||||
_estimated_bandwidth_out = 0 ;
|
_estimated_bandwidth_out = 0 ;
|
||||||
_target_bandwidth_out = 0 ;
|
_target_bandwidth_out = 30*1024 ; // 30 KB/s
|
||||||
|
|
||||||
_total_encoded_size_in = 0 ;
|
_total_encoded_size_in = 0 ;
|
||||||
_total_encoded_size_out = 0 ;
|
_total_encoded_size_out = 0 ;
|
||||||
|
@ -58,7 +58,7 @@ VideoProcessor::~VideoProcessor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VideoProcessor::processImage(const QImage& img,uint32_t size_hint)
|
bool VideoProcessor::processImage(const QImage& img)
|
||||||
{
|
{
|
||||||
VideoCodec *codec ;
|
VideoCodec *codec ;
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ bool VideoProcessor::processImage(const QImage& img,uint32_t size_hint)
|
||||||
{
|
{
|
||||||
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),_target_bandwidth_out,chunk) && chunk.size > 0)
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(vpMtx) ;
|
RS_STACK_MUTEX(vpMtx) ;
|
||||||
_encoded_out_queue.push_back(chunk) ;
|
_encoded_out_queue.push_back(chunk) ;
|
||||||
|
@ -318,7 +318,7 @@ bool JPEGVideo::encodeData(const QImage& image,uint32_t /* size_hint */,RsVOIPDa
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool WaveletVideo::encodeData(const QImage& image,uint32_t size_hint,RsVOIPDataChunk& voip_chunk)
|
bool WaveletVideo::encodeData(const QImage& image, uint32_t target_encoding_bitrate, RsVOIPDataChunk& voip_chunk)
|
||||||
{
|
{
|
||||||
static const int WAVELET_IMG_SIZE = 128 ;
|
static const int WAVELET_IMG_SIZE = 128 ;
|
||||||
static const float W_THRESHOLD = 0.005 ; // low quality
|
static const float W_THRESHOLD = 0.005 ; // low quality
|
||||||
|
@ -568,7 +568,28 @@ FFmpegVideo::FFmpegVideo()
|
||||||
if (!encoding_context) throw std::runtime_error("AV: Could not allocate video codec encoding context");
|
if (!encoding_context) throw std::runtime_error("AV: Could not allocate video codec encoding context");
|
||||||
|
|
||||||
/* put sample parameters */
|
/* put sample parameters */
|
||||||
encoding_context->bit_rate = 200000;
|
encoding_context->bit_rate = 30*1024 ; // default bitrate is 30KB/s
|
||||||
|
encoding_context->bit_rate_tolerance = encoding_context->bit_rate ;
|
||||||
|
encoding_context->rc_min_rate = 0;
|
||||||
|
encoding_context->rc_max_rate = 81920;
|
||||||
|
encoding_context->rc_buffer_size = 1024*1024;
|
||||||
|
encoding_context->flags |= CODEC_FLAG_PSNR;
|
||||||
|
//encoding_context->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_P4X4 | X264_PART_B8X8;
|
||||||
|
//encoding_context->crf = 0.0f;
|
||||||
|
//encoding_context->cqp = 26;
|
||||||
|
encoding_context->i_quant_factor = 0.769f;
|
||||||
|
encoding_context->b_quant_factor = 1.4f;
|
||||||
|
encoding_context->rc_initial_buffer_occupancy = (int) ( 0.9 * encoding_context->rc_buffer_size);
|
||||||
|
encoding_context->rc_max_available_vbv_use = 0.9;
|
||||||
|
encoding_context->rc_min_vbv_overflow_use = 0.1;
|
||||||
|
encoding_context->time_base.num = 1;
|
||||||
|
encoding_context->time_base.den = 15;//framesPerSecond;
|
||||||
|
//encoding_context->me_method = ME_HEX;
|
||||||
|
encoding_context->qmin = 10;
|
||||||
|
encoding_context->qmax = 51;
|
||||||
|
encoding_context->max_qdiff = 4;
|
||||||
|
encoding_context->max_b_frames = 4;
|
||||||
|
|
||||||
/* resolution must be a multiple of two */
|
/* resolution must be a multiple of two */
|
||||||
encoding_context->width = 352;//176;
|
encoding_context->width = 352;//176;
|
||||||
encoding_context->height = 288;//144;
|
encoding_context->height = 288;//144;
|
||||||
|
@ -580,10 +601,9 @@ FFmpegVideo::FFmpegVideo()
|
||||||
* then gop_size is ignored and the output of encoder
|
* then gop_size is ignored and the output of encoder
|
||||||
* will always be I frame irrespective to gop_size
|
* will always be I frame irrespective to gop_size
|
||||||
*/
|
*/
|
||||||
encoding_context->gop_size = 10;
|
encoding_context->gop_size = 250;
|
||||||
encoding_context->max_b_frames = 1;
|
encoding_context->max_b_frames = 1;
|
||||||
//context->pix_fmt = AV_PIX_FMT_RGB24;
|
encoding_context->pix_fmt = AV_PIX_FMT_YUV420P; //context->pix_fmt = AV_PIX_FMT_RGB24;
|
||||||
encoding_context->pix_fmt = AV_PIX_FMT_YUV420P;
|
|
||||||
|
|
||||||
if (codec_id == AV_CODEC_ID_H264)
|
if (codec_id == AV_CODEC_ID_H264)
|
||||||
av_opt_set(encoding_context->priv_data, "preset", "slow", 0);
|
av_opt_set(encoding_context->priv_data, "preset", "slow", 0);
|
||||||
|
@ -664,13 +684,22 @@ FFmpegVideo::~FFmpegVideo()
|
||||||
free(decoding_frame_buffer);
|
free(decoding_frame_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_FFMPEG_ENCODING_BITRATE 81920
|
||||||
|
|
||||||
bool FFmpegVideo::encodeData(const QImage& image,uint32_t size_hint,RsVOIPDataChunk& voip_chunk)
|
bool FFmpegVideo::encodeData(const QImage& image, uint32_t target_encoding_bitrate, RsVOIPDataChunk& voip_chunk)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_MPEG_VIDEO
|
#ifdef DEBUG_MPEG_VIDEO
|
||||||
std::cerr << "Encoding frame of size " << image.width() << "x" << image.height() << ", resized to " << encoding_frame_buffer->width << "x" << encoding_frame_buffer->height << " : ";
|
std::cerr << "Encoding frame of size " << image.width() << "x" << image.height() << ", resized to " << encoding_frame_buffer->width << "x" << encoding_frame_buffer->height << " : ";
|
||||||
#endif
|
#endif
|
||||||
QImage input ;
|
QImage input ;
|
||||||
|
|
||||||
|
if(target_encoding_bitrate > MAX_FFMPEG_ENCODING_BITRATE)
|
||||||
|
{
|
||||||
|
std::cerr << "Max encodign bitrate eexceeded. Capping to " << MAX_FFMPEG_ENCODING_BITRATE << std::endl;
|
||||||
|
target_encoding_bitrate = MAX_FFMPEG_ENCODING_BITRATE ;
|
||||||
|
}
|
||||||
|
encoding_context->bit_rate = target_encoding_bitrate;
|
||||||
|
encoding_context->bit_rate_tolerance = target_encoding_bitrate;
|
||||||
|
|
||||||
if(image.width() != encoding_frame_buffer->width || image.height() != encoding_frame_buffer->height)
|
if(image.width() != encoding_frame_buffer->width || image.height() != encoding_frame_buffer->height)
|
||||||
input = image.scaled(QSize(encoding_frame_buffer->width,encoding_frame_buffer->height),Qt::IgnoreAspectRatio,Qt::SmoothTransformation) ;
|
input = image.scaled(QSize(encoding_frame_buffer->width,encoding_frame_buffer->height),Qt::IgnoreAspectRatio,Qt::SmoothTransformation) ;
|
||||||
|
@ -775,6 +804,7 @@ bool FFmpegVideo::encodeData(const QImage& image,uint32_t size_hint,RsVOIPDataCh
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FFmpegVideo::decodeData(const RsVOIPDataChunk& chunk,QImage& image)
|
bool FFmpegVideo::decodeData(const RsVOIPDataChunk& chunk,QImage& image)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_MPEG_VIDEO
|
#ifdef DEBUG_MPEG_VIDEO
|
||||||
|
@ -843,9 +873,9 @@ bool FFmpegVideo::decodeData(const RsVOIPDataChunk& chunk,QImage& image)
|
||||||
int U = decoding_frame_buffer->data[1][(y/2) * decoding_frame_buffer->linesize[1] + x/2] ;
|
int U = decoding_frame_buffer->data[1][(y/2) * decoding_frame_buffer->linesize[1] + x/2] ;
|
||||||
int V = decoding_frame_buffer->data[2][(y/2) * decoding_frame_buffer->linesize[2] + x/2] ;
|
int V = decoding_frame_buffer->data[2][(y/2) * decoding_frame_buffer->linesize[2] + x/2] ;
|
||||||
|
|
||||||
int R = std::min(255,std::max(0,(int)(1.164*(Y - 16) + 1.596*(V - 128)))) ;
|
int B = std::min(255,std::max(0,(int)(1.164*(Y - 16) + 1.596*(V - 128)))) ;
|
||||||
int G = std::min(255,std::max(0,(int)(1.164*(Y - 16) - 0.813*(V - 128) - 0.391*(U - 128)))) ;
|
int G = std::min(255,std::max(0,(int)(1.164*(Y - 16) - 0.813*(V - 128) - 0.391*(U - 128)))) ;
|
||||||
int B = std::min(255,std::max(0,(int)(1.164*(Y - 16) + 2.018*(U - 128)))) ;
|
int R = std::min(255,std::max(0,(int)(1.164*(Y - 16) + 2.018*(U - 128)))) ;
|
||||||
|
|
||||||
image.setPixel(QPoint(x,y),QRgb( 0xff000000 + (R << 16) + (G << 8) + B)) ;
|
image.setPixel(QPoint(x,y),QRgb( 0xff000000 + (R << 16) + (G << 8) + B)) ;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ public:
|
||||||
JPEGVideo() ;
|
JPEGVideo() ;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool encodeData(const QImage& Image, uint32_t size_hint, RsVOIPDataChunk& chunk) ;
|
virtual bool encodeData(const QImage& Image, uint32_t target_encoding_bitrate, RsVOIPDataChunk& chunk) ;
|
||||||
virtual bool decodeData(const RsVOIPDataChunk& chunk,QImage& image) ;
|
virtual bool decodeData(const RsVOIPDataChunk& chunk,QImage& image) ;
|
||||||
|
|
||||||
static const uint32_t JPEG_VIDEO_FLAGS_DIFFERENTIAL_FRAME = 0x0001 ;
|
static const uint32_t JPEG_VIDEO_FLAGS_DIFFERENTIAL_FRAME = 0x0001 ;
|
||||||
|
@ -47,7 +47,7 @@ public:
|
||||||
WaveletVideo() {}
|
WaveletVideo() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool encodeData(const QImage& Image, uint32_t size_hint, RsVOIPDataChunk& chunk) ;
|
virtual bool encodeData(const QImage& Image, uint32_t target_encoding_bitrate, RsVOIPDataChunk& chunk) ;
|
||||||
virtual bool decodeData(const RsVOIPDataChunk& chunk,QImage& image) ;
|
virtual bool decodeData(const RsVOIPDataChunk& chunk,QImage& image) ;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ public:
|
||||||
~FFmpegVideo() ;
|
~FFmpegVideo() ;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool encodeData(const QImage& Image, uint32_t size_hint, RsVOIPDataChunk& chunk) ;
|
virtual bool encodeData(const QImage& Image, uint32_t target_encoding_bitrate, RsVOIPDataChunk& chunk) ;
|
||||||
virtual bool decodeData(const RsVOIPDataChunk& chunk,QImage& image) ;
|
virtual bool decodeData(const RsVOIPDataChunk& chunk,QImage& image) ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -130,7 +130,7 @@ 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) ;
|
bool processImage(const QImage& Image) ;
|
||||||
bool encodedPacketReady() const { return !_encoded_out_queue.empty() ; }
|
bool encodedPacketReady() const { return !_encoded_out_queue.empty() ; }
|
||||||
bool nextEncodedPacket(RsVOIPDataChunk& ) ;
|
bool nextEncodedPacket(RsVOIPDataChunk& ) ;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue