Changeset 9860

Show
Ignore:
Timestamp:
03/04/09 15:49:39 (6 years ago)
Author:
robert
Message:

Introduced double buffering of video stream to avoid tearing of image.

Removed swapBufers call and image y inversion.

Location:
OpenSceneGraph/trunk/src/osgPlugins/ffmpeg
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp

    r9857 r9860  
    22 
    33#include <osg/Notify> 
     4#include <osg/Timer> 
    45 
    56#include <stdexcept> 
     
    1718    m_bytes_remaining(0), 
    1819    m_packet_pts(AV_NOPTS_VALUE), 
     20    m_writeBuffer(0), 
    1921    m_user_data(0), 
    2022    m_publish_func(0), 
     
    8486    // Allocate converted RGB frame 
    8587    m_frame_rgba.reset(avcodec_alloc_frame()); 
    86     m_buffer_rgba.resize(avpicture_get_size(PIX_FMT_RGB32, width(), height())); 
    87     m_buffer_rgba_public.resize(m_buffer_rgba.size()); 
     88    m_buffer_rgba[0].resize(avpicture_get_size(PIX_FMT_RGB32, width(), height())); 
     89    m_buffer_rgba[1].resize(m_buffer_rgba[0].size()); 
    8890 
    8991    // Assign appropriate parts of the buffer to image planes in m_frame_rgba 
    90     avpicture_fill((AVPicture *) m_frame_rgba.get(), &m_buffer_rgba[0], PIX_FMT_RGB32, width(), height()); 
     92    avpicture_fill((AVPicture *) (m_frame_rgba).get(), &(m_buffer_rgba[0])[0], PIX_FMT_RGB32, width(), height()); 
    9193 
    9294    // Override get_buffer()/release_buffer() from codec context in order to retrieve the PTS of each frame. 
     
    216218            int src_pix_fmt, int src_width, int src_height) 
    217219{ 
     220    osg::Timer_t startTick = osg::Timer::instance()->tick(); 
    218221#ifdef USE_SWSCALE 
    219222    if (m_swscale_ctx==0) 
     
    221224        m_swscale_ctx = sws_getContext(src_width, src_height, src_pix_fmt, 
    222225                                      src_width, src_height, dst_pix_fmt,                                     
    223                                       SWS_BILINEAR, NULL, NULL, NULL); 
     226                                      /*SWS_BILINEAR*/ SWS_BICUBIC, NULL, NULL, NULL); 
    224227    } 
    225228     
    226     osg::notify(osg::NOTICE)<<"Using sws_scale"<<std::endl; 
    227  
    228     return sws_scale(m_swscale_ctx, 
    229            src->data, src->linesize, 0, src_height, 
    230            dst->data, dst->linesize); 
     229 
     230    osg::notify(osg::NOTICE)<<"Using sws_scale "; 
     231 
     232    int result =  sws_scale(m_swscale_ctx, 
     233                            src->data, src->linesize, 0, src_height, 
     234                            dst->data, dst->linesize); 
    231235#else 
    232     osg::notify(osg::NOTICE)<<"Using img_convert"<<std::endl; 
    233  
    234     return img_convert(dst, dst_pix_fmt, src, 
    235                       src_pix_fmt, src_width, src_height); 
     236 
     237    osg::notify(osg::NOTICE)<<"Using img_convert "; 
     238 
     239    int result = img_convert(dst, dst_pix_fmt, src, 
     240                             src_pix_fmt, src_width, src_height); 
     241 
    236242#endif 
     243    osg::Timer_t endTick = osg::Timer::instance()->tick(); 
     244    osg::notify(osg::NOTICE)<<" time = "<<osg::Timer::instance()->delta_m(startTick,endTick)<<"ms"<<std::endl; 
     245 
     246    return result; 
    237247} 
    238248 
     
    247257    if (delay < -0.010) 
    248258        return; 
    249  
     259         
    250260    const AVPicture * const src = (const AVPicture *) m_frame.get(); 
    251261    AVPicture * const dst = (AVPicture *) m_frame_rgba.get(); 
     262 
     263    osg::Timer_t startTick = osg::Timer::instance()->tick(); 
     264 
     265    // Assign appropriate parts of the buffer to image planes in m_frame_rgba 
     266    avpicture_fill((AVPicture *) (m_frame_rgba).get(), &(m_buffer_rgba[m_writeBuffer])[0], PIX_FMT_RGB32, width(), height()); 
    252267 
    253268    // Convert YUVA420p (i.e. YUV420p plus alpha channel) using our own routine 
     
    258273        convert(dst, PIX_FMT_RGB32, src, m_context->pix_fmt, width(), height()); 
    259274 
     275 
    260276    // Flip and swap buffer 
    261     swapBuffers(); 
     277    // swapBuffers(); 
     278 
     279 
     280    osg::Timer_t endTick = osg::Timer::instance()->tick(); 
     281    osg::notify(osg::NOTICE)<<" time of swapBuffers = "<<osg::Timer::instance()->delta_m(startTick,endTick)<<"ms"<<std::endl; 
    262282 
    263283    // Wait 'delay' seconds before publishing the picture. 
     
    277297    } 
    278298 
     299    m_writeBuffer = 1-m_writeBuffer; 
     300 
    279301    m_publish_func(* this, m_user_data); 
    280302} 
     
    285307{ 
    286308    for (int h = 0; h < height(); ++h) 
    287         memcpy(&m_buffer_rgba_public[(height() - h - 1) * width() * 4], &m_buffer_rgba[h * width() * 4], width() * 4); 
     309        memcpy(&(m_buffer_rgba[1-m_writeBuffer])[(height() - h - 1) * width() * 4], &(m_buffer_rgba[m_writeBuffer])[h * width() * 4], width() * 4); 
    288310} 
    289311 
  • OpenSceneGraph/trunk/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.hpp

    r9856 r9860  
    108108    FramePtr                m_frame; 
    109109    FramePtr                m_frame_rgba; 
    110     Buffer                  m_buffer_rgba; 
    111     Buffer                  m_buffer_rgba_public; 
     110    Buffer                  m_buffer_rgba[2]; 
     111    int                     m_writeBuffer; 
    112112 
    113113    void *                  m_user_data; 
     
    176176inline const uint8_t * FFmpegDecoderVideo::image() const 
    177177{ 
    178     return &m_buffer_rgba_public[0]; 
     178    return &((m_buffer_rgba[1-m_writeBuffer])[0]); 
    179179} 
    180180 
  • OpenSceneGraph/trunk/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp

    r9847 r9860  
    5858        const_cast<unsigned char *>(m_decoder->video_decoder().image()), NO_DELETE 
    5959    ); 
     60     
     61    setOrigin(osg::Image::TOP_LEFT); 
    6062 
    6163    m_decoder->video_decoder().setUserData(this); 
     
    265267    FFmpegImageStream * const this_ = reinterpret_cast<FFmpegImageStream*>(user_data); 
    266268 
     269#if 1 
     270    this_->setImage( 
     271        this_->m_decoder->video_decoder().width(), this_->m_decoder->video_decoder().height(), 1, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, 
     272        const_cast<unsigned char *>(this_->m_decoder->video_decoder().image()), NO_DELETE 
     273    ); 
     274#else 
    267275    /** \bug If viewer.realize() hasn't been already called, this doesn't work? */ 
    268276    this_->dirty(); 
     277#endif 
    269278 
    270279    OpenThreads::ScopedLock<Mutex> lock(this_->m_mutex);