23#ifndef __cpp_size_t_suffix
40#define LOC ((m_tvrec) ? \
41 QString("DTVRec[%1]: ").arg(m_tvrec->GetInputId()) : \
42 QString("DTVRec(0x%1): ").arg(intptr_t(this),0,16))
59#ifdef __cpp_size_t_suffix
100 if (name ==
"recordingtype")
111 if (name ==
"wait_for_seqstart")
113 else if (name ==
"recordmpts")
120 const QString &videodev,
121 const QString& ,
const QString& )
149 LOG(VB_RECORD, LOG_INFO,
LOC +
"ResetForNewFile(void)");
213 LOG(VB_RECORD, LOG_INFO,
LOC +
"Reset(void)");
252 if (atsc && atsc->DesiredMinorChannel())
255 atsc->DesiredMinorChannel());
289 int interval = thresh;
293 .fetchAndStoreRelaxed(thresh * 4 / 5);
298 .fetchAndStoreRelaxed(thresh * 9 / 8);
304 LOG(VB_RECORD, LOG_DEBUG,
LOC +
305 QString(
"Updating timeOfLatestData elapsed(%1) interval(%2)")
306 .arg(elapsed.count()).arg(interval));
331 LOG(VB_GENERAL, LOG_INFO,
LOC +
332 QString(
"BufferedWrite: Writes are failing, "
333 "setting status to %1")
341 const uint8_t *bufptr,
int bytes_left,
int pts_or_dts)
346 bool has_pts = (bufptr[3] & 0x80) != 0;
348 if (((
kExtractPTS == pts_or_dts) && !has_pts) || (offset + 5 > bytes_left))
351 bool has_dts = (bufptr[3] & 0x40) != 0;
356 offset += has_pts ? 5 : 0;
357 if (offset + 5 > bytes_left)
361 return ((uint64_t(bufptr[offset+0] & 0x0e) << 29) |
362 (uint64_t(bufptr[offset+1] ) << 22) |
363 (uint64_t(bufptr[offset+2] & 0xfe) << 14) |
364 (uint64_t(bufptr[offset+3] ) << 7) |
365 (uint64_t(bufptr[offset+4] & 0xfe) >> 1));
369 uint64_t
pts, uint64_t pts_first,
const QDateTime &pts_first_dt)
372 pts += 0x1FFFFFFFFLL;
373 const QDateTime& dt = pts_first_dt;
374 return dt.addMSecs((
pts - pts_first)/90);
428 bool hasFrame =
false;
429 bool hasKeyFrame =
false;
431 uint aspectRatio = 0;
443 const uint8_t *bufptr = tspacket->
data() + tspacket->
AFCOffset();
447 while (bufptr < bufend)
450 int bytes_left = bufend - bufptr;
475 aspectRatio = (bufptr[3] >> 4);
478 height = ((bufptr[1] & 0xf) << 8) | bufptr[2];
479 width = (bufptr[0] <<4) | (bufptr[1]>>4);
487 int ext_type = (bufptr[0] >> 4);
499 int picture_structure = bufptr[2] & 3;
500 int top_field_first = bufptr[3] & (1 << 7);
501 int repeat_first_field = bufptr[3] & (1 << 1);
502 int progressive_frame = bufptr[4] & (1 << 7);
504 LOG(VB_RECORD, LOG_DEBUG,
LOC +
505 QString(
"picture_coding_extension(): (m_progressiveSequence: %1) picture_structure: %2 top_field_first: %3 repeat_first_field: %4 progressive_frame: %5")
507 QString::number(picture_structure , 2),
508 QString::number(top_field_first , 2),
509 QString::number(repeat_first_field , 2),
510 QString::number(progressive_frame , 2)
516 if (picture_structure == 0b00)
520 else if (picture_structure == 0b11)
525 else if (picture_structure < 0b11)
530 if (top_field_first != 0)
532 hasFrame = (picture_structure == 0b01);
536 hasFrame = (picture_structure == 0b10);
543 if (repeat_first_field)
552 else if (progressive_frame)
581 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Music Choice program detected");
587 if (hasFrame && !hasKeyFrame)
601 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
602 (
"Keyframe @ %1 + %2 = %3")
613 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
614 (
"Frame @ %1 + %2 = %3")
646 if (frameRate.isNonzero() && frameRate !=
m_frameRate)
649 LOG(VB_RECORD, LOG_INFO,
LOC +
650 QString(
"FindMPEG2Keyframes: frame rate = %1")
651 .arg(frameRate.toDouble() * 1000));
670 LOG(VB_RECORD, LOG_DEBUG,
671 "Switching from dts tracking to pts tracking." +
672 QString(
"TS count is %1").arg(
m_tsCount[stream_id]));
676 int64_t gap_threshold = 90000;
680 gap_threshold = 2*90000LL;
684 gap_threshold = 8*90000LL;
688 int64_t diff = ts -
m_tsLast[stream_id];
691 if (diff < (10 * -90000LL))
693 diff += 0x1ffffffffLL;
710 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString(
"Inserted gap %1 dur %2")
718 LOG(VB_GENERAL, LOG_INFO,
LOC +
719 QString(
"HandleTimestamps: too much damage, "
720 "setting status to %1")
763 LOG(VB_RECORD, LOG_DEBUG,
764 QString(
"count=%1 m_frameRate=%2 tick_frameRate=%3 "
765 "tick_cnt=%4 tick_base=%5 _total_dur=%6")
777 bool hasKeyFrame =
false;
781 static constexpr uint64_t kMsecPerDay { 24ULL * 60 * 60 * 1000 };
783 uint64_t elapsed = 0;
786 auto expected_frame = (uint64_t) ((
double)elapsed / frame_interval);
789 expected_frame += (uint64_t) ((
double)kMsecPerDay / frame_interval);
823 LOG(VB_RECORD, LOG_INFO,
LOC +
"DSMCC - FindOtherKeyframes() - "
824 "generating initial key-frame");
888 LOG(VB_GENERAL, LOG_ERR,
LOC +
"FindH2645Keyframes: No ringbuffer");
894 LOG(VB_GENERAL, LOG_ERR,
LOC +
"FindH2645Keyframes: m_h2645Parser not present");
906 uint aspectRatio = 0;
912 bool hasFrame =
false;
913 bool hasKeyFrame =
false;
925 LOG(VB_GENERAL, LOG_ERR,
LOC +
926 "PES packet start code may overflow to next TS packet, "
927 "aborting keyframe search");
932 if (tspacket->
data()[i ] != 0x00 ||
933 tspacket->
data()[i+1] != 0x00 ||
934 tspacket->
data()[i+2] != 0x01)
939 LOG(VB_GENERAL, LOG_ERR,
LOC +
940 "PES start code not found in TS packet with PUSI set");
951 LOG(VB_GENERAL, LOG_ERR,
LOC +
952 "PES packet headers overflow to next TS packet, "
953 "aborting keyframe search");
963 const unsigned char pes_header_length = tspacket->
data()[i + 5];
968 LOG(VB_GENERAL, LOG_ERR,
LOC +
969 "PES packet headers overflow to next TS packet, "
970 "aborting keyframe search");
977 i += 5 + pes_header_length;
981 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"PES synced");
993 i += (bytes_used - 1);
1015 if (hasFrame && !hasKeyFrame &&
1019 LOG(VB_RECORD, LOG_WARNING,
LOC +
1020 QString(
"FindH2645Keyframes: %1 frames without a keyframe.")
1027 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
1028 (
"Keyframe @ %1 + %2 = %3 AU %4")
1040 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
1041 (
"Frame @ %1 + %2 = %3 AU %4")
1074 if (frameRate.isNonzero() && frameRate !=
m_frameRate)
1076 LOG(VB_RECORD, LOG_INFO,
LOC +
1077 QString(
"FindH2645Keyframes: timescale: %1, tick: %2, framerate: %3")
1080 .arg( frameRate.toDouble() * 1000 ) );
1087 LOG(VB_RECORD, LOG_INFO,
LOC +
1088 QString(
"FindH2645Keyframes: scan type: %1")
1090 "Interlaced" :
"Progressive"));
1107 uint64_t startpos = 0;
1137 const uint8_t *bufstart = buffer;
1138 const uint8_t *bufptr = buffer;
1139 const uint8_t *bufend = buffer + len;
1141 uint aspectRatio = 0;
1147 while (bufptr + skip < bufend)
1149 bool hasFrame =
false;
1150 bool hasKeyFrame =
false;
1152 const uint8_t *tmp = bufptr;
1164 int pes_packet_length = -1;
1165 if ((bufend - bufptr) >= 2)
1166 pes_packet_length = ((bufptr[0]<<8) | bufptr[1]) + 2 + 6;
1173 pes_packet_length = -1;
1174 if (bufend-bufptr >= 4)
1176 uint frmtypei = (bufptr[1]>>3) & 0x7;
1177 if ((1 <= frmtypei) && (frmtypei <= 5))
1187 pes_packet_length = -1;
1193 pes_packet_length = -1;
1198 aspectRatio = (bufptr[3] >> 4);
1201 height = ((bufptr[1] & 0xf) << 8) | bufptr[2];
1202 width = (bufptr[0] <<4) | (bufptr[1]>>4);
1228 if (hasFrame && !hasKeyFrame)
1258 if (height && width &&
1266 if (frameRate.isNonzero() && frameRate !=
m_frameRate)
1269 LOG(VB_RECORD, LOG_INFO,
LOC +
1270 QString(
"FindPSKeyFrames: frame rate = %1")
1271 .arg(frameRate.toDouble() * 1000));
1275 if (hasKeyFrame || hasFrame)
1298 int bytes_skipped = bufend - bufptr;
1299 if (bytes_skipped > 0)
1310 uint64_t rem = (bufend - bufstart);
1314 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1315 QString(
"idx: %1, rem: %2").arg(idx).arg(rem));
1323 LOG(VB_RECORD, LOG_ERR,
LOC +
"SetPAT(NULL)");
1338 int oldProgNum = progNum;
1340 LOG(VB_GENERAL, LOG_INFO,
LOC +
1341 QString(
"Update desired program found in SPTS PAT from %1 to %2")
1342 .arg(oldProgNum).arg(progNum));
1344 pmtpid = _pat->
FindPID(progNum);
1349 LOG(VB_RECORD, LOG_ERR,
LOC +
1350 QString(
"SetPAT(): Ignoring PAT not containing our desired "
1351 "program (%1)...").arg(progNum));
1355 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetPAT(%1 on pid 0x%2)")
1356 .arg(progNum).arg(pmtpid,0,16));
1375 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetPMT(%1, %2)").arg(progNum)
1376 .arg(_pmt ==
nullptr ?
"NULL" :
"valid"));
1381 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetPMT(%1)").arg(progNum));
1387 bool has_no_av =
true;
1405 LOG(VB_RECORD, LOG_ERR,
LOC +
"HandleSingleProgramPAT(NULL)");
1424 LOG(VB_RECORD, LOG_ERR,
LOC +
"HandleSingleProgramPMT(NULL)");
1431 uint bestAudioCodec = 0;
1461 if (avcParser !=
nullptr)
1470 LOG(VB_GENERAL, LOG_INFO,
LOC +
"HEVC detected");
1560 const uint pid = tspacket.
PID();
1570 double erate = v * 100.0 /
m_packetCount.fetchAndAddRelaxed(0);
1571 LOG(VB_RECORD, LOG_WARNING,
LOC +
1572 QString(
"PID 0x%1 discontinuity detected ((%2+1)%16!=%3) %4%")
1573 .arg(pid,0,16).arg(old_cnt,2)
1645 else if (streamType != 0)
1648 LOG(VB_RECORD, LOG_ERR,
LOC +
1649 "ProcessVideoTSPacket: unknown stream type!");
1688 const uint pid = tspacket.
PID();
1698 double erate = v * 100.0 /
m_packetCount.fetchAndAddRelaxed(0);
1699 LOG(VB_RECORD, LOG_WARNING,
LOC +
1700 QString(
"A/V PID 0x%1 discontinuity detected ((%2+1)%16!=%3) %4%")
1702 .arg(erate,5,
'f',2));
1708 LOG(VB_RECORD, LOG_INFO,
LOC +
1709 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::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