MythTV  master
mythcommflagplayer.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QRunnable>
3 
4 // MythTV
5 #include "mthreadpool.h"
6 #include "mythlogging.h"
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  int save_timeout = 1001;
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() > 2534)
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  usleep(200 * 1000);
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() > 98)
142  {
143  ui_timer.restart();
144 
145  if (m_totalFrames)
146  {
147  float elapsed = flagTime.elapsed() * 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  usleep(10000);
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:48
MARK_KEYFRAME
@ MARK_KEYFRAME
Definition: programtypes.h:62
MythRebuildSaver::m_last
uint64_t m_last
Definition: mythcommflagplayer.h:18
DecoderBase::TrackTotalDuration
void TrackTotalDuration(bool track)
Definition: decoderbase.h:260
PlayerContext::UnlockPlayingInfo
void UnlockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:248
LOC
#define LOC
Definition: mythcommflagplayer.cpp:17
MythPlayer::m_decoderThread
MythDecoderThread * m_decoderThread
Definition: mythplayer.h:465
kEofStateNone
@ kEofStateNone
Definition: decoderbase.h:69
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:14
mythcommflagplayer.h
MythPlayer::OpenFile
virtual int OpenFile(int Retries=4)
Definition: mythplayer.cpp:515
DecoderBase::SavePositionMapDelta
uint64_t SavePositionMapDelta(long long first_frame, long long last_frame)
Definition: decoderbase.cpp:494
arg
arg(title).arg(filename).arg(doDelete))
Context
QHash< QString, Action * > Context
Definition: action.h:77
MythPlayer::SaveTotalFrames
void SaveTotalFrames(void)
Definition: mythplayer.cpp:3072
MythRebuildSaver
Definition: mythcommflagplayer.h:8
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
ProgramInfo::UpdateInUseMark
void UpdateInUseMark(bool force=false)
Definition: programinfo.cpp:4701
PlayerFlags
PlayerFlags
Definition: mythplayer.h:79
MythPlayer::GetEof
EofState GetEof(void) const
Definition: mythplayer.cpp:1884
MythPlayer
Definition: mythplayer.h:100
MythPlayer::kInaccuracyNone
static const double kInaccuracyNone
Definition: mythplayer.h:283
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:461
Decoder
Definition: decoder.h:66
MythPlayer::m_framesPlayed
uint64_t m_framesPlayed
Definition: mythplayer.h:522
mythlogging.h
MythVideoOutput::ValidVideoFrames
virtual int ValidVideoFrames() const
Returns number of frames that are fully decoded.
Definition: mythvideoout.cpp:322
MythRebuildSaver::m_decoder
DecoderBase * m_decoder
Definition: mythcommflagplayer.h:16
PlayerContext::m_playingInfo
ProgramInfo * m_playingInfo
Currently playing info.
Definition: playercontext.h:119
MARK_DURATION_MS
@ MARK_DURATION_MS
Definition: programtypes.h:74
MythPlayer::DecoderGetFrame
bool DecoderGetFrame(DecodeType decodetype, bool unsafe=false)
Definition: mythplayer.cpp:2016
PlayerContext::LockPlayingInfo
void LockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:236
MARK_GOP_START
@ MARK_GOP_START
Definition: programtypes.h:61
MythPlayer::m_videoOutput
MythVideoOutput * m_videoOutput
Definition: mythplayer.h:463
MythPlayer::InitVideo
virtual bool InitVideo(void)
Definition: mythplayer.cpp:314
MythPlayer::ClearAfterSeek
void ClearAfterSeek(bool clearvideobuffers=true)
This is to support seeking...
Definition: mythplayer.cpp:2479
MythPlayer::m_totalFrames
uint64_t m_totalFrames
Definition: mythplayer.h:523
MythPlayer::m_playerCtx
PlayerContext * m_playerCtx
Definition: mythplayer.h:464
uint
unsigned int uint
Definition: compat.h:140
MythRebuildSaver::s_wait
static QWaitCondition s_wait
Definition: mythcommflagplayer.h:21
MythPlayer::DoJumpToFrame
void DoJumpToFrame(uint64_t frame, double inaccuracy)
Definition: mythplayer.cpp:2410
kDecodeNothing
@ kDecodeNothing
Definition: decoderbase.h:49
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:459
mthreadpool.h
MythRebuildSaver::run
void run() override
Definition: mythcommflagplayer.cpp:28
MythTimer::elapsed
int elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:90
MythRebuildSaver::s_lock
static QMutex s_lock
Definition: mythcommflagplayer.h:20
MARK_GOP_BYFRAME
@ MARK_GOP_BYFRAME
Definition: programtypes.h:64
ProgramInfo::ClearPositionMap
void ClearPositionMap(MarkTypes type) const
Definition: programinfo.cpp:3631
MythPlayer::m_decodeOneFrame
bool m_decodeOneFrame
Definition: mythplayer.h:487
MythPlayer::SetPlaying
void SetPlaying(bool is_playing)
Definition: mythplayer.cpp:286
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:3056
MythVideoFrame
Definition: mythframe.h:83
DecoderBase::Reset
virtual void Reset(bool reset_video_data, bool seek_reset, bool reset_file)
Definition: decoderbase.cpp:42
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:360
MThreadPool::globalInstance
static MThreadPool * globalInstance(void)
Definition: mthreadpool.cpp:306
DecoderBase::GetFramesRead
long long GetFramesRead(void) const
Definition: decoderbase.h:202
DecoderBase::DoRewind
virtual bool DoRewind(long long desiredFrame, bool discardFrames=true)
Definition: decoderbase.cpp:549
DecoderBase::HasPositionMap
bool HasPositionMap(void) const
Definition: decoderbase.h:226
MythTimer::restart
int restart(void)
Returns milliseconds elapsed since last start() or restart() and resets the count.
Definition: mythtimer.cpp:62
MThreadPool::start
void start(QRunnable *runnable, const QString &debugName, int priority=0)
Definition: mthreadpool.cpp:341
DecoderBase
Definition: decoderbase.h:121
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:486
MythPlayer::DecoderStart
virtual void DecoderStart(bool start_paused)
Definition: mythplayer.cpp:1833
MythRebuildSaver::GetCount
static uint GetCount(DecoderBase *Decoder)
Definition: mythcommflagplayer.cpp:38
m_last
struct exc__state * m_last
Definition: pxsup2dast.c:94
MythRebuildSaver::m_first
uint64_t m_first
Definition: mythcommflagplayer.h:17