Introduced double buffering of video stream to avoid tearing of image.
Removed swapBufers call and image y inversion.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "FFmpegDecoderVideo.hpp"
|
||||
|
||||
#include <osg/Notify>
|
||||
#include <osg/Timer>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string.h>
|
||||
@@ -16,6 +17,7 @@ FFmpegDecoderVideo::FFmpegDecoderVideo(PacketQueue & packets, FFmpegClocks & clo
|
||||
m_packet_data(0),
|
||||
m_bytes_remaining(0),
|
||||
m_packet_pts(AV_NOPTS_VALUE),
|
||||
m_writeBuffer(0),
|
||||
m_user_data(0),
|
||||
m_publish_func(0),
|
||||
m_exit(false)
|
||||
@@ -83,11 +85,11 @@ void FFmpegDecoderVideo::open(AVStream * const stream)
|
||||
|
||||
// Allocate converted RGB frame
|
||||
m_frame_rgba.reset(avcodec_alloc_frame());
|
||||
m_buffer_rgba.resize(avpicture_get_size(PIX_FMT_RGB32, width(), height()));
|
||||
m_buffer_rgba_public.resize(m_buffer_rgba.size());
|
||||
m_buffer_rgba[0].resize(avpicture_get_size(PIX_FMT_RGB32, width(), height()));
|
||||
m_buffer_rgba[1].resize(m_buffer_rgba[0].size());
|
||||
|
||||
// Assign appropriate parts of the buffer to image planes in m_frame_rgba
|
||||
avpicture_fill((AVPicture *) m_frame_rgba.get(), &m_buffer_rgba[0], PIX_FMT_RGB32, width(), height());
|
||||
avpicture_fill((AVPicture *) (m_frame_rgba).get(), &(m_buffer_rgba[0])[0], PIX_FMT_RGB32, width(), height());
|
||||
|
||||
// Override get_buffer()/release_buffer() from codec context in order to retrieve the PTS of each frame.
|
||||
m_context->opaque = this;
|
||||
@@ -215,25 +217,33 @@ void FFmpegDecoderVideo::findAspectRatio()
|
||||
int FFmpegDecoderVideo::convert(AVPicture *dst, int dst_pix_fmt, const AVPicture *src,
|
||||
int src_pix_fmt, int src_width, int src_height)
|
||||
{
|
||||
osg::Timer_t startTick = osg::Timer::instance()->tick();
|
||||
#ifdef USE_SWSCALE
|
||||
if (m_swscale_ctx==0)
|
||||
{
|
||||
m_swscale_ctx = sws_getContext(src_width, src_height, src_pix_fmt,
|
||||
src_width, src_height, dst_pix_fmt,
|
||||
SWS_BILINEAR, NULL, NULL, NULL);
|
||||
/*SWS_BILINEAR*/ SWS_BICUBIC, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Using sws_scale"<<std::endl;
|
||||
|
||||
return sws_scale(m_swscale_ctx,
|
||||
src->data, src->linesize, 0, src_height,
|
||||
dst->data, dst->linesize);
|
||||
osg::notify(osg::NOTICE)<<"Using sws_scale ";
|
||||
|
||||
int result = sws_scale(m_swscale_ctx,
|
||||
src->data, src->linesize, 0, src_height,
|
||||
dst->data, dst->linesize);
|
||||
#else
|
||||
osg::notify(osg::NOTICE)<<"Using img_convert"<<std::endl;
|
||||
|
||||
return img_convert(dst, dst_pix_fmt, src,
|
||||
src_pix_fmt, src_width, src_height);
|
||||
osg::notify(osg::NOTICE)<<"Using img_convert ";
|
||||
|
||||
int result = img_convert(dst, dst_pix_fmt, src,
|
||||
src_pix_fmt, src_width, src_height);
|
||||
|
||||
#endif
|
||||
osg::Timer_t endTick = osg::Timer::instance()->tick();
|
||||
osg::notify(osg::NOTICE)<<" time = "<<osg::Timer::instance()->delta_m(startTick,endTick)<<"ms"<<std::endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -246,10 +256,15 @@ void FFmpegDecoderVideo::publishFrame(const double delay)
|
||||
// If the display delay is too small, we better skip the frame.
|
||||
if (delay < -0.010)
|
||||
return;
|
||||
|
||||
|
||||
const AVPicture * const src = (const AVPicture *) m_frame.get();
|
||||
AVPicture * const dst = (AVPicture *) m_frame_rgba.get();
|
||||
|
||||
osg::Timer_t startTick = osg::Timer::instance()->tick();
|
||||
|
||||
// Assign appropriate parts of the buffer to image planes in m_frame_rgba
|
||||
avpicture_fill((AVPicture *) (m_frame_rgba).get(), &(m_buffer_rgba[m_writeBuffer])[0], PIX_FMT_RGB32, width(), height());
|
||||
|
||||
// Convert YUVA420p (i.e. YUV420p plus alpha channel) using our own routine
|
||||
|
||||
if (m_context->pix_fmt == PIX_FMT_YUVA420P)
|
||||
@@ -257,8 +272,13 @@ void FFmpegDecoderVideo::publishFrame(const double delay)
|
||||
else
|
||||
convert(dst, PIX_FMT_RGB32, src, m_context->pix_fmt, width(), height());
|
||||
|
||||
|
||||
// Flip and swap buffer
|
||||
swapBuffers();
|
||||
// swapBuffers();
|
||||
|
||||
|
||||
osg::Timer_t endTick = osg::Timer::instance()->tick();
|
||||
osg::notify(osg::NOTICE)<<" time of swapBuffers = "<<osg::Timer::instance()->delta_m(startTick,endTick)<<"ms"<<std::endl;
|
||||
|
||||
// Wait 'delay' seconds before publishing the picture.
|
||||
int i_delay = static_cast<int>(delay * 1000000 + 0.5);
|
||||
@@ -276,6 +296,8 @@ void FFmpegDecoderVideo::publishFrame(const double delay)
|
||||
i_delay -= micro_delay;
|
||||
}
|
||||
|
||||
m_writeBuffer = 1-m_writeBuffer;
|
||||
|
||||
m_publish_func(* this, m_user_data);
|
||||
}
|
||||
|
||||
@@ -284,7 +306,7 @@ void FFmpegDecoderVideo::publishFrame(const double delay)
|
||||
void FFmpegDecoderVideo::swapBuffers()
|
||||
{
|
||||
for (int h = 0; h < height(); ++h)
|
||||
memcpy(&m_buffer_rgba_public[(height() - h - 1) * width() * 4], &m_buffer_rgba[h * width() * 4], width() * 4);
|
||||
memcpy(&(m_buffer_rgba[1-m_writeBuffer])[(height() - h - 1) * width() * 4], &(m_buffer_rgba[m_writeBuffer])[h * width() * 4], width() * 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user