added variable bitrate and attempt to control it.

This commit is contained in:
csoler 2015-08-29 21:48:58 -04:00
parent da69db39d6
commit 68918bf9c1
4 changed files with 47 additions and 17 deletions

View File

@ -412,7 +412,7 @@
<number>1</number>
</property>
<property name="minimum">
<double>5.000000000000000</double>
<double>2.000000000000000</double>
</property>
<property name="maximum">
<double>200.000000000000000</double>

View File

@ -77,7 +77,7 @@ void QVideoInputDevice::grabFrame()
if(_video_processor != NULL)
{
_video_processor->processImage(image,0) ;
_video_processor->processImage(image) ;
emit networkPacketReady() ;
}

View File

@ -36,7 +36,7 @@ VideoProcessor::VideoProcessor()
_estimated_bandwidth_in = 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_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 ;
@ -80,7 +80,7 @@ bool VideoProcessor::processImage(const QImage& img,uint32_t size_hint)
{
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) ;
_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 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");
/* 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 */
encoding_context->width = 352;//176;
encoding_context->height = 288;//144;
@ -580,10 +601,9 @@ FFmpegVideo::FFmpegVideo()
* then gop_size is ignored and the output of encoder
* 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;
//context->pix_fmt = AV_PIX_FMT_RGB24;
encoding_context->pix_fmt = AV_PIX_FMT_YUV420P;
encoding_context->pix_fmt = AV_PIX_FMT_YUV420P; //context->pix_fmt = AV_PIX_FMT_RGB24;
if (codec_id == AV_CODEC_ID_H264)
av_opt_set(encoding_context->priv_data, "preset", "slow", 0);
@ -664,13 +684,22 @@ FFmpegVideo::~FFmpegVideo()
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
std::cerr << "Encoding frame of size " << image.width() << "x" << image.height() << ", resized to " << encoding_frame_buffer->width << "x" << encoding_frame_buffer->height << " : ";
#endif
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)
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)
{
#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 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 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)) ;
}

View File

@ -29,7 +29,7 @@ public:
JPEGVideo() ;
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) ;
static const uint32_t JPEG_VIDEO_FLAGS_DIFFERENTIAL_FRAME = 0x0001 ;
@ -47,7 +47,7 @@ public:
WaveletVideo() {}
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) ;
private:
@ -73,7 +73,7 @@ public:
~FFmpegVideo() ;
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) ;
private:
@ -130,7 +130,7 @@ class VideoProcessor
public:
// 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 nextEncodedPacket(RsVOIPDataChunk& ) ;