mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-27 08:29:26 -05:00
fixed bug in creating input image when encoding video
This commit is contained in:
parent
0bb5a74099
commit
024999ed67
@ -58,14 +58,11 @@ bool VideoProcessor::processImage(const QImage& img,uint32_t size_hint,uint32_t&
|
|||||||
{
|
{
|
||||||
RsVOIPDataChunk chunk ;
|
RsVOIPDataChunk chunk ;
|
||||||
|
|
||||||
codec->encodeData(img.scaled(_encoded_frame_size,Qt::IgnoreAspectRatio,Qt::SmoothTransformation),size_hint,chunk) ;
|
if(codec->encodeData(img.scaled(_encoded_frame_size,Qt::IgnoreAspectRatio,Qt::SmoothTransformation),size_hint,chunk) && chunk.size > 0)
|
||||||
|
{
|
||||||
encoded_size = chunk.size ;
|
encoded_size = chunk.size ;
|
||||||
|
_encoded_out_queue.push_back(chunk) ;
|
||||||
if(chunk.size == 0) // the codec might be buffering the frame for compression reasons
|
}
|
||||||
return true ;
|
|
||||||
|
|
||||||
_encoded_out_queue.push_back(chunk) ;
|
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
@ -538,6 +535,9 @@ FFmpegVideo::FFmpegVideo()
|
|||||||
|
|
||||||
encoding_frame_buffer = avcodec_alloc_frame() ;//(AVFrame*)malloc(sizeof(AVFrame)) ;
|
encoding_frame_buffer = avcodec_alloc_frame() ;//(AVFrame*)malloc(sizeof(AVFrame)) ;
|
||||||
|
|
||||||
|
if(!encoding_frame_buffer)
|
||||||
|
throw std::runtime_error("AV: could not allocate frame buffer.") ;
|
||||||
|
|
||||||
encoding_frame_buffer->format = encoding_context->pix_fmt;
|
encoding_frame_buffer->format = encoding_context->pix_fmt;
|
||||||
encoding_frame_buffer->width = encoding_context->width;
|
encoding_frame_buffer->width = encoding_context->width;
|
||||||
encoding_frame_buffer->height = encoding_context->height;
|
encoding_frame_buffer->height = encoding_context->height;
|
||||||
@ -545,7 +545,8 @@ FFmpegVideo::FFmpegVideo()
|
|||||||
/* the image can be allocated by any means and av_image_alloc() is
|
/* the image can be allocated by any means and av_image_alloc() is
|
||||||
* just the most convenient way if av_malloc() is to be used */
|
* just the most convenient way if av_malloc() is to be used */
|
||||||
|
|
||||||
int ret = av_image_alloc(encoding_frame_buffer->data, encoding_frame_buffer->linesize, encoding_context->width, encoding_context->height, encoding_context->pix_fmt, 32);
|
int ret = av_image_alloc(encoding_frame_buffer->data, encoding_frame_buffer->linesize,
|
||||||
|
encoding_context->width, encoding_context->height, encoding_context->pix_fmt, 32);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
throw std::runtime_error("AV: Could not allocate raw picture buffer");
|
throw std::runtime_error("AV: Could not allocate raw picture buffer");
|
||||||
@ -575,6 +576,7 @@ FFmpegVideo::FFmpegVideo()
|
|||||||
throw("AV codec open action failed! ") ;
|
throw("AV codec open action failed! ") ;
|
||||||
|
|
||||||
decoding_frame_buffer = avcodec_alloc_frame() ;//(AVFrame*)malloc(sizeof(AVFrame)) ;
|
decoding_frame_buffer = avcodec_alloc_frame() ;//(AVFrame*)malloc(sizeof(AVFrame)) ;
|
||||||
|
|
||||||
//ret = av_image_alloc(decoding_frame_buffer->data, decoding_frame_buffer->linesize, decoding_context->width, decoding_context->height, decoding_context->pix_fmt, 32);
|
//ret = av_image_alloc(decoding_frame_buffer->data, decoding_frame_buffer->linesize, decoding_context->width, decoding_context->height, decoding_context->pix_fmt, 32);
|
||||||
|
|
||||||
//if (ret < 0)
|
//if (ret < 0)
|
||||||
@ -602,7 +604,7 @@ FFmpegVideo::~FFmpegVideo()
|
|||||||
|
|
||||||
bool FFmpegVideo::encodeData(const QImage& image,uint32_t size_hint,RsVOIPDataChunk& voip_chunk)
|
bool FFmpegVideo::encodeData(const QImage& image,uint32_t size_hint,RsVOIPDataChunk& voip_chunk)
|
||||||
{
|
{
|
||||||
std::cerr << "Encoding frame of size " << image.width() << "x" << image.height() << ", resized to " << encoding_frame_buffer->width << "x" << encoding_frame_buffer->height << std::endl;
|
std::cerr << "Encoding frame of size " << image.width() << "x" << image.height() << ", resized to " << encoding_frame_buffer->width << "x" << encoding_frame_buffer->height << std::endl;
|
||||||
QImage input ;
|
QImage input ;
|
||||||
|
|
||||||
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)
|
||||||
@ -612,20 +614,36 @@ bool FFmpegVideo::encodeData(const QImage& image,uint32_t size_hint,RsVOIPDataCh
|
|||||||
|
|
||||||
/* prepare a dummy image */
|
/* prepare a dummy image */
|
||||||
/* Y */
|
/* Y */
|
||||||
for (int y = 0; y < encoding_context->height; y++)
|
for (int y = 0; y < encoding_context->height/2; y++)
|
||||||
for (int x = 0; x < encoding_context->width; x++)
|
for (int x = 0; x < encoding_context->width/2; x++)
|
||||||
{
|
{
|
||||||
QRgb pix = input.pixel(QPoint(x,y)) ;
|
QRgb pix00 = input.pixel(QPoint(2*x+0,2*y+0)) ;
|
||||||
|
QRgb pix01 = input.pixel(QPoint(2*x+0,2*y+1)) ;
|
||||||
|
QRgb pix10 = input.pixel(QPoint(2*x+1,2*y+0)) ;
|
||||||
|
QRgb pix11 = input.pixel(QPoint(2*x+1,2*y+1)) ;
|
||||||
|
|
||||||
register int R = (pix >> 16) & 0xff ;
|
int R00 = (pix00 >> 16) & 0xff ; int G00 = (pix00 >> 8) & 0xff ; int B00 = (pix00 >> 0) & 0xff ;
|
||||||
register int G = (pix >> 8) & 0xff ;
|
int R01 = (pix01 >> 16) & 0xff ; int G01 = (pix01 >> 8) & 0xff ; int B01 = (pix01 >> 0) & 0xff ;
|
||||||
register int B = (pix >> 0) & 0xff ;
|
int R10 = (pix10 >> 16) & 0xff ; int G10 = (pix10 >> 8) & 0xff ; int B10 = (pix10 >> 0) & 0xff ;
|
||||||
|
int R11 = (pix11 >> 16) & 0xff ; int G11 = (pix11 >> 8) & 0xff ; int B11 = (pix11 >> 0) & 0xff ;
|
||||||
|
|
||||||
|
int Y00 = (0.257 * R00) + (0.504 * G00) + (0.098 * B00) + 16 ;
|
||||||
|
int Y01 = (0.257 * R01) + (0.504 * G01) + (0.098 * B01) + 16 ;
|
||||||
|
int Y10 = (0.257 * R10) + (0.504 * G10) + (0.098 * B10) + 16 ;
|
||||||
|
int Y11 = (0.257 * R11) + (0.504 * G11) + (0.098 * B11) + 16 ;
|
||||||
|
|
||||||
|
float R = 0.25*(R00+R01+R10+R11) ;
|
||||||
|
float G = 0.25*(G00+G01+G10+G11) ;
|
||||||
|
float B = 0.25*(B00+B01+B10+B11) ;
|
||||||
|
|
||||||
int Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16 ;
|
|
||||||
int U = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 ;
|
int U = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 ;
|
||||||
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][(2*y+0) * encoding_frame_buffer->linesize[0] + 2*x+0] = std::min(255,std::max(0,Y00)); // Y
|
||||||
|
encoding_frame_buffer->data[0][(2*y+0) * encoding_frame_buffer->linesize[0] + 2*x+1] = std::min(255,std::max(0,Y01)); // Y
|
||||||
|
encoding_frame_buffer->data[0][(2*y+1) * encoding_frame_buffer->linesize[0] + 2*x+0] = std::min(255,std::max(0,Y10)); // Y
|
||||||
|
encoding_frame_buffer->data[0][(2*y+1) * encoding_frame_buffer->linesize[0] + 2*x+1] = std::min(255,std::max(0,Y11)); // Y
|
||||||
|
|
||||||
encoding_frame_buffer->data[1][y * encoding_frame_buffer->linesize[1] + 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[2][y * encoding_frame_buffer->linesize[2] + 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
|
||||||
}
|
}
|
||||||
@ -658,27 +676,29 @@ bool FFmpegVideo::encodeData(const QImage& image,uint32_t size_hint,RsVOIPDataCh
|
|||||||
// } while(got_output) ;
|
// } while(got_output) ;
|
||||||
|
|
||||||
if(got_output)
|
if(got_output)
|
||||||
{
|
{
|
||||||
voip_chunk.data = malloc(pkt.size + HEADER_SIZE) ;
|
voip_chunk.data = malloc(pkt.size + HEADER_SIZE) ;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
|
||||||
((unsigned char *)voip_chunk.data)[0] = VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO & 0xff ;
|
((unsigned char *)voip_chunk.data)[0] = VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO & 0xff ;
|
||||||
((unsigned char *)voip_chunk.data)[1] = (VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO >> 8) & 0xff ;
|
((unsigned char *)voip_chunk.data)[1] = (VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO >> 8) & 0xff ;
|
||||||
((unsigned char *)voip_chunk.data)[2] = flags & 0xff ;
|
((unsigned char *)voip_chunk.data)[2] = flags & 0xff ;
|
||||||
((unsigned char *)voip_chunk.data)[3] = (flags >> 8) & 0xff ;
|
((unsigned char *)voip_chunk.data)[3] = (flags >> 8) & 0xff ;
|
||||||
|
|
||||||
memcpy(&((unsigned char*)voip_chunk.data)[HEADER_SIZE],pkt.data,pkt.size) ;
|
memcpy(&((unsigned char*)voip_chunk.data)[HEADER_SIZE],pkt.data,pkt.size) ;
|
||||||
|
|
||||||
voip_chunk.size = pkt.size + HEADER_SIZE;
|
voip_chunk.size = pkt.size + HEADER_SIZE;
|
||||||
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
|
#ifdef DEBUG_MPEG_VIDEO
|
||||||
fwrite(pkt.data,1,pkt.size,encoding_debug_file) ;
|
fwrite(pkt.data,1,pkt.size,encoding_debug_file) ;
|
||||||
fflush(encoding_debug_file) ;
|
fflush(encoding_debug_file) ;
|
||||||
#endif
|
#endif
|
||||||
av_free_packet(&pkt);
|
av_free_packet(&pkt);
|
||||||
}
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
voip_chunk.data = NULL;
|
voip_chunk.data = NULL;
|
||||||
@ -686,9 +706,9 @@ 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 << "No output produced." << std::endl;
|
std::cerr << "No output produced." << std::endl;
|
||||||
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
}
|
||||||
bool FFmpegVideo::decodeData(const RsVOIPDataChunk& chunk,QImage& image)
|
bool FFmpegVideo::decodeData(const RsVOIPDataChunk& chunk,QImage& image)
|
||||||
{
|
{
|
||||||
@ -713,6 +733,7 @@ bool FFmpegVideo::decodeData(const RsVOIPDataChunk& chunk,QImage& image)
|
|||||||
std::cerr << "Error decodign frame!" << std::endl;
|
std::cerr << "Error decodign frame!" << std::endl;
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
std::cerr << "Used " << len << " bytes out of " << pkt.size << ". got_frame = " << got_frame << std::endl;
|
||||||
if(!got_frame)
|
if(!got_frame)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user