MythTV master
mythpreviewplayer.cpp
Go to the documentation of this file.
1#include <thread>
2
3// MythTV
4#include "mythpreviewplayer.h"
5
7
8#define LOC QString("PreviewPlayer: ")
9
11 : MythPlayer(Context, Flags)
12{
13}
14
29uint8_t *MythPreviewPlayer::GetScreenGrab(std::chrono::seconds SecondsIn, int& BufferSize,
30 int& FrameWidth, int& FrameHeight, float& AspectRatio)
31{
32 auto frameNum = static_cast<uint64_t>(SecondsIn.count() * m_videoFrameRate);
33 return GetScreenGrabAtFrame(frameNum, false, BufferSize, FrameWidth, FrameHeight, AspectRatio);
34}
35
51uint8_t *MythPreviewPlayer::GetScreenGrabAtFrame(uint64_t FrameNum, bool Absolute, int& BufferSize,
52 int& FrameWidth, int& FrameHeight, float& AspectRatio)
53{
54 BufferSize = 0;
55 FrameWidth = FrameHeight = 0;
56 AspectRatio = 0;
57
58 if (OpenFile(0) < 0)
59 {
60 LOG(VB_GENERAL, LOG_ERR, LOC + "Could not open file for preview.");
61 return nullptr;
62 }
63
64 bool fail = false;
65
66 // No video to grab
67 if ((m_videoDim.width() <= 0) || (m_videoDim.height() <= 0))
68 {
69 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("No video for preview in file '%1'")
71 fail = true;
72 }
73
74 // We may have a BluRay or DVD buffer but this class does not inherit
75 // from MythBDPlayer or MythDVDPlayer - so no seeking/grabbing
77 {
78 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Cannot generate preview for BluRay file '%1'")
80 fail = true;
81 }
82
84 {
85 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Cannot generate preview for DVD file '%1'")
87 fail = true;
88 }
89
90 if (fail)
91 {
92 FrameWidth = 640;
93 FrameHeight = 480;
94 AspectRatio = 4.0F / 3.0F;
95 BufferSize = FrameWidth * FrameHeight * 4;
96 auto *result = new uint8_t[static_cast<size_t>(BufferSize)];
97 memset(result, 0x3f, static_cast<size_t>(BufferSize) * sizeof(char));
98 return result;
99 }
100
101 if (!InitVideo())
102 {
103 LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to initialize video for screen grab.");
104 return nullptr;
105 }
106
108 if (!m_decoderThread)
109 DecoderStart(true /*start paused*/);
110 uint64_t dummy = 0;
111 SeekForScreenGrab(dummy, FrameNum, Absolute);
112 int tries = 0;
113 while (!m_videoOutput->ValidVideoFrames() && (tries < 500))
114 {
115 tries += 1;
116 m_decodeOneFrame = true;
117 std::this_thread::sleep_for(10ms);
118 if ((tries % 10) == 0)
119 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Waited 100ms for video frame");
120 }
121
123 if (frame == nullptr)
124 return nullptr;
125 if (!frame->m_buffer)
126 return nullptr;
127
128 if (frame->m_interlaced)
129 {
130 // Use high quality - which is currently yadif
133 MythDeinterlacer deinterlacer;
134 deinterlacer.Filter(frame, kScan_Interlaced, nullptr, true);
135 }
136 uint8_t* result = MythVideoFrame::CreateBuffer(FMT_RGB32, m_videoDim.width(), m_videoDim.height());
137 MythAVCopy copyCtx;
138 AVFrame retbuf;
139 memset(&retbuf, 0, sizeof(AVFrame));
140 copyCtx.Copy(&retbuf, frame, result, AV_PIX_FMT_RGB32);
141 FrameWidth = m_videoDispDim.width();
142 FrameHeight = m_videoDispDim.height();
143 AspectRatio = frame->m_aspect;
144
145 DiscardVideoFrame(frame);
146 return result;
147}
148
149void MythPreviewPlayer::SeekForScreenGrab(uint64_t& Number, uint64_t FrameNum, bool Absolute)
150{
151 Number = FrameNum;
152 if (Number >= m_totalFrames)
153 {
154 LOG(VB_PLAYBACK, LOG_ERR, LOC + "Screen grab requested for frame number beyond end of file.");
155 Number = m_totalFrames / 2;
156 }
157
158 if (!Absolute && m_hasFullPositionMap)
159 {
161 // Use the bookmark if we should, otherwise make sure we aren't
162 // in the cutlist or a commercial break
163 if (m_bookmarkSeek > 30)
164 {
165 Number = m_bookmarkSeek;
166 }
167 else
168 {
169 uint64_t oldnumber = Number;
172
173 bool started_in_break_map = false;
174 while (m_commBreakMap.IsInCommBreak(Number) || IsInDelete(Number))
175 {
176 started_in_break_map = true;
177 Number += static_cast<uint64_t>(30 * m_videoFrameRate);
178 if (Number >= m_totalFrames)
179 {
180 Number = oldnumber;
181 break;
182 }
183 }
184
185 // Advance a few seconds from the end of the break
186 if (started_in_break_map)
187 {
188 oldnumber = Number;
189 Number += static_cast<uint64_t>(10 * m_videoFrameRate);
190 if (Number >= m_totalFrames)
191 Number = oldnumber;
192 }
193 }
194 }
195
198}
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:739
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:388
MythDecoderThread * m_decoderThread
Definition: mythplayer.h:366
virtual void DecoderStart(bool start_paused)
DeleteMap m_deleteMap
Definition: mythplayer.h:478
static const double kInaccuracyNone
Definition: mythplayer.h:238
void DoJumpToFrame(uint64_t frame, double inaccuracy)
uint64_t m_framesPlayed
Definition: mythplayer.h:423
CommBreakMap m_commBreakMap
Definition: mythplayer.h:475
virtual int OpenFile(int Retries=4)
Definition: mythplayer.cpp:414
uint64_t m_bookmarkSeek
Definition: mythplayer.h:412
bool IsInDelete(uint64_t frame)
uint64_t m_totalFrames
Definition: mythplayer.h:424
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:405
PlayerContext * m_playerCtx
Definition: mythplayer.h:365
MythVideoOutput * m_videoOutput
Definition: mythplayer.h:363
void DiscardVideoFrame(MythVideoFrame *buffer)
Places frame in the available frames queue.
Definition: mythplayer.cpp:623
virtual bool InitVideo(void)
Definition: mythplayer.cpp:267
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:64
#define LOC
@ kScan_Interlaced
Definition: videoouttypes.h:98