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")
644 if (frameRate.isNonzero() && frameRate !=
m_frameRate)
647 LOG(VB_RECORD, LOG_INFO,
LOC +
648 QString(
"FindMPEG2Keyframes: frame rate = %1")
649 .arg(frameRate.toDouble() * 1000));
668 LOG(VB_RECORD, LOG_DEBUG,
669 "Switching from dts tracking to pts tracking." +
670 QString(
"TS count is %1").arg(
m_tsCount[stream_id]));
674 int64_t gap_threshold = 90000;
678 gap_threshold = 2*90000LL;
682 gap_threshold = 8*90000LL;
686 int64_t diff = ts -
m_tsLast[stream_id];
689 if (diff < (10 * -90000LL))
691 diff += 0x1ffffffffLL;
708 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString(
"Inserted gap %1 dur %2")
716 LOG(VB_GENERAL, LOG_INFO,
LOC +
717 QString(
"HandleTimestamps: too much damage, "
718 "setting status to %1")
761 LOG(VB_RECORD, LOG_DEBUG,
762 QString(
"count=%1 m_frameRate=%2 tick_frameRate=%3 "
763 "tick_cnt=%4 tick_base=%5 _total_dur=%6")
775 bool hasKeyFrame =
false;
779 static constexpr uint64_t kMsecPerDay { 24ULL * 60 * 60 * 1000 };
781 uint64_t elapsed = 0;
784 auto expected_frame = (uint64_t) ((
double)elapsed / frame_interval);
787 expected_frame += (uint64_t) ((
double)kMsecPerDay / frame_interval);
821 LOG(VB_RECORD, LOG_INFO,
LOC +
"DSMCC - FindOtherKeyframes() - "
822 "generating initial key-frame");
886 LOG(VB_GENERAL, LOG_ERR,
LOC +
"FindH2645Keyframes: No ringbuffer");
892 LOG(VB_GENERAL, LOG_ERR,
LOC +
"FindH2645Keyframes: m_h2645Parser not present");
904 uint aspectRatio = 0;
910 bool hasFrame =
false;
911 bool hasKeyFrame =
false;
923 LOG(VB_GENERAL, LOG_ERR,
LOC +
924 "PES packet start code may overflow to next TS packet, "
925 "aborting keyframe search");
930 if (tspacket->
data()[i ] != 0x00 ||
931 tspacket->
data()[i+1] != 0x00 ||
932 tspacket->
data()[i+2] != 0x01)
937 LOG(VB_GENERAL, LOG_ERR,
LOC +
938 "PES start code not found in TS packet with PUSI set");
949 LOG(VB_GENERAL, LOG_ERR,
LOC +
950 "PES packet headers overflow to next TS packet, "
951 "aborting keyframe search");
961 const unsigned char pes_header_length = tspacket->
data()[i + 5];
966 LOG(VB_GENERAL, LOG_ERR,
LOC +
967 "PES packet headers overflow to next TS packet, "
968 "aborting keyframe search");
975 i += 5 + pes_header_length;
979 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"PES synced");
991 i += (bytes_used - 1);
1013 if (hasFrame && !hasKeyFrame &&
1017 LOG(VB_RECORD, LOG_WARNING,
LOC +
1018 QString(
"FindH2645Keyframes: %1 frames without a keyframe.")
1025 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
1026 (
"Keyframe @ %1 + %2 = %3 AU %4")
1038 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString
1039 (
"Frame @ %1 + %2 = %3 AU %4")
1070 if (frameRate.isNonzero() && frameRate !=
m_frameRate)
1072 LOG(VB_RECORD, LOG_INFO,
LOC +
1073 QString(
"FindH2645Keyframes: timescale: %1, tick: %2, framerate: %3")
1076 .arg( frameRate.toDouble() * 1000 ) );
1083 LOG(VB_RECORD, LOG_INFO,
LOC +
1084 QString(
"FindH2645Keyframes: scan type: %1")
1086 "Interlaced" :
"Progressive"));
1103 uint64_t startpos = 0;
1133 const uint8_t *bufstart = buffer;
1134 const uint8_t *bufptr = buffer;
1135 const uint8_t *bufend = buffer + len;
1137 uint aspectRatio = 0;
1143 while (bufptr + skip < bufend)
1145 bool hasFrame =
false;
1146 bool hasKeyFrame =
false;
1148 const uint8_t *tmp = bufptr;
1160 int pes_packet_length = -1;
1161 if ((bufend - bufptr) >= 2)
1162 pes_packet_length = ((bufptr[0]<<8) | bufptr[1]) + 2 + 6;
1169 pes_packet_length = -1;
1170 if (bufend-bufptr >= 4)
1172 uint frmtypei = (bufptr[1]>>3) & 0x7;
1173 if ((1 <= frmtypei) && (frmtypei <= 5))
1183 pes_packet_length = -1;
1189 pes_packet_length = -1;
1194 aspectRatio = (bufptr[3] >> 4);
1197 height = ((bufptr[1] & 0xf) << 8) | bufptr[2];
1198 width = (bufptr[0] <<4) | (bufptr[1]>>4);
1224 if (hasFrame && !hasKeyFrame)
1254 if (height && width &&
1262 if (frameRate.isNonzero() && frameRate !=
m_frameRate)
1265 LOG(VB_RECORD, LOG_INFO,
LOC +
1266 QString(
"FindPSKeyFrames: frame rate = %1")
1267 .arg(frameRate.toDouble() * 1000));
1271 if (hasKeyFrame || hasFrame)
1294 int bytes_skipped = bufend - bufptr;
1295 if (bytes_skipped > 0)
1306 uint64_t rem = (bufend - bufstart);
1310 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1311 QString(
"idx: %1, rem: %2").arg(idx).arg(rem));
1319 LOG(VB_RECORD, LOG_ERR,
LOC +
"SetPAT(NULL)");
1334 int oldProgNum = progNum;
1336 LOG(VB_GENERAL, LOG_INFO,
LOC +
1337 QString(
"Update desired program found in SPTS PAT from %1 to %2")
1338 .arg(oldProgNum).arg(progNum));
1340 pmtpid = _pat->
FindPID(progNum);
1345 LOG(VB_RECORD, LOG_ERR,
LOC +
1346 QString(
"SetPAT(): Ignoring PAT not containing our desired "
1347 "program (%1)...").arg(progNum));
1351 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetPAT(%1 on pid 0x%2)")
1352 .arg(progNum).arg(pmtpid,0,16));
1371 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetPMT(%1, %2)").arg(progNum)
1372 .arg(_pmt ==
nullptr ?
"NULL" :
"valid"));
1377 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetPMT(%1)").arg(progNum));
1383 bool has_no_av =
true;
1401 LOG(VB_RECORD, LOG_ERR,
LOC +
"HandleSingleProgramPAT(NULL)");
1420 LOG(VB_RECORD, LOG_ERR,
LOC +
"HandleSingleProgramPMT(NULL)");
1427 uint bestAudioCodec = 0;
1457 if (avcParser !=
nullptr)
1466 LOG(VB_GENERAL, LOG_INFO,
LOC +
"HEVC detected");
1556 const uint pid = tspacket.
PID();
1566 double erate = v * 100.0 /
m_packetCount.fetchAndAddRelaxed(0);
1567 LOG(VB_RECORD, LOG_WARNING,
LOC +
1568 QString(
"PID 0x%1 discontinuity detected ((%2+1)%16!=%3) %4%")
1569 .arg(pid,0,16).arg(old_cnt,2)
1641 else if (streamType != 0)
1644 LOG(VB_RECORD, LOG_ERR,
LOC +
1645 "ProcessVideoTSPacket: unknown stream type!");
1684 const uint pid = tspacket.
PID();
1694 double erate = v * 100.0 /
m_packetCount.fetchAndAddRelaxed(0);
1695 LOG(VB_RECORD, LOG_WARNING,
LOC +
1696 QString(
"A/V PID 0x%1 discontinuity detected ((%2+1)%16!=%3) %4%")
1698 .arg(erate,5,
'f',2));
1704 LOG(VB_RECORD, LOG_INFO,
LOC +
1705 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