Skip to content

Commit

Permalink
Remove individial frame locking code from VideoBuffers.
Browse files Browse the repository at this point in the history
Now that XvMC support has been removed, frame locking is not actually
used anymore and almost all of the calls into this code where no ops.
  • Loading branch information
Mark Kendall committed Feb 21, 2011
1 parent a1a34b7 commit b15558b
Show file tree
Hide file tree
Showing 8 changed files with 22 additions and 288 deletions.
2 changes: 1 addition & 1 deletion mythtv/libs/libmythtv/mythplayer.cpp
Expand Up @@ -1090,7 +1090,7 @@ void MythPlayer::InitFilters(void)
*/
VideoFrame *MythPlayer::GetNextVideoFrame(bool allow_unsafe)
{
return videoOutput->GetNextFreeFrame(false, allow_unsafe);
return videoOutput->GetNextFreeFrame(allow_unsafe);
}

/** \fn MythPlayer::ReleaseNextVideoFrame(VideoFrame*, int64_t)
Expand Down
208 changes: 6 additions & 202 deletions mythtv/libs/libmythtv/videobuffers.cpp
Expand Up @@ -14,8 +14,6 @@ extern "C" {
#include "compat.h"
#include "mythverbose.h"

#define DEBUG_FRAME_LOCKS 0

#define TRY_LOCK_SPINS 100
#define TRY_LOCK_SPINS_BEFORE_WARNING 10
#define TRY_LOCK_SPIN_WAIT 100 /* usec */
Expand Down Expand Up @@ -89,13 +87,6 @@ YUVInfo::YUVInfo(uint w, uint h, uint sz, const int *p, const int *o)
* being displayed at the end of the next
* DoneDisplayingFrame(), finally adding them to available.
*
* Frame locking is also available, the locks are reqursive
* QMutex locks. If more than one frame lock is needed the
* LockFrames should generally be called with all the needed
* locks in the list, and no locks currently held. This
* function will spin until all the locks can be held at
* once, avoiding deadlocks from mismatched locking order.
*
* The only method that returns with a lock held on the VideoBuffers
* object itself, preventing anyone else from using the VideoBuffers
* class, inluding to unlocking frames, is the begin_lock(BufferType).
Expand All @@ -113,8 +104,7 @@ VideoBuffers::VideoBuffers()
: numbuffers(0), needfreeframes(0), needprebufferframes(0),
needprebufferframes_normal(0), needprebufferframes_small(0),
keepprebufferframes(0), need_extra_for_pause(false), rpos(0), vpos(0),
global_lock(QMutex::Recursive), use_frame_locks(true),
frame_lock(QMutex::Recursive)
global_lock(QMutex::Recursive)
{
}

Expand Down Expand Up @@ -143,14 +133,10 @@ VideoBuffers::~VideoBuffers()
* after SetPrebuffering(false) has been called.
* \param keepprebuffer number of buffers in used or limbo that are considered
* enough for decent playback.
* \param enable_frame_locking if true, the frames will be locked with a mutex,
* this makes XvMC decoding safe, but adds some CPU
* overhead. It is normally left off.
*/
void VideoBuffers::Init(uint numdecode, bool extra_for_pause,
uint need_free, uint needprebuffer_normal,
uint needprebuffer_small, uint keepprebuffer,
bool enable_frame_locking)
uint needprebuffer_small, uint keepprebuffer)
{
QMutexLocker locker(&global_lock);

Expand Down Expand Up @@ -179,7 +165,6 @@ void VideoBuffers::Init(uint numdecode, bool extra_for_pause,
needprebufferframes_small = needprebuffer_small;
keepprebufferframes = keepprebuffer;
need_extra_for_pause = extra_for_pause;
use_frame_locks = enable_frame_locking;

for (uint i = 0; i < numdecode; i++)
enqueue(kVideoBuffer_avail, at(i));
Expand Down Expand Up @@ -225,7 +210,7 @@ void VideoBuffers::SetPrebuffering(bool normal)
}

VideoFrame *VideoBuffers::GetNextFreeFrameInternal(
bool with_lock, bool allow_unsafe, BufferType enqueue_to)
bool allow_unsafe, BufferType enqueue_to)
{
QMutexLocker locker(&global_lock);
VideoFrame *frame = available.dequeue();
Expand Down Expand Up @@ -258,47 +243,26 @@ VideoFrame *VideoBuffers::GetNextFreeFrameInternal(
}

if (frame)
{
safeEnqueue(enqueue_to, frame);

bool success = true;
if (with_lock)
success = TryLockFrame(frame, "GetNextFreeFrame");

if (!success)
{
safeEnqueue(kVideoBuffer_avail, frame);
VERBOSE(VB_IMPORTANT,
QString("GetNextFreeFrame() unable to lock frame %1. "
"Dropping %2. w/lock(%3) unsafe(%4)")
.arg(DebugString(frame)).arg(GetStatus())
.arg(with_lock).arg(allow_unsafe));
DiscardFrame(frame);
frame = NULL;
}
}

return frame;
}

/**
* \fn VideoBuffers::GetNextFreeFrame(bool,bool,BufferType)
* Gets a frame from available buffers list.
*
* \param with_lock locks the frame, so that UnlockFrame() must be
* called before anyone else can use it.
* \param allow_unsafe allows busy buffers to be used if no available
* buffers exist. Historic, should never be used.
* \param enqueue_to put new frame in some state other than limbo.
*/
VideoFrame *VideoBuffers::GetNextFreeFrame(bool with_lock,
bool allow_unsafe,
VideoFrame *VideoBuffers::GetNextFreeFrame(bool allow_unsafe,
BufferType enqueue_to)
{
for (uint tries = 1; true; tries++)
{
VideoFrame *frame = VideoBuffers::GetNextFreeFrameInternal(
with_lock, allow_unsafe, enqueue_to);
allow_unsafe, enqueue_to);

if (frame)
return frame;
Expand Down Expand Up @@ -396,27 +360,7 @@ void VideoBuffers::DoneDisplayingFrame(VideoFrame *frame)
void VideoBuffers::DiscardFrame(VideoFrame *frame)
{
QMutexLocker locker(&global_lock);

bool ok = TryLockFrame(frame, "DiscardFrame A");
for (uint i=0; i<5 && !ok; i++)
{
global_lock.unlock();
usleep(50);
global_lock.lock();
ok = TryLockFrame(frame, "DiscardFrame B");
}

if (ok)
{
safeEnqueue(kVideoBuffer_avail, frame);
UnlockFrame(frame, "DiscardFrame");
}
else
{
VERBOSE(VB_IMPORTANT, QString("VideoBuffers::DiscardFrame(): "
"Unable to obtain lock on %1, %2")
.arg(DebugString(frame, true)).arg(GetStatus()));
}
safeEnqueue(kVideoBuffer_avail, frame);
}

frame_queue_t *VideoBuffers::queue(BufferType type)
Expand Down Expand Up @@ -734,146 +678,6 @@ void VideoBuffers::ClearAfterSeek(void)
}
}

void VideoBuffers::LockFrame(const VideoFrame *frame, const char* owner)
{
if (!use_frame_locks)
return;

QMutex *mutex = NULL;
(void)owner;

if (!frame)
return;

frame_lock.lock();
#if DEBUG_FRAME_LOCKS
if (owner!="")
VERBOSE(VB_PLAYBACK, QString("locking frame: %1 %2 %3")
.arg(DebugString(frame)).arg(GetStatus()).arg(owner));
#endif

frame_lock_map_t::iterator it = frame_locks.find(frame);
if (it == frame_locks.end())
mutex = frame_locks[frame] = new QMutex(QMutex::Recursive);
else
mutex = it->second;

frame_lock.unlock();

mutex->lock();
}

void VideoBuffers::LockFrames(vector<const VideoFrame*>& vec,
const char* owner)
{
if (!use_frame_locks)
return;

(void)owner;
bool ok;
vector<bool> oks;
oks.resize(vec.size());

#if DEBUG_FRAME_LOCKS
VERBOSE(VB_PLAYBACK, QString("lock frames: %1 %2 %3")
.arg(DebugString(vec)).arg(GetStatus()).arg(owner));
#endif
do
{
ok = true;
for (uint i=0; i<vec.size(); i++)
ok &= oks[i] = TryLockFrame(vec[i], "");
if (!ok)
{
for (uint i=0; i<vec.size(); i++)
if (oks[i])
UnlockFrame(vec[i], "");
usleep(50);
#if DEBUG_FRAME_LOCKS
VERBOSE(VB_PLAYBACK, QString("no lock, frames: %1 %2 %3")
.arg(DebugString(vec)).arg(GetStatus()).arg(owner));
#endif
}
}
while (!ok);
}

bool VideoBuffers::TryLockFrame(const VideoFrame *frame, const char* owner)
{
if (!use_frame_locks)
return true;

QMutex *mutex = NULL;
(void)owner;

if (!frame)
return true;

frame_lock.lock();
#if DEBUG_FRAME_LOCKS
if (owner!="")
VERBOSE(VB_PLAYBACK, QString("try lock frame: %1 %2 %3")
.arg(DebugString(frame)).arg(GetStatus()).arg(owner));
#endif

frame_lock_map_t::iterator it = frame_locks.find(frame);
if (it == frame_locks.end())
mutex = frame_locks[frame] = new QMutex(QMutex::Recursive);
else
mutex = it->second;

bool ok = mutex->tryLock();

#if DEBUG_FRAME_LOCKS
if (owner!="")
{
QString str = (ok) ? "got lock: " : "try lock failed: ";
VERBOSE(VB_PLAYBACK, str.append(DebugString(frame)));
}
#endif
frame_lock.unlock();

return ok;
}

void VideoBuffers::UnlockFrame(const VideoFrame *frame, const char* owner)
{
if (!use_frame_locks)
return;

(void)owner;

if (!frame)
return;

frame_lock.lock();
#if DEBUG_FRAME_LOCKS
if (owner!="")
VERBOSE(VB_PLAYBACK, QString("unlocking frame: %1 %2 %3")
.arg(DebugString(frame)).arg(GetStatus()).arg(owner));
#endif

frame_lock_map_t::iterator it = frame_locks.find(frame);
it->second->unlock();

frame_lock.unlock();
}

void VideoBuffers::UnlockFrames(vector<const VideoFrame*>& vec,
const char* owner)
{
if (!use_frame_locks)
return;

(void)owner;
#if DEBUG_FRAME_LOCKS
VERBOSE(VB_PLAYBACK, QString("unlocking frames:%1 %2 %3")
.arg(DebugString(vec)).arg(GetStatus()).arg(owner));
#endif
for (uint i=0; i<vec.size(); i++)
UnlockFrame(vec[i], "");
}

bool VideoBuffers::CreateBuffers(VideoFrameType type, int width, int height)
{
vector<unsigned char*> bufs;
Expand Down
17 changes: 3 additions & 14 deletions mythtv/libs/libmythtv/videobuffers.h
Expand Up @@ -65,8 +65,7 @@ class VideoBuffers

void Init(uint numdecode, bool extra_for_pause,
uint need_free, uint needprebuffer_normal,
uint needprebuffer_small, uint keepprebuffer,
bool enable_frame_locking = false);
uint needprebuffer_small, uint keepprebuffer);

bool CreateBuffers(VideoFrameType type, int width, int height,
vector<unsigned char*> bufs,
Expand All @@ -80,7 +79,7 @@ class VideoBuffers

void SetPrebuffering(bool normal);

VideoFrame *GetNextFreeFrame(bool with_lock, bool allow_unsafe,
VideoFrame *GetNextFreeFrame(bool allow_unsafe,
BufferType enqueue_to = kVideoBuffer_limbo);
void ReleaseFrame(VideoFrame *frame);
void DeLimboFrame(VideoFrame *frame);
Expand Down Expand Up @@ -123,12 +122,6 @@ class VideoBuffers
uint size() const { return numbuffers; }
uint allocSize() const { return buffers.size(); }

void LockFrame(const VideoFrame *, const char* owner);
void LockFrames(vector<const VideoFrame*>&, const char* owner);
bool TryLockFrame(const VideoFrame *, const char* owner);
void UnlockFrame(const VideoFrame *, const char* owner);
void UnlockFrames(vector<const VideoFrame*>&, const char* owner);

void Clear(uint i);
void Clear(void);

Expand All @@ -140,7 +133,7 @@ class VideoBuffers
frame_queue_t *queue(BufferType type);
const frame_queue_t *queue(BufferType type) const;
VideoFrame *GetNextFreeFrameInternal(
bool with_lock, bool allow_unsafe, BufferType enqueue_to);
bool allow_unsafe, BufferType enqueue_to);

frame_queue_t available, used, limbo, pause, displayed, decode;
vbuffer_map_t vbufferMap; // videobuffers to buffer's index
Expand All @@ -160,10 +153,6 @@ class VideoBuffers
uint vpos;

mutable QMutex global_lock;

bool use_frame_locks;
QMutex frame_lock;
frame_lock_map_t frame_locks;
};

#endif // __VIDEOBUFFERS_H__

0 comments on commit b15558b

Please sign in to comment.