MythTV  master
mythpreviewplayer.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QThread>
3 
4 // MythTV
5 #include "mythpreviewplayer.h"
6 
7 #define LOC QString("PreviewPlayer: ")
8 
10  : MythPlayer(Context, Flags)
11 {
12 }
13 
28 char *MythPreviewPlayer::GetScreenGrab(int SecondsIn, int& BufferSize,
29  int& FrameWidth, int& FrameHeight, float& AspectRatio)
30 {
31  auto frameNum = static_cast<uint64_t>(SecondsIn * m_videoFrameRate);
32  return GetScreenGrabAtFrame(frameNum, false, BufferSize, FrameWidth, FrameHeight, AspectRatio);
33 }
34 
50 char *MythPreviewPlayer::GetScreenGrabAtFrame(uint64_t FrameNum, bool Absolute, int& BufferSize,
51  int& FrameWidth, int& FrameHeight, float& AspectRatio)
52 {
53  BufferSize = 0;
54  FrameWidth = FrameHeight = 0;
55  AspectRatio = 0;
56 
57  if (OpenFile(0) < 0)
58  {
59  LOG(VB_GENERAL, LOG_ERR, LOC + "Could not open file for preview.");
60  return nullptr;
61  }
62 
63  bool fail = false;
64 
65  // No video to grab
66  if ((m_videoDim.width() <= 0) || (m_videoDim.height() <= 0))
67  {
68  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("No video for preview in file '%1'")
70  fail = true;
71  }
72 
73  // We may have a BluRay or DVD buffer but this class does not inherit
74  // from MythBDPlayer or MythDVDPlayer - so no seeking/grabbing
75  if (m_playerCtx->m_buffer->IsBD())
76  {
77  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Cannot generate preview for BluRay file '%1'")
79  fail = true;
80  }
81 
82  if (m_playerCtx->m_buffer->IsDVD())
83  {
84  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Cannot generate preview for DVD file '%1'")
86  fail = true;
87  }
88 
89  if (fail)
90  {
91  FrameWidth = 640;
92  FrameHeight = 480;
93  AspectRatio = 4.0F / 3.0F;
94  BufferSize = FrameWidth * FrameHeight * 4;
95  char* result = new char[static_cast<size_t>(BufferSize)];
96  memset(result, 0x3f, static_cast<size_t>(BufferSize) * sizeof(char));
97  return result;
98  }
99 
100  if (!InitVideo())
101  {
102  LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to initialize video for screen grab.");
103  return nullptr;
104  }
105 
106  ClearAfterSeek();
107  if (!m_decoderThread)
108  DecoderStart(true /*start paused*/);
109  uint64_t dummy = 0;
110  SeekForScreenGrab(dummy, FrameNum, Absolute);
111  int tries = 0;
112  while (!m_videoOutput->ValidVideoFrames() && (tries < 500))
113  {
114  tries += 1;
115  m_decodeOneFrame = true;
116  QThread::usleep(10000);
117  if ((tries % 10) == 0)
118  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Waited 100ms for video frame");
119  }
120 
121  MythVideoFrame *frame = nullptr;
122  if (!(frame = m_videoOutput->GetLastDecodedFrame()))
123  return nullptr;
124  if (!frame->m_buffer)
125  return nullptr;
126 
127  if (frame->m_interlaced)
128  {
129  // Use high quality - which is currently yadif
132  MythDeinterlacer deinterlacer;
133  deinterlacer.Filter(frame, kScan_Interlaced, nullptr, true);
134  }
135  uint8_t* result = MythVideoFrame::CreateBuffer(FMT_RGB32, m_videoDim.width(), m_videoDim.height());
136  MythAVCopy copyCtx;
137  AVFrame retbuf;
138  memset(&retbuf, 0, sizeof(AVFrame));
139  copyCtx.Copy(&retbuf, frame, result, AV_PIX_FMT_RGB32);
140  FrameWidth = m_videoDispDim.width();
141  FrameHeight = m_videoDispDim.height();
142  AspectRatio = frame->m_aspect;
143 
144  DiscardVideoFrame(frame);
145  return reinterpret_cast<char*>(result);
146 }
147 
148 void MythPreviewPlayer::SeekForScreenGrab(uint64_t& Number, uint64_t FrameNum, bool Absolute)
149 {
150  Number = FrameNum;
151  if (Number >= m_totalFrames)
152  {
153  LOG(VB_PLAYBACK, LOG_ERR, LOC + "Screen grab requested for frame number beyond end of file.");
154  Number = m_totalFrames / 2;
155  }
156 
157  if (!Absolute && m_hasFullPositionMap)
158  {
160  // Use the bookmark if we should, otherwise make sure we aren't
161  // in the cutlist or a commercial break
162  if (m_bookmarkSeek > 30)
163  {
164  Number = m_bookmarkSeek;
165  }
166  else
167  {
168  uint64_t oldnumber = Number;
171 
172  bool started_in_break_map = false;
173  while (m_commBreakMap.IsInCommBreak(Number) || IsInDelete(Number))
174  {
175  started_in_break_map = true;
176  Number += static_cast<uint64_t>(30 * m_videoFrameRate);
177  if (Number >= m_totalFrames)
178  {
179  Number = oldnumber;
180  break;
181  }
182  }
183 
184  // Advance a few seconds from the end of the break
185  if (started_in_break_map)
186  {
187  oldnumber = Number;
188  Number += static_cast<uint64_t>(10 * m_videoFrameRate);
189  if (Number >= m_totalFrames)
190  Number = oldnumber;
191  }
192  }
193  }
194 
197 }
MythVideoFrame::m_interlaced
int m_interlaced
Definition: mythframe.h:131
MythPlayer::m_commBreakMap
CommBreakMap m_commBreakMap
Definition: mythplayer.h:481
MythPlayer::m_decoderThread
MythDecoderThread * m_decoderThread
Definition: mythplayer.h:371
MythVideoFrame::m_deinterlaceAllowed
MythDeintType m_deinterlaceAllowed
Definition: mythframe.h:156
LOC
#define LOC
Definition: mythpreviewplayer.cpp:7
MythPlayer::OpenFile
virtual int OpenFile(int Retries=4)
Definition: mythplayer.cpp:420
DEINT_NONE
@ DEINT_NONE
Definition: mythframe.h:67
arg
arg(title).arg(filename).arg(doDelete))
MythPreviewPlayer::GetScreenGrab
char * GetScreenGrab(int SecondsIn, int &BufferSize, int &FrameWidth, int &FrameHeight, float &AspectRatio)
Returns one RGB frame grab from a video.
Definition: mythpreviewplayer.cpp:28
MythMediaBuffer::IsDVD
bool IsDVD(void) const
Definition: mythmediabuffer.cpp:1823
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythMediaBuffer::GetSafeFilename
QString GetSafeFilename(void)
Definition: mythmediabuffer.cpp:1740
PlayerFlags
PlayerFlags
Definition: mythplayer.h:62
MythPreviewPlayer::SeekForScreenGrab
void SeekForScreenGrab(uint64_t &Number, uint64_t FrameNum, bool Absolute)
Definition: mythpreviewplayer.cpp:148
MythPlayer
Definition: mythplayer.h:83
MythMediaBuffer::IsBD
bool IsBD(void) const
Definition: mythmediabuffer.cpp:1828
MythPlayer::GetBookmark
virtual uint64_t GetBookmark(void)
Definition: mythplayer.cpp:1278
MythPlayer::kInaccuracyNone
static const double kInaccuracyNone
Definition: mythplayer.h:244
DEINT_CPU
@ DEINT_CPU
Definition: mythframe.h:71
AVFrame
struct AVFrame AVFrame
Definition: BorderDetector.h:15
MythVideoFrame::m_deinterlaceDouble
MythDeintType m_deinterlaceDouble
Definition: mythframe.h:155
MythPlayer::m_framesPlayed
uint64_t m_framesPlayed
Definition: mythplayer.h:428
MythVideoOutput::ValidVideoFrames
virtual int ValidVideoFrames() const
Returns number of frames that are fully decoded.
Definition: mythvideoout.cpp:275
MythPlayer::m_bookmarkSeek
uint64_t m_bookmarkSeek
Definition: mythplayer.h:416
MythPlayer::m_videoOutput
MythVideoOutput * m_videoOutput
Definition: mythplayer.h:368
MythPlayer::m_hasFullPositionMap
bool m_hasFullPositionMap
Definition: mythplayer.h:409
MythPlayer::IsInDelete
bool IsInDelete(uint64_t frame)
Definition: mythplayer.cpp:1697
PlayerContext::m_buffer
MythMediaBuffer * m_buffer
Definition: playercontext.h:115
MythPlayer::InitVideo
virtual bool InitVideo(void)
Definition: mythplayer.cpp:276
CommBreakMap::LoadMap
void LoadMap(PlayerContext *player_ctx, uint64_t framesPlayed)
Definition: commbreakmap.cpp:51
MythDeinterlacer::Filter
void Filter(MythVideoFrame *Frame, FrameScanType Scan, MythVideoProfile *Profile, bool Force=false)
Deinterlace Frame if needed.
Definition: mythdeinterlacer.cpp:70
MythPreviewPlayer::MythPreviewPlayer
MythPreviewPlayer(PlayerContext *Context, PlayerFlags Flags=kNoFlags)
Definition: mythpreviewplayer.cpp:9
MythPlayer::ClearAfterSeek
void ClearAfterSeek(bool clearvideobuffers=true)
This is to support seeking...
Definition: mythplayer.cpp:1647
MythDeinterlacer
Handles software based deinterlacing of video frames.
Definition: mythdeinterlacer.h:15
MythVideoFrame::CreateBuffer
static uint8_t * CreateBuffer(VideoFrameType Type, int Width, int Height)
Definition: mythframe.cpp:432
DeleteMap::LoadMap
void LoadMap(const QString &undoMessage="")
Loads the delete map from the database.
Definition: deletemap.cpp:737
MythPlayer::m_totalFrames
uint64_t m_totalFrames
Definition: mythplayer.h:429
MythPlayer::m_videoFrameRate
double m_videoFrameRate
Video (input) Frame Rate (often inaccurate)
Definition: mythplayer.h:439
CommBreakMap::IsInCommBreak
bool IsInCommBreak(uint64_t frameNumber) const
Definition: commbreakmap.cpp:99
MythPlayer::m_playerCtx
PlayerContext * m_playerCtx
Definition: mythplayer.h:370
MythPlayer::m_videoDispDim
QSize m_videoDispDim
Video (input) width & height.
Definition: mythplayer.h:442
MythVideoOutput::GetLastDecodedFrame
virtual MythVideoFrame * GetLastDecodedFrame()
Definition: mythvideoout.cpp:300
MythPlayer::m_deleteMap
DeleteMap m_deleteMap
Definition: mythplayer.h:484
MythPlayer::DoJumpToFrame
void DoJumpToFrame(uint64_t frame, double inaccuracy)
Definition: mythplayer.cpp:1578
kScan_Interlaced
@ kScan_Interlaced
Definition: videoouttypes.h:98
DEINT_HIGH
@ DEINT_HIGH
Definition: mythframe.h:70
MythPlayer::m_decodeOneFrame
bool m_decodeOneFrame
Definition: mythplayer.h:393
PlayerContext
Definition: playercontext.h:48
MythPlayer::m_videoDim
QSize m_videoDim
Video (input) buffer width & height.
Definition: mythplayer.h:443
MythAVCopy
Definition: mythavutil.h:38
MythPreviewPlayer::GetScreenGrabAtFrame
char * GetScreenGrabAtFrame(uint64_t FrameNum, bool Absolute, int &BufferSize, int &FrameWidth, int &FrameHeight, float &AspectRatio)
Returns one RGB frame grab from a video.
Definition: mythpreviewplayer.cpp:50
FMT_RGB32
@ FMT_RGB32
endian dependent format, ARGB or BGRA
Definition: mythframe.h:31
MythVideoFrame
Definition: mythframe.h:85
MythAVCopy::Copy
int Copy(AVFrame *To, const MythVideoFrame *From, unsigned char *Buffer, AVPixelFormat Fmt=AV_PIX_FMT_YUV420P)
Initialise AVFrame and copy contents of VideoFrame frame into it, performing any required conversion.
Definition: mythavutil.cpp:217
mythpreviewplayer.h
MythVideoFrame::m_deinterlaceSingle
MythDeintType m_deinterlaceSingle
Definition: mythframe.h:154
MythVideoFrame::m_aspect
float m_aspect
Definition: mythframe.h:124
MythVideoFrame::m_buffer
uint8_t * m_buffer
Definition: mythframe.h:117
MythPlayer::DecoderStart
virtual void DecoderStart(bool start_paused)
Definition: mythplayer.cpp:1002
MythPlayer::DiscardVideoFrame
void DiscardVideoFrame(MythVideoFrame *buffer)
Places frame in the available frames queue.
Definition: mythplayer.cpp:617