mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-06 21:58:57 -04:00
fixed encoding
This commit is contained in:
parent
1249423eff
commit
4522fe85cc
2 changed files with 60 additions and 44 deletions
|
@ -22,9 +22,10 @@ extern "C" {
|
||||||
#include <libavutil/mathematics.h>
|
#include <libavutil/mathematics.h>
|
||||||
#include <libavutil/samplefmt.h>
|
#include <libavutil/samplefmt.h>
|
||||||
}
|
}
|
||||||
|
#define DEBUG_MPEG_VIDEO 1
|
||||||
|
|
||||||
VideoProcessor::VideoProcessor()
|
VideoProcessor::VideoProcessor()
|
||||||
:_encoded_frame_size(128,128)
|
:_encoded_frame_size(176,144)
|
||||||
{
|
{
|
||||||
_decoded_output_device = NULL ;
|
_decoded_output_device = NULL ;
|
||||||
//_encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO;
|
//_encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO;
|
||||||
|
@ -135,14 +136,14 @@ void VideoProcessor::receiveEncodedData(const RsVOIPDataChunk& chunk)
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
return ;
|
// return ;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if(_decoded_output_device)
|
// if(_decoded_output_device)
|
||||||
_decoded_output_device->showFrame(img) ;
|
// _decoded_output_device->showFrame(img) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoProcessor::setMaximumFrameRate(uint32_t bytes_per_sec)
|
void VideoProcessor::setMaximumFrameRate(uint32_t bytes_per_sec)
|
||||||
|
@ -513,8 +514,8 @@ FFmpegVideo::FFmpegVideo()
|
||||||
/* put sample parameters */
|
/* put sample parameters */
|
||||||
encoding_context->bit_rate = 400000;
|
encoding_context->bit_rate = 400000;
|
||||||
/* resolution must be a multiple of two */
|
/* resolution must be a multiple of two */
|
||||||
encoding_context->width = 352;
|
encoding_context->width = 176;
|
||||||
encoding_context->height = 288;
|
encoding_context->height = 144;
|
||||||
/* frames per second */
|
/* frames per second */
|
||||||
encoding_context->time_base = (AVRational){1,25};
|
encoding_context->time_base = (AVRational){1,25};
|
||||||
/* emit one intra frame every ten frames
|
/* emit one intra frame every ten frames
|
||||||
|
@ -560,12 +561,21 @@ FFmpegVideo::FFmpegVideo()
|
||||||
throw("AV codec not found for codec id ") ;
|
throw("AV codec not found for codec id ") ;
|
||||||
|
|
||||||
decoding_context = avcodec_alloc_context3(decoding_codec);
|
decoding_context = avcodec_alloc_context3(decoding_codec);
|
||||||
|
decoding_context->width = encoding_context->width;
|
||||||
|
decoding_context->height = encoding_context->height;
|
||||||
|
decoding_context->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||||
|
|
||||||
// if (decoding_codec->capabilities & AV_CODEC_CAP_TRUNCATED)
|
// if (decoding_codec->capabilities & AV_CODEC_CAP_TRUNCATED)
|
||||||
// decoding_context->flags |= AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames
|
// decoding_context->flags |= AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames
|
||||||
|
|
||||||
if(avcodec_open2(decoding_context,decoding_codec,NULL) < 0)
|
if(avcodec_open2(decoding_context,decoding_codec,NULL) < 0)
|
||||||
throw("AV codec open action failed! ") ;
|
throw("AV codec open action failed! ") ;
|
||||||
|
|
||||||
|
// debug
|
||||||
|
#ifdef DEBUG_MPEG_VIDEO
|
||||||
|
std::cerr << "Dumping captured data to file tmpvideo.mpg" << std::endl;
|
||||||
|
encoding_debug_file = fopen("tmpvideo.mpg","w") ;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FFmpegVideo::~FFmpegVideo()
|
FFmpegVideo::~FFmpegVideo()
|
||||||
|
@ -601,19 +611,19 @@ bool FFmpegVideo::encodeData(const QImage& image,uint32_t size_hint,RsVOIPDataCh
|
||||||
for (int y = 0; y < encoding_context->height; y++)
|
for (int y = 0; y < encoding_context->height; y++)
|
||||||
for (int x = 0; x < encoding_context->width; x++)
|
for (int x = 0; x < encoding_context->width; x++)
|
||||||
{
|
{
|
||||||
QRgb pix = image.pixel(QPoint(x,y)) ;
|
QRgb pix = input.pixel(QPoint(x,y)) ;
|
||||||
|
|
||||||
register int R = (pix >> 16) & 0xff ;
|
register int R = (pix >> 16) & 0xff ;
|
||||||
register int G = (pix >> 8) & 0xff ;
|
register int G = (pix >> 8) & 0xff ;
|
||||||
register int B = (pix >> 0) & 0xff ;
|
register int B = (pix >> 0) & 0xff ;
|
||||||
|
|
||||||
register int y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16 ;
|
int Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16 ;
|
||||||
register int u = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 ;
|
int U = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 ;
|
||||||
register int v = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128 ;
|
int V = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128 ;
|
||||||
|
|
||||||
encoding_frame_buffer->data[0][y * encoding_frame_buffer->linesize[0] + x] = std::min(255,std::max(0,y)); // Y
|
encoding_frame_buffer->data[0][y * encoding_frame_buffer->linesize[0] + x] = std::min(255,std::max(0,Y)); // Y
|
||||||
encoding_frame_buffer->data[0][y * encoding_frame_buffer->linesize[0] + x] = std::min(255,std::max(0,u));// Cr
|
encoding_frame_buffer->data[1][y * encoding_frame_buffer->linesize[1] + x] = std::min(255,std::max(0,U));// Cr
|
||||||
encoding_frame_buffer->data[0][y * encoding_frame_buffer->linesize[0] + x] = std::min(255,std::max(0,v));// Cb
|
encoding_frame_buffer->data[2][y * encoding_frame_buffer->linesize[2] + x] = std::min(255,std::max(0,V));// Cb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -654,6 +664,10 @@ bool FFmpegVideo::encodeData(const QImage& image,uint32_t size_hint,RsVOIPDataCh
|
||||||
voip_chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ;
|
voip_chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ;
|
||||||
|
|
||||||
std::cerr << "Output : " << pkt.size << " bytes." << std::endl;
|
std::cerr << "Output : " << pkt.size << " bytes." << std::endl;
|
||||||
|
#ifdef DEBUG_MPEG_VIDEO
|
||||||
|
fwrite(pkt.data,1,pkt.size,encoding_debug_file) ;
|
||||||
|
fflush(encoding_debug_file) ;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -670,37 +684,37 @@ 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)
|
||||||
{
|
{
|
||||||
AVPacket pkt ;
|
AVPacket pkt ;
|
||||||
|
|
||||||
av_init_packet(&pkt);
|
|
||||||
|
|
||||||
pkt.data = (unsigned char *)memalign(16,chunk.size + FF_INPUT_BUFFER_PADDING_SIZE) ;
|
|
||||||
memset(pkt.data,0,chunk.size + FF_INPUT_BUFFER_PADDING_SIZE) ;
|
|
||||||
memcpy(pkt.data,&static_cast<unsigned char*>(chunk.data)[HEADER_SIZE],chunk.size - HEADER_SIZE) ;
|
|
||||||
|
|
||||||
pkt.size = chunk.size - HEADER_SIZE;
|
|
||||||
|
|
||||||
int got_frame = 0 ;
|
av_init_packet(&pkt);
|
||||||
int len = avcodec_decode_video2(decoding_context,decoding_frame_buffer,&got_frame,&pkt) ;
|
|
||||||
|
pkt.data = (unsigned char *)memalign(32,chunk.size + FF_INPUT_BUFFER_PADDING_SIZE) ;
|
||||||
if(!got_frame)
|
memset(pkt.data,0,chunk.size + FF_INPUT_BUFFER_PADDING_SIZE) ;
|
||||||
return false;
|
memcpy(pkt.data,&static_cast<unsigned char*>(chunk.data)[HEADER_SIZE],chunk.size - HEADER_SIZE) ;
|
||||||
|
|
||||||
image = QImage(QSize(decoding_frame_buffer->width,decoding_frame_buffer->height),QImage::Format_ARGB32) ;
|
pkt.size = chunk.size - HEADER_SIZE;
|
||||||
|
|
||||||
std::cerr << "Decoding frame. Size=" << image.width() << "x" << image.height() << std::endl;
|
int got_frame = 0 ;
|
||||||
|
int len = avcodec_decode_video2(decoding_context,decoding_frame_buffer,&got_frame,&pkt) ;
|
||||||
for (int y = 0; y < decoding_frame_buffer->height; y++)
|
|
||||||
|
if(!got_frame)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
image = QImage(QSize(decoding_frame_buffer->width,decoding_frame_buffer->height),QImage::Format_ARGB32) ;
|
||||||
|
|
||||||
|
std::cerr << "Decoding frame. Size=" << image.width() << "x" << image.height() << std::endl;
|
||||||
|
|
||||||
|
for (int y = 0; y < decoding_frame_buffer->height; y++)
|
||||||
for (int x = 0; x < decoding_frame_buffer->width; x++)
|
for (int x = 0; x < decoding_frame_buffer->width; x++)
|
||||||
{
|
{
|
||||||
int Y = decoding_frame_buffer->data[0][y * decoding_frame_buffer->linesize[0] + x] ;
|
int Y = decoding_frame_buffer->data[0][y * decoding_frame_buffer->linesize[0] + x] ;
|
||||||
int U = decoding_frame_buffer->data[1][y * decoding_frame_buffer->linesize[0] + x] ;
|
int U = decoding_frame_buffer->data[1][y * decoding_frame_buffer->linesize[1] + x] ;
|
||||||
int V = decoding_frame_buffer->data[2][y * decoding_frame_buffer->linesize[0] + x] ;
|
int V = decoding_frame_buffer->data[2][y * decoding_frame_buffer->linesize[2] + x] ;
|
||||||
|
|
||||||
|
int R = 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)))) ;
|
||||||
|
|
||||||
register int R = std::min(255,std::max(0,(int)(1.164*(Y - 16) + 1.596*(V - 128)))) ;
|
|
||||||
register int G = std::min(255,std::max(0,(int)(1.164*(Y - 16) - 0.813*(V - 128) - 0.391*(U - 128)))) ;
|
|
||||||
register int B = 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)) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,8 @@ private:
|
||||||
AVFrame *encoding_frame_buffer ;
|
AVFrame *encoding_frame_buffer ;
|
||||||
AVFrame *decoding_frame_buffer ;
|
AVFrame *decoding_frame_buffer ;
|
||||||
uint64_t encoding_frame_count ;
|
uint64_t encoding_frame_count ;
|
||||||
|
|
||||||
|
FILE *encoding_debug_file ;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class decodes video from a stream. It keeps a queue of
|
// This class decodes video from a stream. It keeps a queue of
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue