MythTV  master
mythcommflagplayer.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QRunnable>
3 
4 // MythTV
7 #include "mythcommflagplayer.h"
8 
9 // Std
10 #include <unistd.h>
11 #include <iostream>
12 
14 QWaitCondition MythRebuildSaver::s_wait;
15 QHash<DecoderBase*,uint> MythRebuildSaver::s_count;
16 
17 #define LOC QString("CommFlagPlayer: ")
18 
19 MythRebuildSaver::MythRebuildSaver(DecoderBase* Decoder, uint64_t First, uint64_t Last)
20  : m_decoder(Decoder),
21  m_first(First),
22  m_last(Last)
23 {
24  QMutexLocker locker(&s_lock);
25  s_count[Decoder]++;
26 }
27 
29 {
30  m_decoder->SavePositionMapDelta(static_cast<long long>(m_first), static_cast<long long>(m_last));
31 
32  QMutexLocker locker(&s_lock);
33  s_count[m_decoder]--;
34  if (!s_count[m_decoder])
35  s_wait.wakeAll();
36 }
37 
39 {
40  QMutexLocker locker(&s_lock);
41  return s_count[Decoder];
42 }
43 
45 {
46  QMutexLocker locker(&s_lock);
47  if (!s_count[Decoder])
48  return;
49 
50  while (s_wait.wait(&s_lock))
51  if (!s_count[Decoder])
52  return;
53 }
54 
56  : MythPlayer(Context, Flags)
57 {
58 }
59 
60 bool MythCommFlagPlayer::RebuildSeekTable(bool ShowPercentage, StatusCallback Callback, void* Opaque)
61 {
62  uint64_t myFramesPlayed = 0;
63  uint64_t pmap_first = 0;
64  uint64_t pmap_last = 0;
65 
66  m_killDecoder = false;
67  m_framesPlayed = 0;
68 
69  // clear out any existing seektables
70  m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
72  {
77  }
78  m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
79 
80  if (OpenFile() < 0)
81  return false;
82 
83  SetPlaying(true);
84 
85  if (!InitVideo())
86  {
87  LOG(VB_GENERAL, LOG_ERR, "RebuildSeekTable unable to initialize video");
88  SetPlaying(false);
89  return false;
90  }
91 
93 
94  std::chrono::milliseconds save_timeout { 1s + 1ms };
95  MythTimer flagTime;
96  MythTimer ui_timer;
97  MythTimer inuse_timer;
98  MythTimer save_timer;
99  flagTime.start();
100  ui_timer.start();
101  inuse_timer.start();
102  save_timer.start();
103 
105 
106  if (ShowPercentage)
107  std::cout << "\r \r" << std::flush;
108 
109  int prevperc = -1;
110  bool usingIframes = false;
111  while (GetEof() == kEofStateNone)
112  {
113  if (inuse_timer.elapsed() > 2534ms)
114  {
115  inuse_timer.restart();
116  m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
119  m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
120  }
121 
122  if (save_timer.elapsed() > save_timeout)
123  {
124  // Give DB some breathing room if it gets far behind..
125  if (myFramesPlayed - pmap_last > 5000)
126  std::this_thread::sleep_for(200ms);
127 
128  // If we're already saving, just save a larger block next time..
130  {
131  pmap_last = myFramesPlayed;
133  new MythRebuildSaver(m_decoder, pmap_first, pmap_last),
134  "RebuildSaver");
135  pmap_first = pmap_last + 1;
136  }
137 
138  save_timer.restart();
139  }
140 
141  if (ui_timer.elapsed() > 98ms)
142  {
143  ui_timer.restart();
144 
145  if (m_totalFrames)
146  {
147  float elapsed = flagTime.elapsed().count() * 0.001F;
148  auto flagFPS = (elapsed > 0.0F) ? static_cast<int>(myFramesPlayed / elapsed) : 0;
149  auto percentage = static_cast<int>(myFramesPlayed * 100 / m_totalFrames);
150  if (Callback)
151  (*Callback)(percentage, Opaque);
152 
153  if (ShowPercentage)
154  {
155  QString str = QString("\r%1%/%2fps \r").arg(percentage,3).arg(flagFPS,5);
156  std::cout << qPrintable(str) << std::flush;
157  }
158  else if (percentage % 10 == 0 && prevperc != percentage)
159  {
160  prevperc = percentage;
161  LOG(VB_COMMFLAG, LOG_INFO, QString("Progress %1% @ %2fps").arg(percentage,3).arg(flagFPS,5));
162  }
163  }
164  else
165  {
166  if (ShowPercentage)
167  {
168  QString str = QString("\r%1 \r").arg(myFramesPlayed,6);
169  std::cout << qPrintable(str) << std::flush;
170  }
171  else if (myFramesPlayed % 1000 == 0)
172  {
173  LOG(VB_COMMFLAG, LOG_INFO, QString("Frames processed %1").arg(myFramesPlayed));
174  }
175  }
176  }
177 
179  myFramesPlayed = static_cast<uint64_t>(m_decoder->GetFramesRead());
180 
181  // H.264 recordings from an HD-PVR contain IDR keyframes,
182  // which are the only valid cut points for lossless cuts.
183  // However, DVB-S h.264 recordings may lack IDR keyframes, in
184  // which case we need to allow non-IDR I-frames. If we get
185  // far enough into the rebuild without having created any
186  // seektable entries, we can assume it is because of the IDR
187  // keyframe setting, and so we rewind and allow h.264 non-IDR
188  // I-frames to be treated as keyframes.
189  auto frames = static_cast<uint64_t>(m_decoder->GetFramesRead());
190  if (!usingIframes &&
191  (GetEof() != kEofStateNone || (frames > 1000 && frames < 1100)) &&
193  {
194  std::cout << "No I-frames found, rewinding..." << std::endl;
195  m_decoder->DoRewind(0);
196  m_decoder->Reset(true, true, true);
197  pmap_first = pmap_last = myFramesPlayed = 0;
199  usingIframes = true;
200  }
201  }
202 
203  if (ShowPercentage)
204  std::cout << "\r \r" << std::flush;
205 
207  SaveTotalFrames();
208 
209  SetPlaying(false);
210  m_killDecoder = true;
211 
213  new MythRebuildSaver(m_decoder, pmap_first, myFramesPlayed),
214  "RebuildSaver");
216 
217  return true;
218 }
219 
227 {
228  m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
231  m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
232 
233  if (!m_decoderThread)
234  DecoderStart(false);
235 
236  if (FrameNumber >= 0)
237  {
238  DoJumpToFrame(static_cast<uint64_t>(FrameNumber), kInaccuracyNone);
239  ClearAfterSeek();
240  }
241 
242  int tries = 0;
243  while (!m_videoOutput->ValidVideoFrames() && ((tries++) < 100))
244  {
245  m_decodeOneFrame = true;
246  std::this_thread::sleep_for(10ms);
247  if ((tries & 10) == 10)
248  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Waited 100ms for video frame");
249  }
250 
253 }
254 
MythRebuildSaver::s_count
static QHash< DecoderBase *, uint > s_count
Definition: mythcommflagplayer.h:22
StatusCallback
void(*)(int, void *) StatusCallback
Definition: mythplayer.h:51
MythTimer::elapsed
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
MythRebuildSaver::m_last
uint64_t m_last
Definition: mythcommflagplayer.h:18
DecoderBase::TrackTotalDuration
void TrackTotalDuration(bool track)
Definition: decoderbase.h:261
MARK_KEYFRAME
@ MARK_KEYFRAME
Definition: programtypes.h:62
PlayerContext::UnlockPlayingInfo
void UnlockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:249
LOC
#define LOC
Definition: mythcommflagplayer.cpp:17
MythPlayer::m_decoderThread
MythDecoderThread * m_decoderThread
Definition: mythplayer.h:367
MARK_GOP_START
@ MARK_GOP_START
Definition: programtypes.h:61
MythRebuildSaver::Wait
static void Wait(DecoderBase *Decoder)
Definition: mythcommflagplayer.cpp:44
MythTimer
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
mythcommflagplayer.h
MythPlayer::OpenFile
virtual int OpenFile(int Retries=4)
Definition: mythplayer.cpp:420
DecoderBase::SavePositionMapDelta
uint64_t SavePositionMapDelta(long long first_frame, long long last_frame)
Definition: decoderbase.cpp:500
kDecodeNothing
@ kDecodeNothing
Definition: decoderbase.h:49
MythPlayer::SaveTotalFrames
void SaveTotalFrames(void)
Definition: mythplayer.cpp:1979
MythRebuildSaver
Definition: mythcommflagplayer.h:7
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
ProgramInfo::UpdateInUseMark
void UpdateInUseMark(bool force=false)
Definition: programinfo.cpp:4978
PlayerFlags
PlayerFlags
Definition: mythplayer.h:64
MythPlayer::GetEof
EofState GetEof(void) const
Definition: mythplayer.cpp:1067
MythPlayer
Definition: mythplayer.h:83
MythPlayer::kInaccuracyNone
static const double kInaccuracyNone
Definition: mythplayer.h:239
MythCommFlagPlayer::MythCommFlagPlayer
MythCommFlagPlayer(PlayerContext *Context, PlayerFlags Flags=kNoFlags)
Definition: mythcommflagplayer.cpp:55
MythCommFlagPlayer::RebuildSeekTable
bool RebuildSeekTable(bool ShowPercentage=true, StatusCallback Callback=nullptr, void *Opaque=nullptr)
Definition: mythcommflagplayer.cpp:60
MythPlayer::m_decoder
DecoderBase * m_decoder
Definition: mythplayer.h:362
kEofStateNone
@ kEofStateNone
Definition: decoderbase.h:69
Decoder
Definition: decoder.h:70
MythPlayer::m_framesPlayed
uint64_t m_framesPlayed
Definition: mythplayer.h:424
mythlogging.h
MythVideoOutput::ValidVideoFrames
virtual int ValidVideoFrames() const
Returns number of frames that are fully decoded.
Definition: mythvideoout.cpp:278
AutoExtendType::Last
@ Last
MythRebuildSaver::m_decoder
DecoderBase * m_decoder
Definition: mythcommflagplayer.h:16
PlayerContext::m_playingInfo
ProgramInfo * m_playingInfo
Currently playing info.
Definition: playercontext.h:117
MythPlayer::DecoderGetFrame
bool DecoderGetFrame(DecodeType decodetype, bool unsafe=false)
Definition: mythplayer.cpp:1225
PlayerContext::LockPlayingInfo
void LockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:239
MythPlayer::m_videoOutput
MythVideoOutput * m_videoOutput
Definition: mythplayer.h:364
MythPlayer::InitVideo
virtual bool InitVideo(void)
Definition: mythplayer.cpp:273
MythTimer::restart
std::chrono::milliseconds restart(void)
Returns milliseconds elapsed since last start() or restart() and resets the count.
Definition: mythtimer.cpp:62
MythPlayer::ClearAfterSeek
void ClearAfterSeek(bool clearvideobuffers=true)
This is to support seeking...
Definition: mythplayer.cpp:1678
MythPlayer::m_totalFrames
uint64_t m_totalFrames
Definition: mythplayer.h:425
MythPlayer::m_playerCtx
PlayerContext * m_playerCtx
Definition: mythplayer.h:366
uint
unsigned int uint
Definition: compat.h:81
MythRebuildSaver::s_wait
static QWaitCondition s_wait
Definition: mythcommflagplayer.h:21
MARK_GOP_BYFRAME
@ MARK_GOP_BYFRAME
Definition: programtypes.h:64
MythPlayer::DoJumpToFrame
void DoJumpToFrame(uint64_t frame, double inaccuracy)
Definition: mythplayer.cpp:1607
MythVideoOutput::StartDisplayingFrame
virtual void StartDisplayingFrame()
Tell GetLastShownFrame() to return the next frame from the head of the queue of frames to display.
Definition: mythvideoout.cpp:413
mthreadpool.h
MythRebuildSaver::run
void run() override
Definition: mythcommflagplayer.cpp:28
MARK_DURATION_MS
@ MARK_DURATION_MS
Definition: programtypes.h:74
MythRebuildSaver::s_lock
static QMutex s_lock
Definition: mythcommflagplayer.h:20
ProgramInfo::ClearPositionMap
void ClearPositionMap(MarkTypes type) const
Definition: programinfo.cpp:3824
MythPlayer::m_decodeOneFrame
bool m_decodeOneFrame
Definition: mythplayer.h:389
MythPlayer::SetPlaying
void SetPlaying(bool is_playing)
Definition: mythplayer.cpp:245
PlayerContext
Definition: playercontext.h:49
MythRebuildSaver::MythRebuildSaver
MythRebuildSaver(DecoderBase *Decoder, uint64_t First, uint64_t Last)
Definition: mythcommflagplayer.cpp:19
MythPlayer::SaveTotalDuration
void SaveTotalDuration(void)
Definition: mythplayer.cpp:1963
MythVideoFrame
Definition: mythframe.h:88
DecoderBase::Reset
virtual void Reset(bool reset_video_data, bool seek_reset, bool reset_file)
Definition: decoderbase.cpp:48
MythVideoOutput::GetLastShownFrame
virtual MythVideoFrame * GetLastShownFrame()
Returns frame from the head of the ready to be displayed queue, if StartDisplayingFrame has been call...
Definition: mythvideoout.cpp:316
MThreadPool::globalInstance
static MThreadPool * globalInstance(void)
Definition: mthreadpool.cpp:307
DecoderBase::GetFramesRead
long long GetFramesRead(void) const
Definition: decoderbase.h:203
DecoderBase::DoRewind
virtual bool DoRewind(long long desiredFrame, bool discardFrames=true)
Definition: decoderbase.cpp:555
DecoderBase::HasPositionMap
bool HasPositionMap(void) const
Definition: decoderbase.h:227
MThreadPool::start
void start(QRunnable *runnable, const QString &debugName, int priority=0)
Definition: mthreadpool.cpp:342
DecoderBase
Definition: decoderbase.h:120
MythCommFlagPlayer::GetRawVideoFrame
MythVideoFrame * GetRawVideoFrame(long long FrameNumber=-1)
Returns a specific frame from the video.
Definition: mythcommflagplayer.cpp:226
DecoderBase::SetIdrOnlyKeyframes
virtual void SetIdrOnlyKeyframes(bool)
Definition: decoderbase.h:160
MythPlayer::m_killDecoder
bool volatile m_killDecoder
Definition: mythplayer.h:388
MythPlayer::DecoderStart
virtual void DecoderStart(bool start_paused)
Definition: mythplayer.cpp:1016
MythRebuildSaver::GetCount
static uint GetCount(DecoderBase *Decoder)
Definition: mythcommflagplayer.cpp:38
m_last
struct exc__state * m_last
Definition: pxsup2dast.c:91
MythRebuildSaver::m_first
uint64_t m_first
Definition: mythcommflagplayer.h:17