The frame width, height, scan type and apect ratio of a recording are now stored in the 'info' file under the 'F' tag

This commit is contained in:
Klaus Schmidinger 2023-12-28 21:23:19 +01:00
parent 1770a18598
commit 6458f8b581
8 changed files with 160 additions and 25 deletions

View File

@ -2468,6 +2468,8 @@ Christoph Haubrich <christoph1.haubrich@arcor.de>
for fixing handling zero bytes in cH264Parser for fixing handling zero bytes in cH264Parser
for implementing parsing frame rate and image size for MPEG2, H.264 and H.265 for implementing parsing frame rate and image size for MPEG2, H.264 and H.265
for reporting a bug in generating the index file in the cutter for reporting a bug in generating the index file in the cutter
for adding the frame width, height, scan type and aspect ratio of a recording to the 'F'
tag of the 'info' file
Pekka Mauno <pekka.mauno@iki.fi> Pekka Mauno <pekka.mauno@iki.fi>
for fixing cSchedule::GetFollowingEvent() in case there is currently no present for fixing cSchedule::GetFollowingEvent() in case there is currently no present

View File

@ -9852,7 +9852,9 @@ Video Disk Recorder Revision History
mode receiver device (thanks to Markus Ehrnsperger). mode receiver device (thanks to Markus Ehrnsperger).
- Revised support for kernel based LIRC driver (thanks to Marko Mäkelä). - Revised support for kernel based LIRC driver (thanks to Marko Mäkelä).
2023-02-21: 2023-12-28:
- Fixed broken video data streams on systems without output device when switching live - Fixed broken video data streams on systems without output device when switching live
channel to a different transponder while recording (reported by Markus Ehrnsperger). channel to a different transponder while recording (reported by Markus Ehrnsperger).
- The frame width, height, scan type and apect ratio of a recording are now stored in
the 'info' file under the 'F' tag (thanks to Christoph Haubrich).

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recorder.c 5.4 2021/06/19 14:21:16 kls Exp $ * $Id: recorder.c 5.5 2023/12/28 21:22:29 kls Exp $
*/ */
#include "recorder.h" #include "recorder.h"
@ -326,8 +326,12 @@ void cRecorder::Action(void)
break; break;
if (frameDetector->Synced()) { if (frameDetector->Synced()) {
if (!InfoWritten) { if (!InfoWritten) {
if (frameDetector->FramesPerSecond() > 0 && DoubleEqual(recordingInfo->FramesPerSecond(), DEFAULTFRAMESPERSECOND) && !DoubleEqual(recordingInfo->FramesPerSecond(), frameDetector->FramesPerSecond())) { if ((frameDetector->FramesPerSecond() > 0 && DoubleEqual(recordingInfo->FramesPerSecond(), DEFAULTFRAMESPERSECOND) && !DoubleEqual(recordingInfo->FramesPerSecond(), frameDetector->FramesPerSecond())) ||
frameDetector->FrameWidth() != recordingInfo->FrameWidth() ||
frameDetector->FrameHeight() != recordingInfo->FrameHeight() ||
frameDetector->AspectRatio() != recordingInfo->AspectRatio()) {
recordingInfo->SetFramesPerSecond(frameDetector->FramesPerSecond()); recordingInfo->SetFramesPerSecond(frameDetector->FramesPerSecond());
recordingInfo->SetFrameParams(frameDetector->FrameWidth(), frameDetector->FrameHeight(), frameDetector->ScanType(), frameDetector->AspectRatio());
recordingInfo->Write(); recordingInfo->Write();
LOCK_RECORDINGS_WRITE; LOCK_RECORDINGS_WRITE;
Recordings->UpdateByName(recordingName); Recordings->UpdateByName(recordingName);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recording.c 5.22 2023/02/15 14:59:25 kls Exp $ * $Id: recording.c 5.23 2023/12/28 21:22:42 kls Exp $
*/ */
#include "recording.h" #include "recording.h"
@ -24,7 +24,6 @@
#include "i18n.h" #include "i18n.h"
#include "interface.h" #include "interface.h"
#include "menu.h" #include "menu.h"
#include "remux.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include "skins.h" #include "skins.h"
#include "svdrp.h" #include "svdrp.h"
@ -363,6 +362,10 @@ cRecordingInfo::cRecordingInfo(const cChannel *Channel, const cEvent *Event)
event = ownEvent ? ownEvent : Event; event = ownEvent ? ownEvent : Event;
aux = NULL; aux = NULL;
framesPerSecond = DEFAULTFRAMESPERSECOND; framesPerSecond = DEFAULTFRAMESPERSECOND;
frameWidth = 0;
frameHeight = 0;
scanType = stUnknown;
aspectRatio = arUnknown;
priority = MAXPRIORITY; priority = MAXPRIORITY;
lifetime = MAXLIFETIME; lifetime = MAXLIFETIME;
fileName = NULL; fileName = NULL;
@ -424,6 +427,10 @@ cRecordingInfo::cRecordingInfo(const char *FileName)
aux = NULL; aux = NULL;
errors = -1; errors = -1;
framesPerSecond = DEFAULTFRAMESPERSECOND; framesPerSecond = DEFAULTFRAMESPERSECOND;
frameWidth = 0;
frameHeight = 0;
scanType = stUnknown;
aspectRatio = arUnknown;
priority = MAXPRIORITY; priority = MAXPRIORITY;
lifetime = MAXLIFETIME; lifetime = MAXLIFETIME;
fileName = strdup(cString::sprintf("%s%s", FileName, INFOFILESUFFIX)); fileName = strdup(cString::sprintf("%s%s", FileName, INFOFILESUFFIX));
@ -458,6 +465,14 @@ void cRecordingInfo::SetFramesPerSecond(double FramesPerSecond)
framesPerSecond = FramesPerSecond; framesPerSecond = FramesPerSecond;
} }
void cRecordingInfo::SetFrameParams(uint16_t FrameWidth, uint16_t FrameHeight, eScanType ScanType, eAspectRatio AspectRatio)
{
frameWidth = FrameWidth;
frameHeight = FrameHeight;
scanType = ScanType;
aspectRatio = AspectRatio;
}
void cRecordingInfo::SetFileName(const char *FileName) void cRecordingInfo::SetFileName(const char *FileName)
{ {
bool IsPesRecording = fileName && endswith(fileName, ".vdr"); bool IsPesRecording = fileName && endswith(fileName, ".vdr");
@ -507,7 +522,35 @@ bool cRecordingInfo::Read(FILE *f)
} }
} }
break; break;
case 'F': framesPerSecond = atod(t); case 'F': {
char *fpsBuf = NULL;
char scanTypeCode;
char *arBuf = NULL;
int n = sscanf(t, "%m[^ ] %hu %hu %c %m[^\n]", &fpsBuf, &frameWidth, &frameHeight, &scanTypeCode, &arBuf);
if (n >= 1) {
framesPerSecond = atod(fpsBuf);
if (n >= 4) {
scanType = stUnknown;
for (int st = stUnknown + 1; st < stMax; st++) {
if (ScanTypeChars[st] == scanTypeCode) {
scanType = eScanType(st);
break;
}
}
aspectRatio = arUnknown;
if (n == 5) {
for (int ar = arUnknown + 1; ar < arMax; ar++) {
if (strcmp(arBuf, AspectRatioTexts[ar]) == 0) {
aspectRatio = eAspectRatio(ar);
break;
}
}
}
}
}
free(fpsBuf);
free(arBuf);
}
break; break;
case 'L': lifetime = atoi(t); case 'L': lifetime = atoi(t);
break; break;
@ -536,7 +579,10 @@ bool cRecordingInfo::Write(FILE *f, const char *Prefix) const
if (channelID.Valid()) if (channelID.Valid())
fprintf(f, "%sC %s%s%s\n", Prefix, *channelID.ToString(), channelName ? " " : "", channelName ? channelName : ""); fprintf(f, "%sC %s%s%s\n", Prefix, *channelID.ToString(), channelName ? " " : "", channelName ? channelName : "");
event->Dump(f, Prefix, true); event->Dump(f, Prefix, true);
fprintf(f, "%sF %s\n", Prefix, *dtoa(framesPerSecond, "%.10g")); if (frameWidth > 0 && frameHeight > 0)
fprintf(f, "%sF %s %s %s %c %s\n", Prefix, *dtoa(framesPerSecond, "%.10g"), *itoa(frameWidth), *itoa(frameHeight), ScanTypeChars[scanType], AspectRatioTexts[aspectRatio]);
else
fprintf(f, "%sF %s\n", Prefix, *dtoa(framesPerSecond, "%.10g"));
fprintf(f, "%sP %d\n", Prefix, priority); fprintf(f, "%sP %d\n", Prefix, priority);
fprintf(f, "%sL %d\n", Prefix, lifetime); fprintf(f, "%sL %d\n", Prefix, lifetime);
fprintf(f, "%sO %d\n", Prefix, errors); fprintf(f, "%sO %d\n", Prefix, errors);
@ -2520,8 +2566,12 @@ void cIndexFileGenerator::Action(void)
if (IndexFileWritten) { if (IndexFileWritten) {
cRecordingInfo RecordingInfo(recordingName); cRecordingInfo RecordingInfo(recordingName);
if (RecordingInfo.Read()) { if (RecordingInfo.Read()) {
if (FrameDetector.FramesPerSecond() > 0 && !DoubleEqual(RecordingInfo.FramesPerSecond(), FrameDetector.FramesPerSecond())) { if ((FrameDetector.FramesPerSecond() > 0 && !DoubleEqual(RecordingInfo.FramesPerSecond(), FrameDetector.FramesPerSecond())) ||
FrameDetector.FrameWidth() != RecordingInfo.FrameWidth() ||
FrameDetector.FrameHeight() != RecordingInfo.FrameHeight() ||
FrameDetector.AspectRatio() != RecordingInfo.AspectRatio()) {
RecordingInfo.SetFramesPerSecond(FrameDetector.FramesPerSecond()); RecordingInfo.SetFramesPerSecond(FrameDetector.FramesPerSecond());
RecordingInfo.SetFrameParams(FrameDetector.FrameWidth(), FrameDetector.FrameHeight(), FrameDetector.ScanType(), FrameDetector.AspectRatio());
RecordingInfo.Write(); RecordingInfo.Write();
LOCK_RECORDINGS_WRITE; LOCK_RECORDINGS_WRITE;
Recordings->UpdateByName(recordingName); Recordings->UpdateByName(recordingName);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recording.h 5.5 2021/05/23 15:03:17 kls Exp $ * $Id: recording.h 5.6 2023/12/27 09:21:29 kls Exp $
*/ */
#ifndef __RECORDING_H #ifndef __RECORDING_H
@ -17,6 +17,7 @@
#include "thread.h" #include "thread.h"
#include "timers.h" #include "timers.h"
#include "tools.h" #include "tools.h"
#include "remux.h"
#define FOLDERDELIMCHAR '~' #define FOLDERDELIMCHAR '~'
@ -69,6 +70,10 @@ private:
cEvent *ownEvent; cEvent *ownEvent;
char *aux; char *aux;
double framesPerSecond; double framesPerSecond;
uint16_t frameWidth;
uint16_t frameHeight;
eScanType scanType;
eAspectRatio aspectRatio;
int priority; int priority;
int lifetime; int lifetime;
char *fileName; char *fileName;
@ -87,7 +92,14 @@ public:
const cComponents *Components(void) const { return event->Components(); } const cComponents *Components(void) const { return event->Components(); }
const char *Aux(void) const { return aux; } const char *Aux(void) const { return aux; }
double FramesPerSecond(void) const { return framesPerSecond; } double FramesPerSecond(void) const { return framesPerSecond; }
uint16_t FrameWidth(void) const { return frameWidth; }
uint16_t FrameHeight(void) const { return frameHeight; }
eScanType ScanType(void) const { return scanType; }
char ScanTypeChar(void) const { return ScanTypeChars[scanType]; }
eAspectRatio AspectRatio(void) const { return aspectRatio; }
const char *AspectRatioText(void) const { return AspectRatioTexts[aspectRatio]; }
void SetFramesPerSecond(double FramesPerSecond); void SetFramesPerSecond(double FramesPerSecond);
void SetFrameParams(uint16_t FrameWidth, uint16_t FrameHeight, eScanType ScanType, eAspectRatio AspectRatio);
void SetFileName(const char *FileName); void SetFileName(const char *FileName);
int Errors(void) const { return errors; } // returns -1 if undefined int Errors(void) const { return errors; } // returns -1 if undefined
void SetErrors(int Errors); void SetErrors(int Errors);

60
remux.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: remux.c 5.5 2022/11/30 14:38:46 kls Exp $ * $Id: remux.c 5.6 2023/12/28 21:22:47 kls Exp $
*/ */
#include "remux.h" #include "remux.h"
@ -1177,7 +1177,8 @@ protected:
uint16_t frameWidth; uint16_t frameWidth;
uint16_t frameHeight; uint16_t frameHeight;
double framesPerSecond; double framesPerSecond;
bool progressive; eScanType scanType;
eAspectRatio aspectRatio;
public: public:
cFrameParser(void); cFrameParser(void);
virtual ~cFrameParser() {}; virtual ~cFrameParser() {};
@ -1195,7 +1196,8 @@ public:
uint16_t FrameWidth(void) { return frameWidth; } uint16_t FrameWidth(void) { return frameWidth; }
uint16_t FrameHeight(void) { return frameHeight; } uint16_t FrameHeight(void) { return frameHeight; }
double FramesPerSecond(void) { return framesPerSecond; } double FramesPerSecond(void) { return framesPerSecond; }
bool Progressive(void) { return progressive; } eScanType ScanType(void) { return scanType; }
eAspectRatio AspectRatio(void) { return aspectRatio; }
}; };
cFrameParser::cFrameParser(void) cFrameParser::cFrameParser(void)
@ -1207,7 +1209,8 @@ cFrameParser::cFrameParser(void)
frameWidth = 0; frameWidth = 0;
frameHeight = 0; frameHeight = 0;
framesPerSecond = 0.0; framesPerSecond = 0.0;
progressive = false; scanType = stUnknown;
aspectRatio = arUnknown;
} }
// --- cAudioParser ---------------------------------------------------------- // --- cAudioParser ----------------------------------------------------------
@ -1322,17 +1325,24 @@ int cMpeg2Parser::Parse(const uchar *Data, int Length, int Pid)
uchar b = tsPayload.GetByte(); // ignoring two MSB of width and height in sequence extension uchar b = tsPayload.GetByte(); // ignoring two MSB of width and height in sequence extension
frameWidth |= b >> 4; // as 12 Bit = max 4095 should be sufficient for all available MPEG2 streams frameWidth |= b >> 4; // as 12 Bit = max 4095 should be sufficient for all available MPEG2 streams
frameHeight = (b & 0x0F) << 8 | tsPayload.GetByte(); frameHeight = (b & 0x0F) << 8 | tsPayload.GetByte();
b = tsPayload.GetByte(); b = tsPayload.GetByte(); // hi: aspect ratio info, lo: frame rate code
switch (b >> 4) {
case 1: aspectRatio = ar_1_1; break;
case 2: aspectRatio = ar_4_3; break;
case 3: aspectRatio = ar_16_9; break;
case 4: aspectRatio = ar_2_21_1; break;
default: aspectRatio = arUnknown;
}
uchar frame_rate_value = b & 0x0F; uchar frame_rate_value = b & 0x0F;
if (frame_rate_value > 0 && frame_rate_value <= 8) if (frame_rate_value > 0 && frame_rate_value <= 8)
framesPerSecond = frame_rate_table[frame_rate_value]; framesPerSecond = frame_rate_table[frame_rate_value];
} }
else if (!seenScanType && scanner == 0x000001B5) { // Extension start code else if (!seenScanType && scanner == 0x000001B5) { // Extension start code
if ((tsPayload.GetByte() & 0xF0) == 0x10) { // Sequence Extension if ((tsPayload.GetByte() & 0xF0) == 0x10) { // Sequence Extension
progressive = (tsPayload.GetByte() & 0x40) != 0; scanType = (tsPayload.GetByte() & 0x40) ? stProgressive : stInterlaced;
seenScanType = true; seenScanType = true;
if (debug) { if (debug) {
cString s = cString::sprintf("MPEG2: %d x %d%c %.2f fps", frameWidth, frameHeight, progressive ? 'p' : 'i', framesPerSecond); cString s = cString::sprintf("MPEG2: %d x %d%c %.2f fps %s", frameWidth, frameHeight, ScanTypeChars[scanType], framesPerSecond, AspectRatioTexts[aspectRatio]);
dsyslog("%s", *s); dsyslog("%s", *s);
dbgframes("\n%s", *s); dbgframes("\n%s", *s);
} }
@ -1553,7 +1563,7 @@ void cH264Parser::ParseSequenceParameterSet(void)
uint16_t frame_Height = 16 * (1 + GetGolombUe()); // pic_height_in_map_units_minus1 uint16_t frame_Height = 16 * (1 + GetGolombUe()); // pic_height_in_map_units_minus1
frame_mbs_only_flag = GetBit(); // frame_mbs_only_flag frame_mbs_only_flag = GetBit(); // frame_mbs_only_flag
if (frameWidth == 0) { if (frameWidth == 0) {
progressive = frame_mbs_only_flag; scanType = frame_mbs_only_flag ? stProgressive : stInterlaced;
if (!frame_mbs_only_flag) { if (!frame_mbs_only_flag) {
GetBit(); // mb_adaptive_frame_field_flag GetBit(); // mb_adaptive_frame_field_flag
frame_Height *= 2; frame_Height *= 2;
@ -1584,8 +1594,11 @@ void cH264Parser::ParseSequenceParameterSet(void)
if (GetBit()) { // vui_parameters_present_flag if (GetBit()) { // vui_parameters_present_flag
if (GetBit()) { // aspect_ratio_info_present if (GetBit()) { // aspect_ratio_info_present
int aspect_ratio_idc = GetBits(8); // aspect_ratio_idc int aspect_ratio_idc = GetBits(8); // aspect_ratio_idc
if (aspect_ratio_idc == 255) if (aspect_ratio_idc == 255) // EXTENDED_SAR
GetBits(32); GetBits(32); // sar_width, sar_height
else if (frameHeight >= 720 && (aspect_ratio_idc == 1 || aspect_ratio_idc == 14 || aspect_ratio_idc == 15 || aspect_ratio_idc == 16))
aspectRatio = ar_16_9;
// implement decoding of other aspect_ratio_idc values when they are required
} }
if (GetBit()) // overscan_info_present_flag if (GetBit()) // overscan_info_present_flag
GetBit(); // overscan_approriate_flag GetBit(); // overscan_approriate_flag
@ -1606,7 +1619,7 @@ void cH264Parser::ParseSequenceParameterSet(void)
} }
} }
if (debug) { if (debug) {
cString s = cString::sprintf("H.264: %d x %d%c %.2f fps %d Bit", frameWidth, frameHeight, progressive ? 'p':'i', framesPerSecond, bitDepth); cString s = cString::sprintf("H.264: %d x %d%c %.2f fps %d Bit %s", frameWidth, frameHeight, ScanTypeChars[scanType], framesPerSecond, bitDepth, AspectRatioTexts[aspectRatio]);
dsyslog("%s", *s); dsyslog("%s", *s);
dbgframes("\n%s", *s); dbgframes("\n%s", *s);
} }
@ -1737,7 +1750,7 @@ void cH265Parser::ParseSequenceParameterSet(void)
GetByte(); GetByte();
GetByte(); GetByte();
bool general_progressive_source_flag = GetBit(); // general_progressive_source_flag bool general_progressive_source_flag = GetBit(); // general_progressive_source_flag
progressive = general_progressive_source_flag; scanType = general_progressive_source_flag ? stProgressive : stInterlaced;
GetBit(); // general_interlaced_source_flag GetBit(); // general_interlaced_source_flag
GetBits(6); GetBits(6);
GetByte(); GetByte();
@ -1880,6 +1893,9 @@ void cH265Parser::ParseSequenceParameterSet(void)
int aspect_ratio_idc = GetBits(8); // aspect_ratio_idc int aspect_ratio_idc = GetBits(8); // aspect_ratio_idc
if (aspect_ratio_idc == 255) // EXTENDED_SAR if (aspect_ratio_idc == 255) // EXTENDED_SAR
GetBits(32); // sar_width, sar_height GetBits(32); // sar_width, sar_height
else if (aspect_ratio_idc == 1 || aspect_ratio_idc == 14)
aspectRatio = ar_16_9;
// implement decoding of other aspect_ratio_idc values when they are required
} }
if (GetBit()) // overscan_info_present_flag if (GetBit()) // overscan_info_present_flag
GetBit(); // overscan_appropriate_flag GetBit(); // overscan_appropriate_flag
@ -1907,7 +1923,7 @@ void cH265Parser::ParseSequenceParameterSet(void)
} }
} }
if (debug) { if (debug) {
cString s = cString::sprintf("H.265: %d x %d%c %.2f fps %d Bit", frameWidth, frameHeight, progressive ? 'p':'i', framesPerSecond, bitDepth); cString s = cString::sprintf("H.265: %d x %d%c %.2f fps %d Bit %s", frameWidth, frameHeight, ScanTypeChars[scanType], framesPerSecond, bitDepth, AspectRatioTexts[aspectRatio]);
dsyslog("%s", *s); dsyslog("%s", *s);
dbgframes("\n%s", *s); dbgframes("\n%s", *s);
} }
@ -1915,6 +1931,16 @@ void cH265Parser::ParseSequenceParameterSet(void)
// --- cFrameDetector -------------------------------------------------------- // --- cFrameDetector --------------------------------------------------------
const char *ScanTypeChars = "-pi"; // index is eScanType
const char *AspectRatioTexts[] = { // index is eAspectRatio
"-",
"1:1",
"4:3",
"16:9",
"2.21:1",
NULL
};
cFrameDetector::cFrameDetector(int Pid, int Type) cFrameDetector::cFrameDetector(int Pid, int Type)
{ {
parser = NULL; parser = NULL;
@ -1924,6 +1950,10 @@ cFrameDetector::cFrameDetector(int Pid, int Type)
numPtsValues = 0; numPtsValues = 0;
numIFrames = 0; numIFrames = 0;
framesPerSecond = 0; framesPerSecond = 0;
frameWidth = 0;
frameHeight = 0;
scanType = stUnknown;
aspectRatio = arUnknown;
framesInPayloadUnit = framesPerPayloadUnit = 0; framesInPayloadUnit = framesPerPayloadUnit = 0;
scanning = false; scanning = false;
} }
@ -1991,6 +2021,10 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
else { else {
if (parser->FramesPerSecond() > 0.0) { if (parser->FramesPerSecond() > 0.0) {
framesPerSecond = parser->FramesPerSecond(); framesPerSecond = parser->FramesPerSecond();
frameWidth = parser->FrameWidth();
frameHeight = parser->FrameHeight();
scanType = parser->ScanType();
aspectRatio = parser->AspectRatio();
synced = true; synced = true;
parser->SetDebug(false); parser->SetDebug(false);
} }

33
remux.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: remux.h 5.2 2021/12/25 14:11:39 kls Exp $ * $Id: remux.h 5.3 2023/12/27 09:30:42 kls Exp $
*/ */
#ifndef __REMUX_H #ifndef __REMUX_H
@ -504,6 +504,25 @@ void PesDump(const char *Name, const u_char *Data, int Length);
class cFrameParser; class cFrameParser;
enum eScanType {
stUnknown = 0,
stProgressive = 1,
stInterlaced = 2,
stMax
};
enum eAspectRatio {
arUnknown = 0,
ar_1_1 = 1,
ar_4_3 = 2,
ar_16_9 = 3,
ar_2_21_1 = 4,
arMax
};
extern const char *ScanTypeChars;
extern const char *AspectRatioTexts[];
class cFrameDetector { class cFrameDetector {
private: private:
enum { MaxPtsValues = 150 }; enum { MaxPtsValues = 150 };
@ -517,6 +536,10 @@ private:
int numIFrames; int numIFrames;
bool isVideo; bool isVideo;
double framesPerSecond; double framesPerSecond;
uint16_t frameWidth;
uint16_t frameHeight;
eScanType scanType;
eAspectRatio aspectRatio;
int framesInPayloadUnit; int framesInPayloadUnit;
int framesPerPayloadUnit; // Some broadcasters send one frame per payload unit (== 1), int framesPerPayloadUnit; // Some broadcasters send one frame per payload unit (== 1),
// while others put an entire GOP into one payload unit (> 1). // while others put an entire GOP into one payload unit (> 1).
@ -547,6 +570,14 @@ public:
double FramesPerSecond(void) { return framesPerSecond; } double FramesPerSecond(void) { return framesPerSecond; }
///< Returns the number of frames per second, or 0 if this information is not ///< Returns the number of frames per second, or 0 if this information is not
///< available. ///< available.
uint16_t FrameWidth(void) { return frameWidth; }
///< Returns the frame width, or 0 if this information is not available.
uint16_t FrameHeight(void) { return frameHeight; }
///< Returns the frame height, or 0 if this information is not available.
eScanType ScanType(void) { return scanType; }
///< Returns the scan type, or stUnknown if this information is not available.
eAspectRatio AspectRatio(void) { return aspectRatio; }
///< Returns the aspect ratio, or arUnknown if this information is not available.
}; };
#endif // __REMUX_H #endif // __REMUX_H

4
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" vdr distribution.
.\" .\"
.\" $Id: vdr.5 5.8 2022/12/26 13:24:09 kls Exp $ .\" $Id: vdr.5 5.9 2023/12/25 20:53:04 kls Exp $
.\" .\"
.TH vdr 5 "27 Dec 2021" "2.6" "Video Disk Recorder Files" .TH vdr 5 "27 Dec 2021" "2.6" "Video Disk Recorder Files"
.SH NAME .SH NAME
@ -814,7 +814,7 @@ characters are defined:
.TS .TS
tab (|); tab (|);
l l. l l.
\fBF\fR|<frame rate> \fBF\fR|<frame rate> <frame width> <frame height> <scan type> <aspect ratio>
\fBL\fR|<lifetime> \fBL\fR|<lifetime>
\fBP\fR|<priority> \fBP\fR|<priority>
\fBO\fR|<errors> \fBO\fR|<errors>