00001
00002
00003
00004 #include <unistd.h>
00005 #include "mythcontext.h"
00006 #include "videobuffers.h"
00007 extern "C" {
00008 #include "../libavcodec/avcodec.h"
00009 }
00010 #include "fourcc.h"
00011 #include "compat.h"
00012
00013 #ifdef USING_XVMC
00014 #include "videoout_xv.h"
00015 #endif
00016
00017 #define DEBUG_FRAME_LOCKS 0
00018
00019 #define TRY_LOCK_SPINS 100
00020 #define TRY_LOCK_SPINS_BEFORE_WARNING 10
00021 #define TRY_LOCK_SPIN_WAIT 100
00022
00023 int next_dbg_str = 0;
00024
00025 YUVInfo::YUVInfo(uint w, uint h, uint sz, const int *p, const int *o)
00026 : width(w), height(h), size(sz)
00027 {
00028 if (p)
00029 {
00030 memcpy(pitches, p, 3 * sizeof(int));
00031 }
00032 else
00033 {
00034 pitches[0] = width;
00035 pitches[1] = pitches[2] = width >> 1;
00036 }
00037
00038 if (o)
00039 {
00040 memcpy(offsets, o, 3 * sizeof(int));
00041 }
00042 else
00043 {
00044 offsets[0] = 0;
00045 offsets[1] = width * height;
00046 offsets[2] = offsets[1] + (offsets[1] >> 2);
00047 }
00048 }
00049
00112 VideoBuffers::VideoBuffers()
00113 : numbuffers(0), needfreeframes(0), needprebufferframes(0),
00114 needprebufferframes_normal(0), needprebufferframes_small(0),
00115 keepprebufferframes(0), need_extra_for_pause(false), rpos(0), vpos(0),
00116 global_lock(true), use_frame_locks(true),
00117 frame_lock(true)
00118 {
00119 }
00120
00121 VideoBuffers::~VideoBuffers()
00122 {
00123 DeleteBuffers();
00124 }
00125
00150 void VideoBuffers::Init(uint numdecode, bool extra_for_pause,
00151 uint need_free, uint needprebuffer_normal,
00152 uint needprebuffer_small, uint keepprebuffer,
00153 bool enable_frame_locking)
00154 {
00155 QMutexLocker locker(&global_lock);
00156
00157 Reset();
00158
00159 uint numcreate = numdecode + ((extra_for_pause) ? 1 : 0);
00160
00161
00162
00163 buffers.reserve(max(numcreate, (uint)128));
00164
00165 buffers.resize(numcreate);
00166 for (uint i = 0; i < numcreate; i++)
00167 {
00168 memset(at(i), 0, sizeof(VideoFrame));
00169 at(i)->codec = FMT_NONE;
00170 at(i)->interlaced_frame = -1;
00171 at(i)->top_field_first = +1;
00172 vbufferMap[at(i)] = i;
00173 }
00174
00175 numbuffers = numdecode;
00176 needfreeframes = need_free;
00177 needprebufferframes = needprebuffer_normal;
00178 needprebufferframes_normal = needprebuffer_normal;
00179 needprebufferframes_small = needprebuffer_small;
00180 keepprebufferframes = keepprebuffer;
00181 need_extra_for_pause = extra_for_pause;
00182 use_frame_locks = enable_frame_locking;
00183
00184 for (uint i = 0; i < numdecode; i++)
00185 enqueue(kVideoBuffer_avail, at(i));
00186 }
00187
00192 void VideoBuffers::Reset()
00193 {
00194 QMutexLocker locker(&global_lock);
00195
00196
00197
00198 frame_vector_t::iterator it = buffers.begin();
00199 for (;it != buffers.end(); it++)
00200 {
00201 if (it->qscale_table)
00202 {
00203 delete [] it->qscale_table;
00204 it->qscale_table = NULL;
00205 }
00206 }
00207
00208 available.clear();
00209 used.clear();
00210 limbo.clear();
00211 pause.clear();
00212 displayed.clear();
00213 parents.clear();
00214 children.clear();
00215 vbufferMap.clear();
00216 }
00217
00222 void VideoBuffers::SetPrebuffering(bool normal)
00223 {
00224 QMutexLocker locker(&global_lock);
00225 needprebufferframes = (normal) ?
00226 needprebufferframes_normal : needprebufferframes_small;
00227 };
00228
00229 VideoFrame *VideoBuffers::GetNextFreeFrameInternal(
00230 bool with_lock, bool allow_unsafe, BufferType enqueue_to)
00231 {
00232 QMutexLocker locker(&global_lock);
00233 VideoFrame *frame = available.dequeue();
00234
00235
00236 for (uint i = 0; i <= available.size() && decode.contains(frame); i++)
00237 {
00238 if (!available.contains(frame))
00239 available.enqueue(frame);
00240 frame = available.dequeue();
00241 }
00242
00243 while (frame && used.contains(frame))
00244 {
00245 VERBOSE(VB_IMPORTANT,
00246 QString("GetNextFreeFrame() served a busy frame %1. "
00247 "Dropping. %2")
00248 .arg(DebugString(frame, true)).arg(GetStatus()));
00249 frame = available.dequeue();
00250 }
00251
00252
00253 if (!frame && allow_unsafe)
00254 {
00255 VERBOSE(VB_PLAYBACK,
00256 QString("GetNextFreeFrame() is getting a busy frame %1. "
00257 " %2")
00258 .arg(DebugString(frame, true)).arg(GetStatus()));
00259 frame = used.dequeue();
00260 if (EnoughFreeFrames())
00261 available_wait.wakeAll();
00262 }
00263
00264 if (frame)
00265 {
00266 safeEnqueue(enqueue_to, frame);
00267
00268 bool success = true;
00269 if (with_lock)
00270 success = TryLockFrame(frame, "GetNextFreeFrame");
00271
00272 if (!success)
00273 {
00274 safeEnqueue(kVideoBuffer_avail, frame);
00275 VERBOSE(VB_IMPORTANT,
00276 QString("GetNextFreeFrame() unable to lock frame %1. "
00277 "Dropping %2. w/lock(%3) unsafe(%4)")
00278 .arg(DebugString(frame)).arg(GetStatus())
00279 .arg(with_lock).arg(allow_unsafe));
00280 DiscardFrame(frame);
00281 frame = NULL;
00282 }
00283 }
00284
00285 return frame;
00286 }
00287
00298 VideoFrame *VideoBuffers::GetNextFreeFrame(bool with_lock,
00299 bool allow_unsafe,
00300 BufferType enqueue_to)
00301 {
00302 for (uint tries = 1; true; tries++)
00303 {
00304 VideoFrame *frame = VideoBuffers::GetNextFreeFrameInternal(
00305 with_lock, allow_unsafe, enqueue_to);
00306
00307 if (frame)
00308 return frame;
00309
00310 if (tries >= TRY_LOCK_SPINS)
00311 {
00312 VERBOSE(VB_IMPORTANT,
00313 QString("GetNextFreeFrame() unable to "
00314 "lock frame %1 times. Discarding Frames.")
00315 .arg(TRY_LOCK_SPINS));
00316 DiscardFrames(true);
00317 continue;
00318 }
00319
00320 if (tries && !(tries % TRY_LOCK_SPINS_BEFORE_WARNING))
00321 {
00322 VERBOSE(VB_PLAYBACK,
00323 QString("GetNextFreeFrame() TryLock has "
00324 "spun %1 times, this is a lot.").arg(tries));
00325 }
00326 usleep(TRY_LOCK_SPIN_WAIT);
00327 }
00328
00329 return NULL;
00330 }
00331
00338 void VideoBuffers::ReleaseFrame(VideoFrame *frame)
00339 {
00340 QMutexLocker locker(&global_lock);
00341
00342 vpos = vbufferMap[frame];
00343 limbo.remove(frame);
00344 decode.enqueue(frame);
00345 used.enqueue(frame);
00346 }
00347
00353 void VideoBuffers::DeLimboFrame(VideoFrame *frame)
00354 {
00355 QMutexLocker locker(&global_lock);
00356 if (limbo.contains(frame))
00357 {
00358 limbo.remove(frame);
00359 available.enqueue(frame);
00360 }
00361
00362
00363
00364
00365 while (decode.contains(frame))
00366 decode.remove(frame);
00367
00368 }
00369
00374 void VideoBuffers::StartDisplayingFrame(void)
00375 {
00376 QMutexLocker locker(&global_lock);
00377 rpos = vbufferMap[used.head()];
00378 }
00379
00384 void VideoBuffers::DoneDisplayingFrame(void)
00385 {
00386 QMutexLocker locker(&global_lock);
00387
00388 VideoFrame *buf = used.dequeue();
00389 if (buf)
00390 {
00391 available.enqueue(buf);
00392 if (EnoughFreeFrames())
00393 available_wait.wakeAll();
00394 }
00395 }
00396
00402 void VideoBuffers::DiscardFrame(VideoFrame *frame)
00403 {
00404 QMutexLocker locker(&global_lock);
00405
00406 bool ok = TryLockFrame(frame, "DiscardFrame A");
00407 for (uint i=0; i<5 && !ok; i++)
00408 {
00409 global_lock.unlock();
00410 usleep(50);
00411 global_lock.lock();
00412 ok = TryLockFrame(frame, "DiscardFrame B");
00413 }
00414
00415 if (ok)
00416 {
00417 safeEnqueue(kVideoBuffer_avail, frame);
00418 UnlockFrame(frame, "DiscardFrame");
00419 }
00420 else
00421 {
00422 VERBOSE(VB_IMPORTANT, QString("VideoBuffers::DiscardFrame(): "
00423 "Unable to obtain lock on %1, %2")
00424 .arg(DebugString(frame, true)).arg(GetStatus()));
00425 }
00426 }
00427
00428 frame_queue_t *VideoBuffers::queue(BufferType type)
00429 {
00430 QMutexLocker locker(&global_lock);
00431
00432 frame_queue_t *q = NULL;
00433
00434 if (type == kVideoBuffer_avail)
00435 q = &available;
00436 else if (type == kVideoBuffer_used)
00437 q = &used;
00438 else if (type == kVideoBuffer_displayed)
00439 q = &displayed;
00440 else if (type == kVideoBuffer_limbo)
00441 q = &limbo;
00442 else if (type == kVideoBuffer_pause)
00443 q = &pause;
00444 else if (type == kVideoBuffer_decode)
00445 q = &decode;
00446
00447 return q;
00448 }
00449
00450 const frame_queue_t *VideoBuffers::queue(BufferType type) const
00451 {
00452 QMutexLocker locker(&global_lock);
00453
00454 const frame_queue_t *q = NULL;
00455
00456 if (type == kVideoBuffer_avail)
00457 q = &available;
00458 else if (type == kVideoBuffer_used)
00459 q = &used;
00460 else if (type == kVideoBuffer_displayed)
00461 q = &displayed;
00462 else if (type == kVideoBuffer_limbo)
00463 q = &limbo;
00464 else if (type == kVideoBuffer_pause)
00465 q = &pause;
00466 else if (type == kVideoBuffer_decode)
00467 q = &decode;
00468
00469 return q;
00470 }
00471
00472 VideoFrame *VideoBuffers::dequeue(BufferType type)
00473 {
00474 QMutexLocker locker(&global_lock);
00475
00476 frame_queue_t *q = queue(type);
00477
00478 if (!q)
00479 return NULL;
00480
00481 return q->dequeue();
00482 }
00483
00484 VideoFrame *VideoBuffers::head(BufferType type)
00485 {
00486 QMutexLocker locker(&global_lock);
00487
00488 frame_queue_t *q = queue(type);
00489
00490 if (!q)
00491 return NULL;
00492
00493 if (q->size())
00494 return q->head();
00495
00496 return NULL;
00497 }
00498
00499 VideoFrame *VideoBuffers::tail(BufferType type)
00500 {
00501 QMutexLocker locker(&global_lock);
00502
00503 frame_queue_t *q = queue(type);
00504
00505 if (!q)
00506 return NULL;
00507
00508 if (q->size())
00509 return q->tail();
00510
00511 return NULL;
00512 }
00513
00514 void VideoBuffers::enqueue(BufferType type, VideoFrame *frame)
00515 {
00516 if (!frame)
00517 return;
00518
00519 frame_queue_t *q = queue(type);
00520 if (!q)
00521 return;
00522
00523 global_lock.lock();
00524 q->remove(frame);
00525 q->enqueue(frame);
00526 global_lock.unlock();
00527
00528 if (q == &available && EnoughFreeFrames())
00529 available_wait.wakeAll();
00530
00531 return;
00532 }
00533
00534 void VideoBuffers::remove(BufferType type, VideoFrame *frame)
00535 {
00536 if (!frame)
00537 return;
00538
00539 QMutexLocker locker(&global_lock);
00540
00541 if ((type & kVideoBuffer_avail) == kVideoBuffer_avail)
00542 available.remove(frame);
00543 if ((type & kVideoBuffer_used) == kVideoBuffer_used)
00544 used.remove(frame);
00545 if ((type & kVideoBuffer_displayed) == kVideoBuffer_displayed)
00546 displayed.remove(frame);
00547 if ((type & kVideoBuffer_limbo) == kVideoBuffer_limbo)
00548 limbo.remove(frame);
00549 if ((type & kVideoBuffer_pause) == kVideoBuffer_pause)
00550 pause.remove(frame);
00551 if ((type & kVideoBuffer_decode) == kVideoBuffer_decode)
00552 decode.remove(frame);
00553 }
00554
00555 void VideoBuffers::requeue(BufferType dst, BufferType src, int num)
00556 {
00557 QMutexLocker locker(&global_lock);
00558
00559 num = (num <= 0) ? size(src) : num;
00560 for (uint i=0; i<(uint)num; i++)
00561 {
00562 VideoFrame *frame = dequeue(src);
00563 if (frame)
00564 enqueue(dst, frame);
00565 }
00566 }
00567
00568 void VideoBuffers::safeEnqueue(BufferType dst, VideoFrame* frame)
00569 {
00570 if (!frame)
00571 return;
00572
00573 QMutexLocker locker(&global_lock);
00574
00575 remove(kVideoBuffer_all, frame);
00576 enqueue(dst, frame);
00577 }
00578
00579 frame_queue_t::iterator VideoBuffers::begin_lock(BufferType type)
00580 {
00581 global_lock.lock();
00582 frame_queue_t *q = queue(type);
00583 if (q)
00584 return q->begin();
00585 else
00586 return available.begin();
00587 }
00588
00589 frame_queue_t::iterator VideoBuffers::end(BufferType type)
00590 {
00591 QMutexLocker locker(&global_lock);
00592
00593 frame_queue_t::iterator it;
00594 frame_queue_t *q = queue(type);
00595 if (q)
00596 it = q->end();
00597 else
00598 it = available.end();
00599
00600 return it;
00601 }
00602
00603 uint VideoBuffers::size(BufferType type) const
00604 {
00605 QMutexLocker locker(&global_lock);
00606
00607 const frame_queue_t *q = queue(type);
00608 if (q)
00609 return q->size();
00610
00611 return 0;
00612 }
00613
00614 bool VideoBuffers::contains(BufferType type, VideoFrame *frame) const
00615 {
00616 QMutexLocker locker(&global_lock);
00617
00618 const frame_queue_t *q = queue(type);
00619 if (q)
00620 return q->contains(frame);
00621
00622 return false;
00623 }
00624
00625 VideoFrame *VideoBuffers::GetScratchFrame(void)
00626 {
00627 if (!need_extra_for_pause)
00628 {
00629 VERBOSE(VB_IMPORTANT,
00630 "GetScratchFrame() called, but not allocated");
00631 }
00632
00633 QMutexLocker locker(&global_lock);
00634 return at(allocSize()-1);
00635 }
00636
00637 const VideoFrame *VideoBuffers::GetScratchFrame(void) const
00638 {
00639 if (!need_extra_for_pause)
00640 {
00641 VERBOSE(VB_IMPORTANT,
00642 "GetScratchFrame() called, but not allocated");
00643 }
00644
00645 QMutexLocker locker(&global_lock);
00646 return at(allocSize()-1);
00647 }
00648
00653 void VideoBuffers::DiscardFrames(bool next_frame_keyframe)
00654 {
00655 QMutexLocker locker(&global_lock);
00656 VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(%1): %2")
00657 .arg(next_frame_keyframe).arg(GetStatus()));
00658
00659 if (!next_frame_keyframe)
00660 {
00661 for (bool change = true; change;)
00662 {
00663 change = false;
00664 frame_queue_t ula(used);
00665 frame_queue_t::iterator it = ula.begin();
00666 for (; it != ula.end(); ++it)
00667 {
00668 if (!HasChildren(*it))
00669 {
00670 RemoveInheritence(*it);
00671 DiscardFrame(*it);
00672 change = true;
00673 }
00674 }
00675 }
00676 VERBOSE(VB_PLAYBACK,
00677 QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
00678 .arg(next_frame_keyframe).arg(GetStatus()));
00679 return;
00680 }
00681
00682
00683 frame_queue_t ula(used);
00684 ula.insert(ula.end(), limbo.begin(), limbo.end());
00685 ula.insert(ula.end(), available.begin(), available.end());
00686 frame_queue_t::iterator it;
00687 for (it = ula.begin(); it != ula.end(); ++it)
00688 RemoveInheritence(*it);
00689
00690
00691 frame_queue_t discards(used);
00692 discards.insert(discards.end(), limbo.begin(), limbo.end());
00693 for (it = discards.begin(); it != discards.end(); ++it)
00694 DiscardFrame(*it);
00695
00696
00697 if (available.count() + pause.count() + displayed.count() != size())
00698 {
00699 for (uint i=0; i < size(); i++)
00700 {
00701 if (!available.contains(at(i)) &&
00702 !pause.contains(at(i)) &&
00703 !displayed.contains(at(i)))
00704 {
00705 VERBOSE(VB_IMPORTANT,
00706 QString("VideoBuffers::DiscardFrames(): ERROR, %1 not "
00707 "in available, pause, or displayed %2")
00708 .arg(DebugString(at(i), true))
00709 .arg(GetStatus()));
00710 DiscardFrame(at(i));
00711 }
00712 }
00713 }
00714
00715
00716
00717 for (it = decode.begin(); it != decode.end(); ++it)
00718 remove(kVideoBuffer_all, *it);
00719 for (it = decode.begin(); it != decode.end(); ++it)
00720 available.enqueue(*it);
00721 decode.clear();
00722
00723 VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(): %1 -- done()")
00724 .arg(GetStatus()));
00725
00726 VERBOSE(VB_PLAYBACK,
00727 QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
00728 .arg(next_frame_keyframe).arg(GetStatus()));
00729 }
00730
00731 void VideoBuffers::ClearAfterSeek(void)
00732 {
00733 {
00734 QMutexLocker locker(&global_lock);
00735
00736 for (uint i = 0; i < size(); i++)
00737 at(i)->timecode = 0;
00738
00739 while (used.count() > 1)
00740 {
00741 VideoFrame *buffer = used.dequeue();
00742 available.enqueue(buffer);
00743 }
00744
00745 if (used.count() > 0)
00746 {
00747 VideoFrame *buffer = used.dequeue();
00748 available.enqueue(buffer);
00749 vpos = vbufferMap[buffer];
00750 rpos = vpos;
00751 }
00752 else
00753 {
00754 vpos = rpos = 0;
00755 }
00756 }
00757
00758 if (EnoughFreeFrames())
00759 available_wait.wakeAll();
00760
00761 }
00762
00763 void VideoBuffers::LockFrame(const VideoFrame *frame, const char* owner)
00764 {
00765 if (!use_frame_locks)
00766 return;
00767
00768 QMutex *mutex = NULL;
00769 (void)owner;
00770
00771 if (!frame)
00772 return;
00773
00774 frame_lock.lock();
00775 #if DEBUG_FRAME_LOCKS
00776 if (owner!="")
00777 VERBOSE(VB_PLAYBACK, QString("locking frame: %1 %2 %3")
00778 .arg(DebugString(frame)).arg(GetStatus()).arg(owner));
00779 #endif
00780
00781 frame_lock_map_t::iterator it = frame_locks.find(frame);
00782 if (it == frame_locks.end())
00783 mutex = frame_locks[frame] = new QMutex(true);
00784 else
00785 mutex = it->second;
00786
00787 frame_lock.unlock();
00788
00789 mutex->lock();
00790 }
00791
00792 void VideoBuffers::LockFrames(vector<const VideoFrame*>& vec,
00793 const char* owner)
00794 {
00795 if (!use_frame_locks)
00796 return;
00797
00798 (void)owner;
00799 bool ok;
00800 vector<bool> oks;
00801 oks.resize(vec.size());
00802
00803 #if DEBUG_FRAME_LOCKS
00804 VERBOSE(VB_PLAYBACK, QString("lock frames: %1 %2 %3")
00805 .arg(DebugString(vec)).arg(GetStatus()).arg(owner));
00806 #endif
00807 do
00808 {
00809 ok = true;
00810 for (uint i=0; i<vec.size(); i++)
00811 ok &= oks[i] = TryLockFrame(vec[i], "");
00812 if (!ok)
00813 {
00814 for (uint i=0; i<vec.size(); i++)
00815 if (oks[i])
00816 UnlockFrame(vec[i], "");
00817 usleep(50);
00818 #if DEBUG_FRAME_LOCKS
00819 VERBOSE(VB_PLAYBACK, QString("no lock, frames: %1 %2 %3")
00820 .arg(DebugString(vec)).arg(GetStatus()).arg(owner));
00821 #endif
00822 }
00823 }
00824 while (!ok);
00825 }
00826
00827 bool VideoBuffers::TryLockFrame(const VideoFrame *frame, const char* owner)
00828 {
00829 if (!use_frame_locks)
00830 return true;
00831
00832 QMutex *mutex = NULL;
00833 (void)owner;
00834
00835 if (!frame)
00836 return true;
00837
00838 frame_lock.lock();
00839 #if DEBUG_FRAME_LOCKS
00840 if (owner!="")
00841 VERBOSE(VB_PLAYBACK, QString("try lock frame: %1 %2 %3")
00842 .arg(DebugString(frame)).arg(GetStatus()).arg(owner));
00843 #endif
00844
00845 frame_lock_map_t::iterator it = frame_locks.find(frame);
00846 if (it == frame_locks.end())
00847 mutex = frame_locks[frame] = new QMutex(true);
00848 else
00849 mutex = it->second;
00850
00851 bool ok = mutex->tryLock();
00852
00853 #if DEBUG_FRAME_LOCKS
00854 if (owner!="")
00855 {
00856 QString str = (ok) ? "got lock: " : "try lock failed: ";
00857 VERBOSE(VB_PLAYBACK, str.append(DebugString(frame)));
00858 }
00859 #endif
00860 frame_lock.unlock();
00861
00862 return ok;
00863 }
00864
00865 void VideoBuffers::UnlockFrame(const VideoFrame *frame, const char* owner)
00866 {
00867 if (!use_frame_locks)
00868 return;
00869
00870 (void)owner;
00871
00872 if (!frame)
00873 return;
00874
00875 frame_lock.lock();
00876 #if DEBUG_FRAME_LOCKS
00877 if (owner!="")
00878 VERBOSE(VB_PLAYBACK, QString("unlocking frame: %1 %2 %3")
00879 .arg(DebugString(frame)).arg(GetStatus()).arg(owner));
00880 #endif
00881
00882 frame_lock_map_t::iterator it = frame_locks.find(frame);
00883 it->second->unlock();
00884
00885 frame_lock.unlock();
00886 }
00887
00888 void VideoBuffers::UnlockFrames(vector<const VideoFrame*>& vec,
00889 const char* owner)
00890 {
00891 if (!use_frame_locks)
00892 return;
00893
00894 (void)owner;
00895 #if DEBUG_FRAME_LOCKS
00896 VERBOSE(VB_PLAYBACK, QString("unlocking frames:%1 %2 %3")
00897 .arg(DebugString(vec)).arg(GetStatus()).arg(owner));
00898 #endif
00899 for (uint i=0; i<vec.size(); i++)
00900 UnlockFrame(vec[i], "");
00901 }
00902
00903 void VideoBuffers::AddInheritence(const VideoFrame *frame)
00904 {
00905 (void)frame;
00906 #ifdef USING_XVMC
00907 QMutexLocker locker(&global_lock);
00908
00909 frame_map_t::iterator it = parents.find(frame);
00910 if (it == parents.end())
00911 {
00912
00913 frame_queue_t new_parents;
00914 VideoFrame *past = PastFrame(frame);
00915 if (past == frame)
00916 VERBOSE(VB_IMPORTANT, QString("AddInheritence(%1) Error, past=frame")
00917 .arg(DebugString(frame)));
00918 else if (past)
00919 {
00920 bool in_correct_buffer =
00921 used.contains(past) || displayed.contains(past) ||
00922 limbo.contains(past) || pause.contains(past);
00923 if (in_correct_buffer)
00924 new_parents.push_back(past);
00925 else
00926 VERBOSE(VB_IMPORTANT, QString("AddInheritence past %1 NOT "
00927 "in used or in done. %2")
00928 .arg(DebugString(past)).arg(GetStatus()));
00929 }
00930
00931 VideoFrame *future = FutureFrame(frame);
00932 if (future == frame)
00933 VERBOSE(VB_IMPORTANT, QString("AddInheritence(%1) Error, future=frame")
00934 .arg(DebugString(frame)));
00935 else if (future)
00936 {
00937 if (used.contains(future) || limbo.contains(future))
00938 new_parents.push_back(future);
00939 else
00940 VERBOSE(VB_IMPORTANT, QString("AddInheritence future %1 NOT "
00941 "in used or in limbo. %2")
00942 .arg(DebugString(future)).arg(GetStatus()));
00943 }
00944
00945 parents[frame] = new_parents;
00946
00947 frame_queue_t::iterator it = new_parents.begin();
00948 for (; it != new_parents.end(); ++it)
00949 children[*it].push_back((VideoFrame*)frame);
00950 }
00951 #endif // USING_XVMC
00952 }
00953
00954 void VideoBuffers::RemoveInheritence(const VideoFrame *frame)
00955 {
00956 QMutexLocker locker(&global_lock);
00957
00958 frame_map_t::iterator it = parents.find(frame);
00959 if (it == parents.end())
00960 return;
00961
00962 frame_queue_t new_parents;
00963 frame_queue_t &p = it->second;
00964 for (frame_queue_t::iterator pit = p.begin(); pit != p.end(); ++pit)
00965 {
00966 frame_map_t::iterator cit = children.find(*pit);
00967 if (cit != children.end())
00968 {
00969 frame_queue_t::iterator fit = cit->second.find((VideoFrame*)frame);
00970 if (fit != cit->second.end())
00971 cit->second.erase(fit);
00972 else
00973 new_parents.push_back(*pit);
00974 }
00975 }
00976
00977 if (new_parents.empty())
00978 parents.erase(it);
00979 else
00980 {
00981 parents[frame] = new_parents;
00982 VERBOSE(VB_IMPORTANT, QString("RemoveInheritenc:%1 parents.size() = ")
00983 .arg(DebugString(frame)).arg(parents.size()));
00984 frame_queue_t::iterator pit = new_parents.begin();
00985 for (int i=0; pit != new_parents.end() && i<8; (++pit), (++i))
00986 VERBOSE(VB_IMPORTANT, QString("Parent #%1: %2")
00987 .arg(i).arg(DebugString(*pit)));
00988 }
00989 }
00990
00991 frame_queue_t VideoBuffers::Children(const VideoFrame *frame)
00992 {
00993 QMutexLocker locker(&global_lock);
00994
00995 frame_queue_t c;
00996 frame_map_t::iterator it = children.find(frame);
00997 if (it != children.end())
00998 c = it->second;
00999 return c;
01000 }
01001
01002 bool VideoBuffers::HasChildren(const VideoFrame *frame)
01003 {
01004 QMutexLocker locker(&global_lock);
01005
01006 frame_map_t::iterator it = children.find(frame);
01007 if (it != children.end())
01008 return !(it->second.empty());
01009 return false;
01010 }
01011
01012 #ifdef USING_XVMC
01013
01014 inline xvmc_render_state_t *GetRender(VideoFrame *frame)
01015 {
01016 if (frame)
01017 return (xvmc_render_state_t*) frame->buf;
01018 else
01019 return NULL;
01020 }
01021
01022 inline const xvmc_render_state_t *GetRender(const VideoFrame *frame)
01023 {
01024 if (frame)
01025 return (const xvmc_render_state_t*) frame->buf;
01026 else
01027 return NULL;
01028 }
01029
01030 VideoFrame* VideoBuffers::PastFrame(const VideoFrame *frame)
01031 {
01032 LockFrame(frame, "PastFrame");
01033 const xvmc_render_state_t* r = GetRender(frame);
01034 VideoFrame* f = NULL;
01035 if (r)
01036 f = xvmc_surf_to_frame[r->p_past_surface];
01037 UnlockFrame(frame, "PastFrame");
01038 return f;
01039 }
01040
01041 VideoFrame* VideoBuffers::FutureFrame(const VideoFrame *frame)
01042 {
01043 LockFrame(frame, "FutureFrame");
01044 const xvmc_render_state_t* r = GetRender(frame);
01045 VideoFrame* f = NULL;
01046 if (r)
01047 f = xvmc_surf_to_frame[r->p_future_surface];
01048 UnlockFrame(frame, "FutureFrame");
01049 return f;
01050 }
01051
01052 VideoFrame* VideoBuffers::GetOSDFrame(const VideoFrame *frame)
01053 {
01054 LockFrame(frame, "GetOSDFrame");
01055 const xvmc_render_state_t* r = GetRender(frame);
01056 VideoFrame* f = NULL;
01057 if (r)
01058 f = (VideoFrame*) (r->p_osd_target_surface_render);
01059
01060 QString dbg_str("GetOSDFrame ");
01061 #if DEBUG_FRAME_LOCKS
01062 if (f)
01063 dbg_str.append(DebugString(f, true));
01064 #endif
01065 UnlockFrame(frame, dbg_str);
01066
01067 return f;
01068 }
01069
01070 void VideoBuffers::SetOSDFrame(VideoFrame *frame, VideoFrame *osd)
01071 {
01072 if (frame == osd)
01073 {
01074 VERBOSE(VB_IMPORTANT, QString("SetOSDFrame() -- frame==osd %1")
01075 .arg(GetStatus()));
01076 return;
01077 }
01078
01079 LockFrame(frame, "SetOSDFrame");
01080 xvmc_render_state_t* r = GetRender(frame);
01081 if (r)
01082 {
01083 QMutexLocker locker(&global_lock);
01084
01085 VideoFrame* old_osd = (VideoFrame*) r->p_osd_target_surface_render;
01086 if (old_osd)
01087 xvmc_osd_parent[old_osd] = NULL;
01088
01089 r->p_osd_target_surface_render = osd;
01090
01091 if (osd)
01092 xvmc_osd_parent[osd] = frame;
01093 }
01094
01095 UnlockFrame(frame, "SetOSDFrame");
01096 }
01097
01098 VideoFrame* VideoBuffers::GetOSDParent(const VideoFrame *osd)
01099 {
01100 QMutexLocker locker(&global_lock);
01101 return xvmc_osd_parent[osd];
01102 }
01103
01104 #endif
01105
01106 bool VideoBuffers::CreateBuffers(int width, int height)
01107 {
01108 vector<unsigned char*> bufs;
01109 vector<YUVInfo> yuvinfo;
01110 return CreateBuffers(width, height, bufs, yuvinfo);
01111 }
01112
01113 bool VideoBuffers::CreateBuffers(int width, int height,
01114 vector<unsigned char*> bufs,
01115 vector<YUVInfo> yuvinfo)
01116 {
01117 bool ok = true;
01118 uint bpp = 12 / 4;
01119 uint bpb = 8 / 4;
01120
01121
01122
01123
01124 uint adj_w = (width + 15) & ~0xF;
01125 uint adj_h = (height + 15) & ~0xF;
01126 uint buf_size = (adj_w * adj_h * bpp + 4) / bpb;
01127
01128 while (bufs.size() < allocSize())
01129 {
01130 unsigned char *data = (unsigned char*)av_malloc(buf_size + 64);
01131
01132 bufs.push_back(data);
01133 yuvinfo.push_back(YUVInfo(width, height, buf_size, NULL, NULL));
01134
01135 if (bufs.back())
01136 {
01137 VERBOSE(VB_PLAYBACK, "Created data @"
01138 <<((void*)data)<<"->"<<((void*)(data+buf_size)));
01139 allocated_arrays.push_back(bufs.back());
01140 }
01141 else
01142 ok = false;
01143 }
01144
01145 for (uint i = 0; i < allocSize(); i++)
01146 {
01147 init(&buffers[i],
01148 FMT_YV12, bufs[i], yuvinfo[i].width, yuvinfo[i].height,
01149 12, max(buf_size, yuvinfo[i].size),
01150 (const int*) yuvinfo[i].pitches, (const int*) yuvinfo[i].offsets);
01151
01152 ok &= (bufs[i] != NULL);
01153 }
01154
01155 Clear(GUID_I420_PLANAR);
01156
01157 return ok;
01158 }
01159
01160 #ifdef USING_XVMC
01161 bool VideoBuffers::CreateBuffers(int width, int height,
01162 Display *disp,
01163 void *p_xvmc_ctx,
01164 void *p_xvmc_surf_info,
01165 vector<void*> surfs)
01166 {
01167 XvMCContext &xvmc_ctx = *((XvMCContext*) p_xvmc_ctx);
01168 XvMCSurfaceInfo &xvmc_surf_info = *((XvMCSurfaceInfo*) p_xvmc_surf_info);
01169
01170 static unsigned char *ffmpeg_vld_hack = (unsigned char*)
01171 "avlib should not use this private data in XvMC-VLD mode.";
01172
01173 if (surfs.size()>allocSize())
01174 {
01175 VERBOSE(VB_PLAYBACK,
01176 QString("Allocated %1 XvMC surfaces, minimum was %2 surfaces")
01177 .arg(surfs.size()).arg(allocSize()));
01178
01179 Reset();
01180 uint increment = surfs.size() - allocSize();
01181
01182 Init(surfs.size(),
01183 false ,
01184 needfreeframes,
01185 needprebufferframes_normal + increment - 1,
01186 needprebufferframes_small,
01187 keepprebufferframes + 1);
01188 }
01189
01190 for (uint i = 0; i < allocSize(); i++)
01191 {
01192 xvmc_vo_surf_t *surf = (xvmc_vo_surf_t*) surfs[i];
01193 xvmc_render_state_t *render = new xvmc_render_state_t;
01194 allocated_structs.push_back((unsigned char*)render);
01195 memset(render, 0, sizeof(xvmc_render_state_t));
01196
01197
01198 render->magic = MP_XVMC_RENDER_MAGIC;
01199 render->state = 0;
01200
01201
01202 render->disp = disp;
01203 render->ctx = &xvmc_ctx;
01204
01205
01206 render->p_surface = &surf->surface;
01207
01208 render->total_number_of_data_blocks = surf->blocks.num_blocks;
01209 render->total_number_of_mv_blocks = surf->macro_blocks.num_blocks;
01210
01211 init(&buffers[i],
01212 FMT_XVMC_IDCT_MPEG2, (unsigned char*) render,
01213 width, height, -1, sizeof(XvMCSurface));
01214
01215 buffers[i].priv[0] = ffmpeg_vld_hack;
01216 buffers[i].priv[1] = ffmpeg_vld_hack;
01217
01218 if (surf->blocks.blocks)
01219 {
01220 render->data_blocks = surf->blocks.blocks;
01221 buffers[i].priv[0] = (unsigned char*) &(surf->blocks);
01222
01223 render->mv_blocks = surf->macro_blocks.macro_blocks;
01224 buffers[i].priv[1] = (unsigned char*) &(surf->macro_blocks);
01225 }
01226
01227
01228 render->mc_type = xvmc_surf_info.mc_type;
01229 render->idct = (xvmc_surf_info.mc_type & XVMC_IDCT) == XVMC_IDCT;
01230 render->chroma_format = xvmc_surf_info.chroma_format;
01231 render->unsigned_intra = (xvmc_surf_info.flags &
01232 XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED;
01233
01234 xvmc_surf_to_frame[render->p_surface] = &buffers[i];
01235 }
01236 return true;
01237 }
01238 #endif
01239
01240 void VideoBuffers::DeleteBuffers()
01241 {
01242 next_dbg_str = 0;
01243 for (uint i = 0; i < allocSize(); i++)
01244 {
01245 buffers[i].buf = NULL;
01246
01247 if (buffers[i].qscale_table)
01248 {
01249 delete [] buffers[i].qscale_table;
01250 buffers[i].qscale_table = NULL;
01251 }
01252 }
01253
01254 for (uint i = 0; i < allocated_structs.size(); i++)
01255 delete allocated_structs[i];
01256 allocated_structs.clear();
01257
01258 for (uint i = 0; i < allocated_arrays.size(); i++)
01259 av_free(allocated_arrays[i]);
01260 allocated_arrays.clear();
01261 #ifdef USING_XVMC
01262 xvmc_surf_to_frame.clear();
01263 #endif
01264 }
01265
01266 static unsigned long long to_bitmap(const frame_queue_t& list);
01267 QString VideoBuffers::GetStatus(int n) const
01268 {
01269 if (0 > n)
01270 n = numbuffers;
01271
01272 QString str("");
01273 if (global_lock.tryLock())
01274 {
01275 unsigned long long a = to_bitmap(available);
01276 unsigned long long u = to_bitmap(used);
01277 unsigned long long d = to_bitmap(displayed);
01278 unsigned long long l = to_bitmap(limbo);
01279 unsigned long long p = to_bitmap(pause);
01280 unsigned long long x = to_bitmap(decode);
01281 for (uint i=0; i<(uint)n; i++)
01282 {
01283 unsigned long long mask = 1<<i;
01284 QString tmp("");
01285 if (a & mask)
01286 tmp += (x & mask) ? "a" : "A";
01287 if (u & mask)
01288 tmp += (x & mask) ? "u" : "U";
01289 if (d & mask)
01290 tmp += (x & mask) ? "d" : "D";
01291 if (l & mask)
01292 tmp += (x & mask) ? "l" : "L";
01293 if (p & mask)
01294 tmp += (x & mask) ? "p" : "P";
01295
01296 if (0 == tmp.length())
01297 str += " ";
01298 else if (1 == tmp.length())
01299 str += tmp;
01300 else
01301 str += "(" + tmp + ")";
01302 }
01303 global_lock.unlock();
01304 }
01305 else
01306 {
01307 for (uint i=0; i<(uint)n; i++)
01308 str += " ";
01309 }
01310 return str;
01311 }
01312
01313 void VideoBuffers::Clear(uint i, int fourcc)
01314 {
01315 clear(at(i), fourcc);
01316 }
01317
01318 void VideoBuffers::Clear(int fourcc)
01319 {
01320 for (uint i = 0; i < allocSize(); i++)
01321 Clear(i, fourcc);
01322 }
01323
01324
01325
01326
01327
01328 #define DBG_STR_ARR_SIZE 40
01329 QString dbg_str_arr[DBG_STR_ARR_SIZE] =
01330 {
01331 "A ", " B ", " C ", " D ",
01332 " E ", " F ", " G ", " H",
01333 "a ", " b ", " c ", " d ",
01334 " e ", " f ", " g ", " h",
01335 "0 ", " 1 ", " 2 ", " 3 ",
01336 " 4 ", " 5 ", " 6 ", " 7",
01337 "I ", " J ", " K ", " L ",
01338 " M ", " N ", " O ", " P",
01339 "i ", " j ", " k ", " l ",
01340 " m ", " n ", " o ", " p",
01341 };
01342 QString dbg_str_arr_short[DBG_STR_ARR_SIZE] =
01343 {
01344 "A","B","C","D","E","F","G","H",
01345 "a","b","c","d","e","f","g","h",
01346 "0","1","2","3","4","5","6","7",
01347 "I","J","K","L","M","N","O","P",
01348 "i","j","k","l","m","n","o","p",
01349 };
01350
01351 map<const VideoFrame *, int> dbg_str;
01352
01353 int DebugNum(const VideoFrame *frame)
01354 {
01355 map<const VideoFrame *, int>::iterator it = dbg_str.find(frame);
01356 if (it == dbg_str.end())
01357 {
01358 dbg_str[frame] = next_dbg_str;
01359 next_dbg_str = (next_dbg_str+1) % DBG_STR_ARR_SIZE;
01360 }
01361 return dbg_str[frame];
01362 }
01363
01364 const QString& DebugString(const VideoFrame *frame, bool short_str)
01365 {
01366 if (short_str)
01367 return dbg_str_arr_short[DebugNum(frame)];
01368 else
01369 return dbg_str_arr[DebugNum(frame)];
01370 }
01371
01372 const QString& DebugString(uint i, bool short_str)
01373 {
01374 return ((short_str) ? dbg_str_arr_short : dbg_str_arr)[i];
01375 }
01376
01377 static unsigned long long to_bitmap(const frame_queue_t& list)
01378 {
01379 unsigned long long bitmap = 0;
01380 frame_queue_t::const_iterator it = list.begin();
01381 for (; it != list.end(); ++it)
01382 {
01383 int shift = DebugNum(*it);
01384 bitmap |= 1<<shift;
01385 }
01386 return bitmap;
01387 }
01388
01389 static QString bitmap_to_string(unsigned long long bitmap)
01390 {
01391 QString str("");
01392 for (int i=0; i<8; i++)
01393 str += ((bitmap>>i)&1) ? DebugString(i, true) : " ";
01394 return str;
01395 }
01396
01397 const QString DebugString(const frame_queue_t& list)
01398 {
01399 return bitmap_to_string(to_bitmap(list));
01400 }
01401
01402 const QString DebugString(const vector<const VideoFrame*>& list)
01403 {
01404
01405 unsigned long long bitmap = 0;
01406 vector<const VideoFrame*>::const_iterator it = list.begin();
01407 for (; it != list.end(); ++it)
01408 {
01409 int shift = DebugNum(*it);
01410 bitmap |= 1<<shift;
01411 }
01412
01413 return bitmap_to_string(bitmap);
01414 }