00001 #include <iostream>
00002 using namespace std;
00003
00004 #include <QRunnable>
00005
00006 #include "mythcommflagplayer.h"
00007 #include "mthreadpool.h"
00008 #include "mythlogging.h"
00009
00010 class RebuildSaver : public QRunnable
00011 {
00012 public:
00013 RebuildSaver(DecoderBase *d, uint64_t f, uint64_t l)
00014 : m_decoder(d), m_first(f), m_last(l)
00015 {
00016 QMutexLocker locker(&s_lock);
00017 s_cnt[d]++;
00018 }
00019
00020 virtual void run(void)
00021 {
00022 m_decoder->SavePositionMapDelta(m_first, m_last);
00023
00024 QMutexLocker locker(&s_lock);
00025 s_cnt[m_decoder]--;
00026 if (!s_cnt[m_decoder])
00027 s_wait.wakeAll();
00028 }
00029
00030 static uint GetCount(DecoderBase *d)
00031 {
00032 QMutexLocker locker(&s_lock);
00033 return s_cnt[d];
00034 }
00035
00036 static void Wait(DecoderBase *d)
00037 {
00038 QMutexLocker locker(&s_lock);
00039 if (!s_cnt[d])
00040 return;
00041 while (s_wait.wait(&s_lock))
00042 {
00043 if (!s_cnt[d])
00044 return;
00045 }
00046 }
00047
00048 private:
00049 DecoderBase *m_decoder;
00050 uint64_t m_first;
00051 uint64_t m_last;
00052
00053 static QMutex s_lock;
00054 static QWaitCondition s_wait;
00055 static QMap<DecoderBase*,uint> s_cnt;
00056 };
00057 QMutex RebuildSaver::s_lock;
00058 QWaitCondition RebuildSaver::s_wait;
00059 QMap<DecoderBase*,uint> RebuildSaver::s_cnt;
00060
00061 bool MythCommFlagPlayer::RebuildSeekTable(
00062 bool showPercentage, StatusCallback cb, void* cbData)
00063 {
00064 int percentage = 0;
00065 uint64_t myFramesPlayed = 0, pmap_first = 0, pmap_last = 0;
00066
00067 killdecoder = false;
00068 framesPlayed = 0;
00069
00070
00071 player_ctx->LockPlayingInfo(__FILE__, __LINE__);
00072 if (player_ctx->playingInfo)
00073 {
00074 player_ctx->playingInfo->ClearPositionMap(MARK_KEYFRAME);
00075 player_ctx->playingInfo->ClearPositionMap(MARK_GOP_START);
00076 player_ctx->playingInfo->ClearPositionMap(MARK_GOP_BYFRAME);
00077 }
00078 player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
00079
00080 if (OpenFile() < 0)
00081 return false;
00082
00083 SetPlaying(true);
00084
00085 if (!InitVideo())
00086 {
00087 LOG(VB_GENERAL, LOG_ERR,
00088 "RebuildSeekTable unable to initialize video");
00089 SetPlaying(false);
00090 return false;
00091 }
00092
00093 ClearAfterSeek();
00094
00095 int save_timeout = 1001;
00096 MythTimer flagTime, ui_timer, inuse_timer, save_timer;
00097 flagTime.start();
00098 ui_timer.start();
00099 inuse_timer.start();
00100 save_timer.start();
00101
00102 DecoderGetFrame(kDecodeNothing,true);
00103
00104 if (showPercentage)
00105 cout << "\r \r" << flush;
00106
00107 int prevperc = -1;
00108 while (!GetEof())
00109 {
00110 if (inuse_timer.elapsed() > 2534)
00111 {
00112 inuse_timer.restart();
00113 player_ctx->LockPlayingInfo(__FILE__, __LINE__);
00114 if (player_ctx->playingInfo)
00115 player_ctx->playingInfo->UpdateInUseMark();
00116 player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
00117 }
00118
00119 if (save_timer.elapsed() > save_timeout)
00120 {
00121
00122 if (myFramesPlayed - pmap_last > 5000)
00123 usleep(200 * 1000);
00124
00125
00126 if (RebuildSaver::GetCount(decoder) < 1)
00127 {
00128 pmap_last = myFramesPlayed;
00129 MThreadPool::globalInstance()->start(
00130 new RebuildSaver(decoder, pmap_first, pmap_last),
00131 "RebuildSaver");
00132 pmap_first = pmap_last + 1;
00133 }
00134
00135 save_timer.restart();
00136 }
00137
00138 if (ui_timer.elapsed() > 98)
00139 {
00140 ui_timer.restart();
00141
00142 if (totalFrames)
00143 {
00144 float elapsed = flagTime.elapsed() * 0.001f;
00145 int flagFPS = (elapsed > 0.0f) ?
00146 (int)(myFramesPlayed / elapsed) : 0;
00147
00148 percentage = myFramesPlayed * 100 / totalFrames;
00149 if (cb)
00150 (*cb)(percentage, cbData);
00151
00152 if (showPercentage)
00153 {
00154 QString str = QString("\r%1%/%2fps \r")
00155 .arg(percentage,3).arg(flagFPS,5);
00156 cout << qPrintable(str) << flush;
00157 }
00158 else if (percentage % 10 == 0 && prevperc != percentage)
00159 {
00160 prevperc = percentage;
00161 LOG(VB_GENERAL, LOG_INFO, QString("Progress %1% @ %2fps")
00162 .arg(percentage,3).arg(flagFPS,5));
00163 }
00164 }
00165 else
00166 {
00167 if (showPercentage)
00168 {
00169 QString str = QString("\r%1 \r").arg(myFramesPlayed,6);
00170 cout << qPrintable(str) << flush;
00171 }
00172 else if (myFramesPlayed % 1000 == 0)
00173 {
00174 LOG(VB_GENERAL, LOG_INFO, QString("Frames processed %1")
00175 .arg(myFramesPlayed));
00176 }
00177 }
00178 }
00179
00180 if (DecoderGetFrame(kDecodeNothing,true))
00181 myFramesPlayed = decoder->GetFramesRead();
00182 }
00183
00184 if (showPercentage)
00185 cout << "\r \r" << flush;
00186
00187 SaveTotalDuration();
00188 SaveTotalFrames();
00189
00190 SetPlaying(false);
00191 killdecoder = true;
00192
00193 MThreadPool::globalInstance()->start(
00194 new RebuildSaver(decoder, pmap_first, myFramesPlayed),
00195 "RebuildSaver");
00196 RebuildSaver::Wait(decoder);
00197
00198 return true;
00199 }