Ticket #4758: 4758-v1.patch

File 4758-v1.patch, 7.7 KB (added by danielk, 16 years ago)

Possible fix

  • libs/libmythtv/videoout_null.cpp

     
    1212const int kPrebufferFramesSmall = 4;
    1313const int kKeepPrebuffer = 2;
    1414
    15 VideoOutputNull::VideoOutputNull(void)
    16                : VideoOutput()
     15VideoOutputNull::VideoOutputNull(void) :
     16    VideoOutput(), global_lock(true)
    1717{
    1818    VERBOSE(VB_PLAYBACK, "VideoOutputNull()");
    19     XJ_started = 0;
    20 
    21     pauseFrame.buf = NULL;
     19    memset(&av_pause_frame, 0, sizeof(av_pause_frame));
    2220}
    2321
    2422VideoOutputNull::~VideoOutputNull()
    2523{
    2624    VERBOSE(VB_PLAYBACK, "~VideoOutputNull()");
    27     if (pauseFrame.buf)
    28         delete [] pauseFrame.buf;
     25    QMutexLocker locker(&global_lock);
    2926
    30     Exit();
     27    vbuffers.LockFrame(&av_pause_frame, "DeletePauseFrame");
     28    if (av_pause_frame.buf)
     29    {
     30        delete [] av_pause_frame.buf;
     31        memset(&av_pause_frame, 0, sizeof(av_pause_frame));
     32    }
     33    vbuffers.UnlockFrame(&av_pause_frame, "DeletePauseFrame");
     34
     35    vbuffers.DeleteBuffers();
    3136}
    3237
    3338// this is documented in videooutbase.cpp
    3439void VideoOutputNull::Zoom(ZoomDirection direction)
    3540{
     41    QMutexLocker locker(&global_lock);
    3642    VideoOutput::Zoom(direction);
    3743    MoveResize();
    3844}
    3945
     46void VideoOutputNull::CreatePauseFrame(void)
     47{
     48    vbuffers.LockFrame(&av_pause_frame, "CreatePauseFrame");
     49
     50    if (av_pause_frame.buf)
     51    {
     52        delete [] av_pause_frame.buf;
     53        av_pause_frame.buf = NULL;
     54    }
     55
     56    init(&av_pause_frame, FMT_YV12,
     57         new unsigned char[vbuffers.GetScratchFrame()->size + 128],
     58         vbuffers.GetScratchFrame()->width,
     59         vbuffers.GetScratchFrame()->height,
     60         vbuffers.GetScratchFrame()->bpp,
     61         vbuffers.GetScratchFrame()->size);
     62
     63    av_pause_frame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
     64
     65    clear(&av_pause_frame, GUID_I420_PLANAR);
     66
     67    vbuffers.UnlockFrame(&av_pause_frame, "CreatePauseFrame");
     68}
     69
    4070bool VideoOutputNull::InputChanged(const QSize &input_size,
    4171                                   float        aspect,
    4272                                   MythCodecID  av_codec_id,
     
    4777            .arg(input_size.width())
    4878            .arg(input_size.height()).arg(aspect));
    4979
     80    QMutexLocker locker(&global_lock);
     81
    5082    VideoOutput::InputChanged(input_size, aspect, av_codec_id, codec_private);
    5183
    5284    if (input_size.width()  == vbuffers.GetScratchFrame()->width &&
    5385        input_size.height() == vbuffers.GetScratchFrame()->height)
    5486    {
     87        vbuffers.Clear(GUID_I420_PLANAR);
    5588        MoveResize();
    5689        return true;
    5790    }
    5891
    5992    video_dim = input_size;
    6093
     94    vbuffers.DiscardFrames(true);
    6195    vbuffers.DeleteBuffers();
    6296
    6397    MoveResize();
     
    68102                "Failed to recreate buffers");
    69103        errored = true;
    70104    }
     105    CreatePauseFrame();
    71106
    72107    db_vdisp_profile->SetVideoRenderer("null");
    73108
    74     if (pauseFrame.buf)
    75         delete [] pauseFrame.buf;
    76 
    77     pauseFrame.height = vbuffers.GetScratchFrame()->height;
    78     pauseFrame.width  = vbuffers.GetScratchFrame()->width;
    79     pauseFrame.bpp    = vbuffers.GetScratchFrame()->bpp;
    80     pauseFrame.size   = vbuffers.GetScratchFrame()->size;
    81     pauseFrame.buf    = new unsigned char[pauseFrame.size];
    82     pauseFrame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
    83 
    84109    return true;
    85110}
    86111
     
    96121    if ((width <= 0) || (height <= 0))
    97122        return false;
    98123
     124    QMutexLocker locker(&global_lock);
     125
    99126    vbuffers.Init(kNumBuffers, true, kNeedFreeFrames,
    100127                  kPrebufferFramesNormal, kPrebufferFramesSmall,
    101128                  kKeepPrebuffer);
     
    106133
    107134    if (!vbuffers.CreateBuffers(width, height))
    108135        return false;
     136    CreatePauseFrame();
    109137
    110138    db_vdisp_profile->SetVideoRenderer("null");
    111139
    112     pauseFrame.height = vbuffers.GetScratchFrame()->height;
    113     pauseFrame.width  = vbuffers.GetScratchFrame()->width;
    114     pauseFrame.bpp    = vbuffers.GetScratchFrame()->bpp;
    115     pauseFrame.size   = vbuffers.GetScratchFrame()->size;
    116     pauseFrame.buf    = new unsigned char[pauseFrame.size];
    117     pauseFrame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
    118 
    119140    MoveResize();
    120     XJ_started = true;
    121141
    122142    return true;
    123143}
    124144
    125 void VideoOutputNull::Exit(void)
    126 {
    127     if (XJ_started)
    128     {
    129         XJ_started = false;
    130 
    131         vbuffers.DeleteBuffers();
    132     }
    133 }
    134 
    135145void VideoOutputNull::EmbedInWidget(WId wid, int x, int y, int w, int h)
    136146{
    137     if (embedding)
    138         return;
    139 
    140     VideoOutput::EmbedInWidget(wid, x, y, w, h);
     147    QMutexLocker locker(&global_lock);
     148    if (!embedding)
     149        VideoOutput::EmbedInWidget(wid, x, y, w, h);
    141150}
    142151 
    143152void VideoOutputNull::StopEmbedding(void)
    144153{
    145     if (!embedding)
    146         return;
    147 
    148     VideoOutput::StopEmbedding();
     154    QMutexLocker locker(&global_lock);
     155    if (embedding)
     156        VideoOutput::StopEmbedding();
    149157}
    150158
    151159void VideoOutputNull::PrepareFrame(VideoFrame *buffer, FrameScanType t)
     
    155163    if (!buffer)
    156164        buffer = vbuffers.GetScratchFrame();
    157165
     166    vbuffers.LockFrame(buffer, "PrepareFrame");
    158167    framesPlayed = buffer->frameNumber + 1;
     168    vbuffers.UnlockFrame(buffer, "PrepareFrame");
    159169}
    160170
    161171void VideoOutputNull::Show(FrameScanType )
     
    168178
    169179void VideoOutputNull::UpdatePauseFrame(void)
    170180{
    171     VideoFrame *pauseb = vbuffers.GetScratchFrame();
    172     VideoFrame *pauseu = vbuffers.head(kVideoBuffer_used);
    173     if (pauseu)
    174         memcpy(pauseFrame.buf, pauseu->buf, pauseu->size);
    175     else
    176         memcpy(pauseFrame.buf, pauseb->buf, pauseb->size);
     181    QMutexLocker locker(&global_lock);
     182
     183    // Try used frame first, then fall back to scratch frame.
     184    vbuffers.LockFrame(&av_pause_frame, "UpdatePauseFrame -- pause");
     185
     186    vbuffers.begin_lock(kVideoBuffer_used);
     187    VideoFrame *used_frame = NULL;
     188    if (vbuffers.size(kVideoBuffer_used) > 0)
     189    {
     190        used_frame = vbuffers.head(kVideoBuffer_used);
     191        if (!vbuffers.TryLockFrame(used_frame, "UpdatePauseFrame -- used"))
     192            used_frame = NULL;
     193    }
     194    if (used_frame)
     195    {
     196        CopyFrame(&av_pause_frame, used_frame);
     197        vbuffers.UnlockFrame(used_frame, "UpdatePauseFrame -- used");
     198    }
     199    vbuffers.end_lock();
     200
     201    if (!used_frame &&
     202        vbuffers.TryLockFrame(vbuffers.GetScratchFrame(),
     203                              "UpdatePauseFrame -- scratch"))
     204    {
     205        vbuffers.GetScratchFrame()->frameNumber = framesPlayed - 1;
     206        CopyFrame(&av_pause_frame, vbuffers.GetScratchFrame());
     207        vbuffers.UnlockFrame(vbuffers.GetScratchFrame(),
     208                             "UpdatePauseFrame -- scratch");
     209    }
     210    vbuffers.UnlockFrame(&av_pause_frame, "UpdatePauseFrame - used");
    177211}
    178212
    179213void VideoOutputNull::ProcessFrame(VideoFrame *frame, OSD *osd,
  • libs/libmythtv/videoout_null.h

     
    11#ifndef VIDEOOUT_NULL_H_
    22#define VIDEOOUT_NULL_H_
    33
     4#include <qmutex.h>
     5
    46#include "videooutbase.h"
    57
    68class VideoOutputNull : public VideoOutput
     
    1820    void PrepareFrame(VideoFrame *buffer, FrameScanType);
    1921    void Show(FrameScanType );
    2022
     23    void CreatePauseFrame(void);
    2124    bool InputChanged(const QSize &input_size,
    2225                      float        aspect,
    2326                      MythCodecID  av_codec_id,
     
    4043                                           const QSize &video_dim);
    4144
    4245  private:
    43     void Exit(void);
    44 
    45     bool XJ_started;
    46 
    47     VideoFrame pauseFrame;
     46    QMutex     global_lock;
     47    VideoFrame av_pause_frame;
    4848};
    4949
    5050#endif