MythTV master
mythpreviewplayer.cpp
Go to the documentation of this file.
1// Qt
2#include <QThread>
3
4// MythTV
5#include "mythpreviewplayer.h"
6
8
9#define LOC QString("PreviewPlayer: ")
10
12 : MythPlayer(Context, Flags)
13{
14}
15
30uint8_t *MythPreviewPlayer::GetScreenGrab(std::chrono::seconds SecondsIn, int& BufferSize,
31 int& FrameWidth, int& FrameHeight, float& AspectRatio)
32{
33 auto frameNum = static_cast<uint64_t>(SecondsIn.count() * m_videoFrameRate);
34 return GetScreenGrabAtFrame(frameNum, false, BufferSize, FrameWidth, FrameHeight, AspectRatio);
35}
36
52uint8_t *MythPreviewPlayer::GetScreenGrabAtFrame(uint64_t FrameNum, bool Absolute, int& BufferSize,
53 int& FrameWidth, int& FrameHeight, float& AspectRatio)
54{
55 BufferSize = 0;
56 FrameWidth = FrameHeight = 0;
57 AspectRatio = 0;
58
59 if (OpenFile(0) < 0)
60 {
61 LOG(VB_GENERAL, LOG_ERR, LOC + "Could not open file for preview.");
62 return nullptr;
63 }
64
65 bool fail = false;
66
67 // No video to grab
68 if ((m_videoDim.width() <= 0) || (m_videoDim.height() <= 0))
69 {
70 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("No video for preview in file '%1'")
72 fail = true;
73 }
74
75 // We may have a BluRay or DVD buffer but this class does not inherit
76 // from MythBDPlayer or MythDVDPlayer - so no seeking/grabbing
78 {
79 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Cannot generate preview for BluRay file '%1'")
81 fail = true;
82 }
83
85 {
86 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Cannot generate preview for DVD file '%1'")
88 fail = true;
89 }
90
91 if (fail)
92 {
93 FrameWidth = 640;
94 FrameHeight = 480;
95 AspectRatio = 4.0F / 3.0F;
96 BufferSize = FrameWidth * FrameHeight * 4;
97 auto *result = new uint8_t[static_cast<size_t>(BufferSize)];
98 memset(result, 0x3f, static_cast<size_t>(BufferSize) * sizeof(char));
99 return result;
100 }
101
102 if (!InitVideo())
103 {
104 LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to initialize video for screen grab.");
105 return nullptr;
106 }
107
109 if (!m_decoderThread)
110 DecoderStart(true /*start paused*/);
111 uint64_t dummy = 0;
112 SeekForScreenGrab(dummy, FrameNum, Absolute);
113 int tries = 0;
114 while (!m_videoOutput->ValidVideoFrames() && (tries < 500))
115 {
116 tries += 1;
117 m_decodeOneFrame = true;
118 QThread::usleep(10000);
119 if ((tries % 10) == 0)
120 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Waited 100ms for video frame");
121 }
122
124 if (frame == nullptr)
125 return nullptr;
126 if (!frame->m_buffer)
127 return nullptr;
128
129 if (frame->m_interlaced)
130 {
131 // Use high quality - which is currently yadif
134 MythDeinterlacer deinterlacer;
135 deinterlacer.Filter(frame, kScan_Interlaced, nullptr, true);
136 }
137 uint8_t* result = MythVideoFrame::CreateBuffer(FMT_RGB32, m_videoDim.width(), m_videoDim.height());
138 MythAVCopy copyCtx;
139 AVFrame retbuf;
140 memset(&retbuf, 0, sizeof(AVFrame));
141 copyCtx.Copy(&retbuf, frame, result, AV_PIX_FMT_RGB32);
142 FrameWidth = m_videoDispDim.width();
143 FrameHeight = m_videoDispDim.height();
144 AspectRatio = frame->m_aspect;
145
146 DiscardVideoFrame(frame);
147 return result;
148}
149
150void MythPreviewPlayer::SeekForScreenGrab(uint64_t& Number, uint64_t FrameNum, bool Absolute)
151{
152 Number = FrameNum;
153 if (Number >= m_totalFrames)
154 {
155 LOG(VB_PLAYBACK, LOG_ERR, LOC + "Screen grab requested for frame number beyond end of file.");
156 Number = m_totalFrames / 2;
157 }
158
159 if (!Absolute && m_hasFullPositionMap)
160 {
162 // Use the bookmark if we should, otherwise make sure we aren't
163 // in the cutlist or a commercial break
164 if (m_bookmarkSeek > 30)
165 {
166 Number = m_bookmarkSeek;
167 }
168 else
169 {
170 uint64_t oldnumber = Number;
173
174 bool started_in_break_map = false;
175 while (m_commBreakMap.IsInCommBreak(Number) || IsInDelete(Number))
176 {
177 started_in_break_map = true;
178 Number += static_cast<uint64_t>(30 * m_videoFrameRate);
179 if (Number >= m_totalFrames)
180 {
181 Number = oldnumber;
182 break;
183 }
184 }
185
186 // Advance a few seconds from the end of the break
187 if (started_in_break_map)
188 {
189 oldnumber = Number;
190 Number += static_cast<uint64_t>(10 * m_videoFrameRate);
191 if (Number >= m_totalFrames)
192 Number = oldnumber;
193 }
194 }
195 }
196
199}
AVFrame AVFrame
bool IsInCommBreak(uint64_t frameNumber) const
void LoadMap(PlayerContext *player_ctx, uint64_t framesPlayed)
void LoadMap(const QString &undoMessage="")
Loads the delete map from the database.
Definition: deletemap.cpp:742
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:267
Handles software based deinterlacing of video frames.
void Filter(MythVideoFrame *Frame, FrameScanType Scan, MythVideoProfile *Profile, bool Force=false)
Deinterlace Frame if needed.
QString GetSafeFilename(void)
bool IsDVD(void) const
bool IsBD(void) const
bool m_decodeOneFrame
Definition: mythplayer.h:389
MythDecoderThread * m_decoderThread
Definition: mythplayer.h:367
virtual void DecoderStart(bool start_paused)
DeleteMap m_deleteMap
Definition: mythplayer.h:478
static const double kInaccuracyNone
Definition: mythplayer.h:239
void DoJumpToFrame(uint64_t frame, double inaccuracy)
uint64_t m_framesPlayed
Definition: mythplayer.h:424
CommBreakMap m_commBreakMap
Definition: mythplayer.h:475
virtual int OpenFile(int Retries=4)
Definition: mythplayer.cpp:417
uint64_t m_bookmarkSeek
Definition: mythplayer.h:413
bool IsInDelete(uint64_t frame)
uint64_t m_totalFrames
Definition: mythplayer.h:425
QSize m_videoDispDim
Video (input) width & height.
Definition: mythplayer.h:438
virtual uint64_t GetBookmark(void)
QSize m_videoDim
Video (input) buffer width & height.
Definition: mythplayer.h:439
double m_videoFrameRate
Video (input) Frame Rate (often inaccurate)
Definition: mythplayer.h:435
void ClearAfterSeek(bool clearvideobuffers=true)
This is to support seeking...
bool m_hasFullPositionMap
Definition: mythplayer.h:406
PlayerContext * m_playerCtx
Definition: mythplayer.h:366
MythVideoOutput * m_videoOutput
Definition: mythplayer.h:364
void DiscardVideoFrame(MythVideoFrame *buffer)
Places frame in the available frames queue.
Definition: mythplayer.cpp:626
virtual bool InitVideo(void)
Definition: mythplayer.cpp:270
uint8_t * GetScreenGrabAtFrame(uint64_t FrameNum, bool Absolute, int &BufferSize, int &FrameWidth, int &FrameHeight, float &AspectRatio)
Returns one RGB frame grab from a video.
MythPreviewPlayer(PlayerContext *Context, PlayerFlags Flags=kNoFlags)
uint8_t * GetScreenGrab(std::chrono::seconds SecondsIn, int &BufferSize, int &FrameWidth, int &FrameHeight, float &AspectRatio)
Returns one RGB frame grab from a video.
void SeekForScreenGrab(uint64_t &Number, uint64_t FrameNum, bool Absolute)
bool m_interlaced
Definition: mythframe.h:133
static uint8_t * CreateBuffer(VideoFrameType Type, int Width, int Height)
Definition: mythframe.cpp:435
MythDeintType m_deinterlaceAllowed
Definition: mythframe.h:159
uint8_t * m_buffer
Definition: mythframe.h:119
MythDeintType m_deinterlaceSingle
Definition: mythframe.h:157
float m_aspect
Definition: mythframe.h:126
MythDeintType m_deinterlaceDouble
Definition: mythframe.h:158
virtual int ValidVideoFrames() const
Returns number of frames that are fully decoded.
virtual MythVideoFrame * GetLastDecodedFrame()
MythMediaBuffer * m_buffer
@ DEINT_HIGH
Definition: mythframe.h:71
@ DEINT_NONE
Definition: mythframe.h:68
@ DEINT_CPU
Definition: mythframe.h:72
@ FMT_RGB32
endian dependent format, ARGB or BGRA
Definition: mythframe.h:32
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
PlayerFlags
Definition: mythplayer.h:65
#define LOC
@ kScan_Interlaced
Definition: videoouttypes.h:98