mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
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:
parent
1770a18598
commit
6458f8b581
@ -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
|
||||||
|
4
HISTORY
4
HISTORY
@ -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).
|
||||||
|
@ -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);
|
||||||
|
60
recording.c
60
recording.c
@ -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);
|
||||||
|
14
recording.h
14
recording.h
@ -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
60
remux.c
@ -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
33
remux.h
@ -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
4
vdr.5
@ -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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user