diff --git a/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp b/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp index 915118ed9..4daca11de 100644 --- a/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp +++ b/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp @@ -1,6 +1,7 @@ #include "FFmpegDecoderVideo.hpp" #include +#include #include #include @@ -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"<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"<tick(); + osg::notify(osg::NOTICE)<<" time = "<delta_m(startTick,endTick)<<"ms"<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 = "<delta_m(startTick,endTick)<<"ms"<(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); } diff --git a/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.hpp b/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.hpp index 9607b335c..14a3d2c2d 100644 --- a/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.hpp +++ b/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.hpp @@ -107,8 +107,8 @@ private: FramePtr m_frame; FramePtr m_frame_rgba; - Buffer m_buffer_rgba; - Buffer m_buffer_rgba_public; + Buffer m_buffer_rgba[2]; + int m_writeBuffer; void * m_user_data; PublishFunc m_publish_func; @@ -175,7 +175,7 @@ inline double FFmpegDecoderVideo::frameRate() const inline const uint8_t * FFmpegDecoderVideo::image() const { - return &m_buffer_rgba_public[0]; + return &((m_buffer_rgba[1-m_writeBuffer])[0]); } diff --git a/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp b/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp index 24989c655..ca1d4977c 100644 --- a/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp +++ b/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp @@ -57,6 +57,8 @@ bool FFmpegImageStream::open(const std::string & filename) m_decoder->video_decoder().width(), m_decoder->video_decoder().height(), 1, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, const_cast(m_decoder->video_decoder().image()), NO_DELETE ); + + setOrigin(osg::Image::TOP_LEFT); m_decoder->video_decoder().setUserData(this); m_decoder->video_decoder().setPublishCallback(publishNewFrame); @@ -264,8 +266,15 @@ void FFmpegImageStream::publishNewFrame(const FFmpegDecoderVideo &, void * user_ { FFmpegImageStream * const this_ = reinterpret_cast(user_data); +#if 1 + this_->setImage( + this_->m_decoder->video_decoder().width(), this_->m_decoder->video_decoder().height(), 1, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, + const_cast(this_->m_decoder->video_decoder().image()), NO_DELETE + ); +#else /** \bug If viewer.realize() hasn't been already called, this doesn't work? */ this_->dirty(); +#endif OpenThreads::ScopedLock lock(this_->m_mutex);