38#define LOC ((m_tvrec) ? \
39 QString("DTVRec[%1]: ").arg(m_tvrec->GetInputId()) : \
40 QString("DTVRec(0x%1): ").arg(intptr_t(this),0,16))
94 if (name ==
"recordingtype")
105 if (name ==
"wait_for_seqstart")
107 else if (name ==
"recordmpts")
114 const QString &videodev,
115 const QString& ,
const QString& )
143 LOG(VB_RECORD, LOG_INFO,
LOC +
"ResetForNewFile(void)");
207 LOG(VB_RECORD, LOG_INFO,
LOC +
"Reset(void)");
246 if (atsc && atsc->DesiredMinorChannel())
249 atsc->DesiredMinorChannel());
283 int interval = thresh;
287 .fetchAndStoreRelaxed(thresh * 4 / 5);
292 .fetchAndStoreRelaxed(thresh * 9 / 8);
298 LOG(VB_RECORD, LOG_DEBUG,
LOC +
299 QString(
"Updating timeOfLatestData elapsed(%1) interval(%2)")
300 .arg(elapsed.count()).arg(interval));
325 LOG(VB_GENERAL, LOG_INFO,
LOC +
326 QString(
"BufferedWrite: Writes are failing, "
327 "setting status to %1")
335 const uint8_t *bufptr,
int bytes_left,
int pts_or_dts)
340 bool has_pts = (bufptr[3] & 0x80) != 0;
342 if (((
kExtractPTS == pts_or_dts) && !has_pts) || (offset + 5 > bytes_left))
345 bool has_dts = (bufptr[3] & 0x40) != 0;
350 offset += has_pts ? 5 : 0;
351 if (offset + 5 > bytes_left)
355 return ((uint64_t(bufptr[offset+0] & 0x0e) << 29) |
356 (uint64_t(bufptr[offset+1] ) << 22) |
357 (uint64_t(bufptr[offset+2] & 0xfe) << 14) |
358 (uint64_t(bufptr[offset+3] ) << 7) |
359 (uint64_t(bufptr[offset+4] & 0xfe) >> 1));
363 uint64_t
pts, uint64_t pts_first,
const QDateTime &pts_first_dt)
366 pts += 0x1FFFFFFFFLL;
367 const QDateTime& dt = pts_first_dt;
368 return dt.addMSecs((
pts - pts_first)/90);
422 bool hasFrame =
false;
423 bool hasKeyFrame =
false;
425 uint aspectRatio = 0;
437 const uint8_t *bufptr = tspacket->
data() + tspacket->
AFCOffset();
441 while (bufptr < bufend)
444 int bytes_left = bufend - bufptr;
469 aspectRatio = (bufptr[3] >> 4);
472 height = ((bufptr[1] & 0xf) << 8) | bufptr[2];
473 width = (bufptr[0] <<4) | (bufptr[1]>>4);
481 int ext_type = (bufptr[0] >> 4);
493 int picture_structure = bufptr[2] & 3;
494 int top_field_first = bufptr[3] & (1 << 7);
495 int repeat_first_field = bufptr[3] & (1 << 1);
496 int progressive_frame = bufptr[4] & (1 << 7);
498 LOG(VB_RECORD, LOG_DEBUG,
LOC +
499 QString(
"picture_coding_extension(): (m_progressiveSequence: %1) picture_structure: %2 top_field_first: %3 repeat_first_field: %4 progressive_frame: %5")
501 QString::number(picture_structure , 2),
502 QString::number(top_field_first , 2),
503 QString::number(repeat_first_field , 2),
504 QString::number(progressive_frame , 2)
510 if (picture_structure == 0b00)
514 else if (picture_structure == 0b11)
519 else if (picture_structure < 0b11)
524 if (top_field_first != 0)
526 hasFrame = (picture_structure == 0b01);
530 hasFrame = (picture_structure == 0b10);
537 if (repeat_first_field)
546 else if (progressive_frame)
575 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Music Choice program detected");
581 if (hasFrame && !hasKeyFrame)
595 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
596 (
"Keyframe @ %1 + %2 = %3")
607 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
608 (
"Frame @ %1 + %2 = %3")
638 if (frameRate.isNonzero() && frameRate !=
m_frameRate)
641 LOG(VB_RECORD, LOG_INFO,
LOC +
642 QString(
"FindMPEG2Keyframes: frame rate = %1")
643 .arg(frameRate.toDouble() * 1000));
662 LOG(VB_RECORD, LOG_DEBUG,
663 "Switching from dts tracking to pts tracking." +
664 QString(
"TS count is %1").arg(
m_tsCount[stream_id]));
668 int64_t gap_threshold = 90000;
672 gap_threshold = 2*90000LL;
676 gap_threshold = 8*90000LL;
680 int64_t diff = ts -
m_tsLast[stream_id];
683 if (diff < (10 * -90000LL))
685 diff += 0x1ffffffffLL;
702 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString(
"Inserted gap %1 dur %2")
710 LOG(VB_GENERAL, LOG_INFO,
LOC +
711 QString(
"HandleTimestamps: too much damage, "
712 "setting status to %1")
755 LOG(VB_RECORD, LOG_DEBUG,
756 QString(
"count=%1 m_frameRate=%2 tick_frameRate=%3 "
757 "tick_cnt=%4 tick_base=%5 _total_dur=%6")
769 bool hasKeyFrame =
false;
773 static constexpr uint64_t kMsecPerDay { 24ULL * 60 * 60 * 1000 };
775 uint64_t elapsed = 0;
778 auto expected_frame = (uint64_t) ((
double)elapsed / frame_interval);
781 expected_frame += (uint64_t) ((
double)kMsecPerDay / frame_interval);
815 LOG(VB_RECORD, LOG_INFO,
LOC +
"DSMCC - FindOtherKeyframes() - "
816 "generating initial key-frame");
880 LOG(VB_GENERAL, LOG_ERR,
LOC +
"FindH2645Keyframes: No ringbuffer");
886 LOG(VB_GENERAL, LOG_ERR,
LOC +
"FindH2645Keyframes: m_h2645Parser not present");
898 uint aspectRatio = 0;
904 bool hasFrame =
false;
905 bool hasKeyFrame =
false;
917 LOG(VB_GENERAL, LOG_ERR,
LOC +
918 "PES packet start code may overflow to next TS packet, "
919 "aborting keyframe search");
924 if (tspacket->
data()[i ] != 0x00 ||
925 tspacket->
data()[i+1] != 0x00 ||
926 tspacket->
data()[i+2] != 0x01)
931 LOG(VB_GENERAL, LOG_ERR,
LOC +
932 "PES start code not found in TS packet with PUSI set");
943 LOG(VB_GENERAL, LOG_ERR,
LOC +
944 "PES packet headers overflow to next TS packet, "
945 "aborting keyframe search");
955 const unsigned char pes_header_length = tspacket->
data()[i + 5];
960 LOG(VB_GENERAL, LOG_ERR,
LOC +
961 "PES packet headers overflow to next TS packet, "
962 "aborting keyframe search");
969 i += 5 + pes_header_length;
973 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"PES synced");
985 i += (bytes_used - 1);
1007 if (hasFrame && !hasKeyFrame &&
1011 LOG(VB_RECORD, LOG_WARNING,
LOC +
1012 QString(
"FindH2645Keyframes: %1 frames without a keyframe.")
1019 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
1020 (
"Keyframe @ %1 + %2 = %3 AU %4")
1032 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
1033 (
"Frame @ %1 + %2 = %3 AU %4")
1064 if (frameRate.isNonzero() && frameRate !=
m_frameRate)
1066 LOG(VB_RECORD, LOG_INFO,
LOC +
1067 QString(
"FindH2645Keyframes: timescale: %1, tick: %2, framerate: %3")
1070 .arg( frameRate.toDouble() * 1000 ) );
1077 LOG(VB_RECORD, LOG_INFO,
LOC +
1078 QString(
"FindH2645Keyframes: scan type: %1")
1080 "Interlaced" :
"Progressive"));
1097 uint64_t startpos = 0;
1127 const uint8_t *bufstart = buffer;
1128 const uint8_t *bufptr = buffer;
1129 const uint8_t *bufend = buffer + len;
1131 uint aspectRatio = 0;
1137 while (bufptr + skip < bufend)
1139 bool hasFrame =
false;
1140 bool hasKeyFrame =
false;
1142 const uint8_t *
tmp = bufptr;
1154 int pes_packet_length = -1;
1155 if ((bufend - bufptr) >= 2)
1156 pes_packet_length = ((bufptr[0]<<8) | bufptr[1]) + 2 + 6;
1163 pes_packet_length = -1;
1164 if (bufend-bufptr >= 4)
1166 uint frmtypei = (bufptr[1]>>3) & 0x7;
1167 if ((1 <= frmtypei) && (frmtypei <= 5))
1177 pes_packet_length = -1;
1183 pes_packet_length = -1;
1188 aspectRatio = (bufptr[3] >> 4);
1191 height = ((bufptr[1] & 0xf) << 8) | bufptr[2];
1192 width = (bufptr[0] <<4) | (bufptr[1]>>4);
1218 if (hasFrame && !hasKeyFrame)
1248 if (height && width &&
1256 if (frameRate.isNonzero() && frameRate !=
m_frameRate)
1259 LOG(VB_RECORD, LOG_INFO,
LOC +
1260 QString(
"FindPSKeyFrames: frame rate = %1")
1261 .arg(frameRate.toDouble() * 1000));
1265 if (hasKeyFrame || hasFrame)
1288 int bytes_skipped = bufend - bufptr;
1289 if (bytes_skipped > 0)
1300 uint64_t rem = (bufend - bufstart);
1304 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1305 QString(
"idx: %1, rem: %2").arg(idx).arg(rem));
1313 LOG(VB_RECORD, LOG_ERR,
LOC +
"SetPAT(NULL)");
1328 int oldProgNum = progNum;
1330 LOG(VB_GENERAL, LOG_INFO,
LOC +
1331 QString(
"Update desired program found in SPTS PAT from %1 to %2")
1332 .arg(oldProgNum).arg(progNum));
1334 pmtpid = _pat->
FindPID(progNum);
1339 LOG(VB_RECORD, LOG_ERR,
LOC +
1340 QString(
"SetPAT(): Ignoring PAT not containing our desired "
1341 "program (%1)...").arg(progNum));
1345 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetPAT(%1 on pid 0x%2)")
1346 .arg(progNum).arg(pmtpid,0,16));
1365 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetPMT(%1, %2)").arg(progNum)
1366 .arg(_pmt ==
nullptr ?
"NULL" :
"valid"));
1371 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetPMT(%1)").arg(progNum));
1377 bool has_no_av =
true;
1395 LOG(VB_RECORD, LOG_ERR,
LOC +
"HandleSingleProgramPAT(NULL)");
1414 LOG(VB_RECORD, LOG_ERR,
LOC +
"HandleSingleProgramPMT(NULL)");
1421 uint bestAudioCodec = 0;
1451 if (avcParser !=
nullptr)
1460 LOG(VB_GENERAL, LOG_INFO,
LOC +
"HEVC detected");
1550 const uint pid = tspacket.
PID();
1560 double erate = v * 100.0 /
m_packetCount.fetchAndAddRelaxed(0);
1561 LOG(VB_RECORD, LOG_WARNING,
LOC +
1562 QString(
"PID 0x%1 discontinuity detected ((%2+1)%16!=%3) %4%")
1563 .arg(pid,0,16).arg(old_cnt,2)
1635 else if (streamType != 0)
1638 LOG(VB_RECORD, LOG_ERR,
LOC +
1639 "ProcessVideoTSPacket: unknown stream type!");
1678 const uint pid = tspacket.
PID();
1688 double erate = v * 100.0 /
m_packetCount.fetchAndAddRelaxed(0);
1689 LOG(VB_RECORD, LOG_WARNING,
LOC +
1690 QString(
"A/V PID 0x%1 discontinuity detected ((%2+1)%16!=%3) %4%")
1692 .arg(erate,5,
'f',2));
1698 LOG(VB_RECORD, LOG_INFO,
LOC +
1699 QString(
"PID 0x%1 Found Payload Start").arg(pid,0,16));
This is in libmythtv because that is where the parsers, which are its main users, are.
Encapsulates data about ATSC stream and emits events for most tables.
void SetDesiredChannel(int major, int minor)
QString m_error
non-empty iff irrecoverable recording error detected
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
bool m_hasWrittenOtherKeyframe
std::array< QDateTime, 256 > m_tsFirstDt
bool FindH2645Keyframes(const TSPacket *tspacket)
std::array< uint8_t, 0x1fff+1 > m_continuityCounter
unsigned int m_audioBytesRemaining
int m_minimumRecordingQuality
bool ProcessAudioTSPacket(const TSPacket &tspacket) override
std::vector< unsigned char > m_payloadBuffer
std::array< int64_t, 256 > m_tsLast
ProgramMapTable * m_inputPmt
PMT on input side.
double m_tdBase
Milliseconds from the start to m_tdTickCount = 0.
std::vector< TSPacket > m_scratch
uint64_t m_tdTickCount
Count of the number of equivalent interlaced fields that have passed since m_tdBase.
std::array< int64_t, 256 > m_tsFirst
RecordingQuality * GetRecordingQuality(const RecordingInfo *r) const override
Returns a report about the current recordings quality.
unsigned long long m_lastGopSeen
unsigned long long m_lastKeyframeSeen
void ResetForNewFile(void) override
QElapsedTimer m_audioTimer
void BufferedWrite(const TSPacket &tspacket, bool insert=false)
int m_progressiveSequence
bool ProcessVideoTSPacket(const TSPacket &tspacket) override
bool ProcessTSPacket(const TSPacket &tspacket) override
bool FindOtherKeyframes(const TSPacket *tspacket)
Non-Audio/Video data.
virtual void SetCAMPMT(const ProgramMapTable *)
unsigned int m_otherBytesRemaining
void HandleH2645Keyframe(void)
This save the current frame to the position maps and handles ringbuffer switching.
MPEGStreamData * GetStreamData(void) const
unsigned long long m_framesSeenCount
static const unsigned char kPayloadStartSeen
std::array< uint8_t, 0x1fff+1 > m_streamId
std::array< uint8_t, 0x1fff+1 > m_pidStatus
virtual QString GetSIStandard(void) const
static const uint kMaxKeyFrameDistance
If the number of regular frames detected since the last detected keyframe exceeds this value,...
std::array< uint64_t, 256 > m_tsCount
ProgramAssociationTable * m_inputPat
PAT on input side.
void HandleKeyframe(int64_t extra)
This save the current frame to the position maps and handles ringbuffer switching.
H2645Parser * m_h2645Parser
void HandleSingleProgramPAT(ProgramAssociationTable *pat, bool insert) override
void HandlePAT(const ProgramAssociationTable *_pat) override
void Reset(void) override
Reset the recorder to the startup state.
MythAVRational m_tdTickFramerate
void HandleTimestamps(int stream_id, int64_t pts, int64_t dts)
void SetOptionsFromProfile(RecordingProfile *profile, const QString &videodev, const QString &audiodev, const QString &vbidev) override
Sets basic recorder options.
bool ProcessAVTSPacket(const TSPacket &tspacket)
Common code for processing either audio or video packets.
void HandlePMT(uint progNum, const ProgramMapTable *_pmt) override
bool m_waitForKeyframeOption
Wait for the a GOP/SEQ-start before sending data.
MPEGStreamData * m_streamData
void SetOption(const QString &name, const QString &value) override
Set an specific option.
double m_totalDuration
Total milliseconds that have passed since the start of the recording.
void FindPSKeyFrames(const uint8_t *buffer, uint len) override
QAtomicInt m_continuityErrorCount
QRecursiveMutex m_pidLock
unsigned int m_videoBytesRemaining
bool CheckCC(uint pid, uint new_cnt)
unsigned long long m_lastSeqSeen
bool FindAudioKeyframes(const TSPacket *tspacket)
virtual void SetStreamData(MPEGStreamData *data)
unsigned long long m_framesWrittenCount
virtual void InitStreamData(void)
MythTimer m_recordMptsTimer
void HandleSingleProgramPMT(ProgramMapTable *pmt, bool insert) override
bool FindMPEG2Keyframes(const TSPacket *tspacket)
Locates the keyframes and saves them to the position map.
void UpdateFramesWritten(void)
void ClearStatistics(void) override
void AddDVBMainListener(DVBMainStreamListener *val)
SCAN_t GetScanType(void) const
uint pictureHeight(void) const
uint aspectRatio(void) const
Computes aspect ratio from picture size and sample aspect ratio.
bool stateChanged(void) const
virtual MythAVRational getFrameRate() const =0
virtual field_type getFieldType(void) const =0
bool onFrameStart(void) const
uint pictureWidth(void) const
uint32_t GetUnitsInTick(void) const
virtual uint32_t addBytes(const uint8_t *bytes, uint32_t byte_count, uint64_t stream_offset)=0
bool onKeyFrameStart(void) const
uint32_t GetTimeScale(void) const
uint64_t keyframeAUstreamOffset(void) const
Encapsulates data about MPEG stream and emits events for each table.
void AddMPEGListener(MPEGStreamListener *val)
void SetDesiredProgram(int p)
void AddMPEGSPListener(MPEGSingleProgramStreamListener *val)
int DesiredProgram(void) const
virtual bool IsListeningPID(uint pid) const
virtual void AddListeningPID(uint pid, PIDPriority priority=kPIDPriorityNormal)
C++ wrapper for FFmpeg libavutil AVRational.
MythAVRational invert() const
QString GetSetting(const QString &key, const QString &defaultval="")
int GetNumSetting(const QString &key, int defaultval=0)
void addMSecs(std::chrono::milliseconds ms)
Adds an offset to the last call to start() or restart().
std::chrono::milliseconds restart(void)
Returns milliseconds elapsed since last start() or restart() and resets the count.
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
bool isRunning(void) const
Returns true if start() or restart() has been called at least once since construction and since any c...
void stop(void)
Stops timer, next call to isRunning() will return false and any calls to elapsed() or restart() will ...
void start(void)
starts measuring elapsed time.
void GetAsTSPackets(std::vector< TSPacket > &output, uint cc) const
Returns payload only PESPacket as series of TSPackets.
const TSHeader * tsheader() const
@ SequenceStartCode
Sequence (SEQ) start code contains frame size, aspect ratio and fps.
@ MPEGAudioStreamEnd
Last MPEG-1/2 audio stream (w/ext hdr)
@ MPEG2ExtensionStartCode
Followed by an extension byte, not documented here.
@ MPEGVideoStreamBegin
First MPEG-1/2 video stream (w/ext hdr)
@ GOPStartCode
Group of Pictures (GOP) start code.
@ MPEGVideoStreamEnd
Last MPEG-1/2 video stream (w/ext hdr)
@ MPEGAudioStreamBegin
First MPEG-1/2 audio stream (w/ext hdr)
The Program Association Table lists all the programs in a stream, and is always found on PID 0.
uint ProgramCount(void) const
uint FindPID(uint progNum) const
uint ProgramNumber(uint i) const
uint ProgramPID(uint i) const
void ClearPositionMap(MarkTypes type) const
RecStatus::Type GetRecordingStatus(void) const
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
uint StreamCount(void) const
uint PCRPID(void) const
stream that contains program clock reference.
uint StreamPID(uint i) const
uint StreamType(uint i) const
int FindPID(uint pid) const
Locates stream index of pid.
bool IsAudio(uint i, const QString &sistandard) const
Returns true iff the stream at index i is an audio stream.
bool IsVideo(uint i, const QString &sistandard) const
Returns true iff the stream at index i is a video stream.
static QString toString(RecStatus::Type recstatus, uint id)
Converts "recstatus" into a short (unreadable) string.
This is the abstract base class for supporting recorder hardware.
QAtomicInt m_timeOfLatestDataPacketInterval
static constexpr std::chrono::milliseconds kTimeOfLatestDataIntervalTarget
timeOfLatest update interval target in milliseconds.
AVContainer m_containerFormat
virtual bool CheckForRingBufferSwitch(void)
If requested, switch to new RingBuffer/ProgramInfo objects.
frm_pos_map_t m_positionMap
AVCodecID m_primaryAudioCodec
frm_pos_map_t m_durationMapDelta
QDateTime m_timeOfLatestData
MythTimer m_timeOfLatestDataTimer
void FrameRateChange(uint framerate, uint64_t frame)
Note a change in video frame rate in the recordedmark table.
void SetTotalFrames(uint64_t total_frames)
Note the total frames in the recordedmark table.
QDateTime m_timeOfFirstData
void VideoCodecChange(AVCodecID vCodec)
Note a change in video codec.
virtual void StopRecording(void)
StopRecording() signals to the recorder that it should stop recording and exit cleanly.
frm_pos_map_t m_positionMapDelta
virtual void FinishRecording(void)
void ResolutionChange(uint width, uint height, long long frame)
Note a change in video size in the recordedmark table.
virtual RecordingQuality * GetRecordingQuality(const RecordingInfo *ri) const
Returns a report about the current recordings quality.
void AspectChange(uint aspect, long long frame)
Note a change in aspect ratio in the recordedmark table.
AVCodecID m_primaryVideoCodec
virtual void SetRecordingStatus(RecStatus::Type status, const QString &file, int line)
frm_pos_map_t m_durationMap
void SetStrOption(RecordingProfile *profile, const QString &name)
Convenience function used to set QString options from a profile.
MythMediaBuffer * m_ringBuffer
RecordingGaps m_recordingGaps
void SetDuration(std::chrono::milliseconds duration)
Note the total duration in the recordedmark table.
MythAVRational m_frameRate
QAtomicInt m_timeOfLatestDataCount
void VideoScanChange(SCAN_t scan, uint64_t frame)
Note a change in video scan type in the recordedmark table.
QAtomicInt m_timeOfFirstDataIsSet
virtual void SetOption(const QString &name, const QString &value)
Set an specific option.
void AudioCodecChange(AVCodecID aCodec)
Note a change in audio codec.
RecordingInfo * m_curRecording
virtual void ClearStatistics(void)
void SetPositionMapType(MarkTypes type)
Set seektable type.
void SetIntOption(RecordingProfile *profile, const QString &name)
Convenience function used to set integer options from a profile.
Holds information on a TV Program one might wish to record.
bool IsDamaged(void) const
void AddTSStatistics(int continuity_error_count, int packet_count)
@ MPEG2Video
ISO 13818-2 & ITU H.262 (aka MPEG-2)
@ EAC3Audio
A/53 Part 3:2009 6.7.3.
@ MPEG2AACAudio
ISO 13818-7 Audio w/ADTS syntax.
@ AC3Audio
A/53 Part 3:2009 6.7.1.
@ H265Video
ISO 23008-2 & ITU H.265 (aka HEVC, Ultra HD)
@ VC1Video
SMPTE 421M video codec (aka VC1) in Blu-Ray.
@ MPEG4Video
ISO 14492-2 (aka MPEG-4)
@ PrivSec
ISO 13818-1 private tables & ITU H.222.0.
@ MPEG2AudioAmd1
ISO 13818-3/AMD-1 Audio using LATM syntax.
@ MPEG1Video
ISO 11172-2 (aka MPEG-1)
@ OpenCableVideo
Always MPEG-2??
@ H264Video
ISO 14492-10 & ITU H.264 (aka MPEG-4-AVC)
static bool IsAudio(uint type)
Returns true iff audio is MPEG1/2, AAC, AC3 or DTS audio stream.
static bool IsVideo(uint type)
Returns true iff video is an MPEG1/2/3, H264 or open cable video stream.
Used to access the data of a Transport Stream packet.
unsigned int AFCOffset(void) const
static constexpr unsigned int kSize
This is the coordinating class of the Recorder Subsystem.
static int64_t extract_timestamp(const uint8_t *bufptr, int bytes_left, int pts_or_dts)
#define LOC
DTVRecorder – base class for Digital Televison recorders Copyright 2003-2004 by Brandon Beattie,...
static const std::array< const MythAVRational, 16 > frameRateMap
static QDateTime ts_to_qdatetime(uint64_t pts, uint64_t pts_first, const QDateTime &pts_first_dt)
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::milliseconds > millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
void SendMythSystemRecEvent(const QString &msg, const RecordingInfo *pginfo)
bool start_code_is_valid(uint32_t start_code)
Test whether a start code found by find_start_code() is valid.
MTV_PUBLIC const uint8_t * find_start_code_truncated(const uint8_t *p, const uint8_t *end, uint32_t *start_code)
By preserving the start_code value between subsequent calls, the caller can detect start codes across...
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts