mirror of
https://github.com/rofafor/vdr-plugin-femon.git
synced 2023-10-10 13:36:53 +02:00
Detect H.265 video resolution.
This commit is contained in:
parent
ba767e02bf
commit
3e78ac0987
101
h265.c
101
h265.c
@ -17,7 +17,7 @@ cFemonH265::cFemonH265(cFemonVideoIf *videoHandlerP)
|
||||
formatM(VIDEO_FORMAT_INVALID),
|
||||
frameRateM(0),
|
||||
bitRateM(0),
|
||||
scanM(VIDEO_SCAN_INVALID)
|
||||
scanM(VIDEO_SCAN_PROGRESSIVE)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
@ -28,7 +28,8 @@ cFemonH265::~cFemonH265()
|
||||
|
||||
bool cFemonH265::processVideo(const uint8_t *bufP, int lenP)
|
||||
{
|
||||
bool aud_found = false;
|
||||
uint8_t nal_data[lenP];
|
||||
bool aud_found = false, sps_found = false;
|
||||
const uint8_t *buf = bufP;
|
||||
const uint8_t *start = buf;
|
||||
const uint8_t *end = start + lenP;
|
||||
@ -54,8 +55,18 @@ bool cFemonH265::processVideo(const uint8_t *bufP, int lenP)
|
||||
switch ((buf[3] >> 1) & 0x3F) {
|
||||
case NAL_AUD:
|
||||
if (!aud_found) {
|
||||
aud_found = true;
|
||||
debug2("%s Found NAL AUD at offset %d/%d", __PRETTY_FUNCTION__, int(buf - start), lenP);
|
||||
aud_found = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAL_SPS:
|
||||
if (!sps_found) {
|
||||
debug2("%s Found NAL SPS at offset %d/%d", __PRETTY_FUNCTION__, int(buf - start), lenP);
|
||||
int nal_len = nalUnescape(nal_data, buf + 4, int(end - buf - 4));
|
||||
consumed = parseSPS(nal_data, nal_len);
|
||||
if (consumed > 0)
|
||||
sps_found = true;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -63,7 +74,7 @@ bool cFemonH265::processVideo(const uint8_t *bufP, int lenP)
|
||||
break;
|
||||
}
|
||||
|
||||
if (aud_found)
|
||||
if (aud_found && sps_found)
|
||||
break;
|
||||
|
||||
buf += consumed + 4;
|
||||
@ -71,15 +82,18 @@ bool cFemonH265::processVideo(const uint8_t *bufP, int lenP)
|
||||
|
||||
if (aud_found) {
|
||||
videoHandlerM->SetVideoCodec(VIDEO_CODEC_H265);
|
||||
if (sps_found) {
|
||||
debug2("%s width=%d height=%d, aspect=%d format=%d bitrate=%.0f scan=%d framerate=%.2f", __PRETTY_FUNCTION__, widthM, heightM, aspectRatioM, formatM, bitRateM, scanM, frameRateM);
|
||||
videoHandlerM->SetVideoSize(widthM, heightM);
|
||||
videoHandlerM->SetVideoScan(scanM);
|
||||
//videoHandlerM->SetVideoFormat(formatM);
|
||||
//videoHandlerM->SetVideoSize(widthM, heightM);
|
||||
//videoHandlerM->SetVideoAspectRatio(aspectRatioM);
|
||||
//videoHandlerM->SetVideoBitrate(bitRateM);
|
||||
//videoHandlerM->SetVideoScan(scanM);
|
||||
//videoHandlerM->SetVideoFramerate((scanM == VIDEO_SCAN_PROGRESSIVE) ? (frameRateM / 2) : frameRateM);
|
||||
//videoHandlerM->SetVideoFramerate(frameRateM);
|
||||
}
|
||||
}
|
||||
|
||||
return aud_found;
|
||||
return sps_found;
|
||||
}
|
||||
|
||||
void cFemonH265::reset()
|
||||
@ -116,3 +130,74 @@ int cFemonH265::nalUnescape(uint8_t *dstP, const uint8_t *srcP, int lenP)
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
int cFemonH265::parseSPS(const uint8_t *bufP, int lenP)
|
||||
{
|
||||
cFemonBitStream bs(bufP, lenP);
|
||||
|
||||
uint32_t width = widthM;
|
||||
uint32_t height = heightM;
|
||||
bool profilePresentFlag = true;
|
||||
unsigned int chroma_format_idc;
|
||||
uint8_t sps_max_sub_layers_minus1;
|
||||
uint8_t sub_layer_profile_present_flag[8];
|
||||
uint8_t sub_layer_level_present_flag[8];
|
||||
|
||||
bs.SkipBits(4); // sps_video_parameter_set_id
|
||||
sps_max_sub_layers_minus1 = bs.GetBits(3); // sps_max_sub_layers_minus1
|
||||
bs.SkipBit(); // sps_temporal_id_nesting_flag
|
||||
// start of profile_tier_level(1, sps_max_sub_layers_minus1)
|
||||
if (profilePresentFlag) {
|
||||
bs.SkipBits(2); // general_profile_space
|
||||
bs.SkipBit(); // general_profile_space
|
||||
bs.SkipBits(5); // general_profile_idc
|
||||
bs.SkipBits(32); // general_profile_compatibility_flag[0-31]
|
||||
bs.SkipBit(); // general_progressive_source_flag
|
||||
bs.SkipBit(); // general_interlaced_source_flag
|
||||
bs.SkipBit(); // general_non_packed_constraint_flag
|
||||
bs.SkipBit(); // general_frame_only_constraint_flag
|
||||
// the number of bits in this syntax structure is not affected by this condition
|
||||
bs.SkipBits(43); // general_reserved_zero_43bits
|
||||
// the number of bits in this syntax structure is not affected by this condition
|
||||
bs.SkipBit(); // general_reserved_zero_bit
|
||||
}
|
||||
bs.SkipBits(8); // general_level_idc
|
||||
for (int i = 0; i < sps_max_sub_layers_minus1; ++i) {
|
||||
sub_layer_profile_present_flag[i] = bs.GetBit(); // sub_layer_profile_present_flag[i]
|
||||
sub_layer_level_present_flag[i] = bs.GetBit(); // sub_layer_level_present_flag[i]
|
||||
}
|
||||
if (sps_max_sub_layers_minus1 > 0) {
|
||||
for (int i = sps_max_sub_layers_minus1; i < 8; ++i)
|
||||
bs.SkipBits(2); // reserved_zero_2bits[i]
|
||||
}
|
||||
for (int i = 0; i < sps_max_sub_layers_minus1; ++i) {
|
||||
if (sub_layer_profile_present_flag[i]) {
|
||||
bs.SkipBits(2); // sub_layer_profile_space[i]
|
||||
bs.SkipBit(); // sub_layer_tier_flag[i]
|
||||
bs.SkipBits(5); // sub_layer_profile_idc[i]
|
||||
bs.SkipBits(32); // sub_layer_profile_compatibility_flag[i][0-31]
|
||||
bs.SkipBit(); // sub_layer_progressive_source_flag[i]
|
||||
bs.SkipBit(); // sub_layer_interlaced_source_flag[i]
|
||||
bs.SkipBit(); // sub_layer_non_packed_constraint_flag[i]
|
||||
bs.SkipBit(); // sub_layer_frame_only_constraint_flag[i]
|
||||
// the number of bits in this syntax structure is not affected by this condition
|
||||
bs.SkipBits(43); // sub_layer_reserved_zero_43bits[i]
|
||||
// the number of bits in this syntax structure is not affected by this condition
|
||||
bs.SkipBit(); // sub_layer_reserved_zero_bit[i]
|
||||
}
|
||||
if (sub_layer_level_present_flag[i])
|
||||
bs.SkipBits(8); // sub_layer_level_idc[i]
|
||||
}
|
||||
// end of profile_tier_level
|
||||
bs.SkipUeGolomb(); // sps_seq_parameter_set_id
|
||||
chroma_format_idc = bs.GetUeGolomb(); // chroma_format_idc
|
||||
if (chroma_format_idc == 3)
|
||||
bs.SkipBit(); // separate_colour_plane_flag
|
||||
width = bs.GetUeGolomb(); // pic_width_in_luma_samples
|
||||
height = bs.GetUeGolomb(); // pic_height_in_luma_samples
|
||||
|
||||
widthM = width;
|
||||
heightM = height;
|
||||
|
||||
return (bs.Index() / 8);
|
||||
}
|
||||
|
1
h265.h
1
h265.h
@ -33,6 +33,7 @@ private:
|
||||
void reset();
|
||||
const uint8_t *nextStartCode(const uint8_t *start, const uint8_t *end);
|
||||
int nalUnescape(uint8_t *dst, const uint8_t *src, int len);
|
||||
int parseSPS(const uint8_t *buf, int len);
|
||||
|
||||
public:
|
||||
cFemonH265(cFemonVideoIf *videoHandlerP);
|
||||
|
9
osd.c
9
osd.c
@ -307,7 +307,14 @@ void cFemonOsd::DrawStatusWindow(void)
|
||||
OSDDRAWSTATUSBM(OSDSPACING);
|
||||
}
|
||||
if (receiverM) {
|
||||
if (IS_OSDRESOLUTION(receiverM->VideoVerticalSize(), 1080)) {
|
||||
if (IS_OSDRESOLUTION(receiverM->VideoVerticalSize(), 2160)) {
|
||||
switch (receiverM->VideoScan()) {
|
||||
case VIDEO_SCAN_INTERLACED: bm = &OSDSYMBOL(SYMBOL_FORMAT_2160i); break;
|
||||
case VIDEO_SCAN_PROGRESSIVE: bm = &OSDSYMBOL(SYMBOL_FORMAT_2160p); break;
|
||||
default: bm = &OSDSYMBOL(SYMBOL_FORMAT_2160); break;
|
||||
}
|
||||
}
|
||||
else if (IS_OSDRESOLUTION(receiverM->VideoVerticalSize(), 1080)) {
|
||||
switch (receiverM->VideoScan()) {
|
||||
case VIDEO_SCAN_INTERLACED: bm = &OSDSYMBOL(SYMBOL_FORMAT_1080i); break;
|
||||
case VIDEO_SCAN_PROGRESSIVE: bm = &OSDSYMBOL(SYMBOL_FORMAT_1080p); break;
|
||||
|
9
symbol.c
9
symbol.c
@ -43,6 +43,9 @@
|
||||
#include "symbols/six.xpm"
|
||||
#include "symbols/seven.xpm"
|
||||
#include "symbols/eight.xpm"
|
||||
#include "symbols/format2160.xpm"
|
||||
#include "symbols/format2160i.xpm"
|
||||
#include "symbols/format2160p.xpm"
|
||||
#include "symbols/format1080.xpm"
|
||||
#include "symbols/format1080i.xpm"
|
||||
#include "symbols/format1080p.xpm"
|
||||
@ -89,6 +92,9 @@ static cBitmap bmFive(five_xpm);
|
||||
static cBitmap bmSix(six_xpm);
|
||||
static cBitmap bmSeven(seven_xpm);
|
||||
static cBitmap bmEight(eight_xpm);
|
||||
static cBitmap bmFormat2160(format2160_xpm);
|
||||
static cBitmap bmFormat2160i(format2160i_xpm);
|
||||
static cBitmap bmFormat2160p(format2160p_xpm);
|
||||
static cBitmap bmFormat1080(format1080_xpm);
|
||||
static cBitmap bmFormat1080i(format1080i_xpm);
|
||||
static cBitmap bmFormat1080p(format1080p_xpm);
|
||||
@ -172,6 +178,9 @@ bool cFemonSymbolCache::Populate(void)
|
||||
cacheM.Append(bmSix.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_SIX
|
||||
cacheM.Append(bmSeven.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_SEVEN
|
||||
cacheM.Append(bmEight.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_EIGHT
|
||||
cacheM.Append(bmFormat2160.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_2160
|
||||
cacheM.Append(bmFormat2160i.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_2160i
|
||||
cacheM.Append(bmFormat2160p.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_2160p
|
||||
cacheM.Append(bmFormat1080.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_1080
|
||||
cacheM.Append(bmFormat1080i.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_1080i
|
||||
cacheM.Append(bmFormat1080p.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_1080p
|
||||
|
3
symbol.h
3
symbol.h
@ -45,6 +45,9 @@ enum eSymbols {
|
||||
SYMBOL_SIX,
|
||||
SYMBOL_SEVEN,
|
||||
SYMBOL_EIGHT,
|
||||
SYMBOL_FORMAT_2160,
|
||||
SYMBOL_FORMAT_2160i,
|
||||
SYMBOL_FORMAT_2160p,
|
||||
SYMBOL_FORMAT_1080,
|
||||
SYMBOL_FORMAT_1080i,
|
||||
SYMBOL_FORMAT_1080p,
|
||||
|
23
symbols/format2160.xpm
Normal file
23
symbols/format2160.xpm
Normal file
@ -0,0 +1,23 @@
|
||||
/* XPM */
|
||||
static const char *const format2160_xpm[] = {
|
||||
"40 18 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"++++++++++++++++++++++++++++++++++++++++",
|
||||
"+......................................+",
|
||||
"+.....++++......++..++++++....++++.....+",
|
||||
"+...+++++++..+++++.++++++++..++++++....+",
|
||||
"+...++....++.+++++.+++...++..++..++....+",
|
||||
"+.........++....++.++.......++....++...+",
|
||||
"+.........++....++.++.......++....++...+",
|
||||
"+.........++....++.++.+++...++....++...+",
|
||||
"+.......+++.....++.+++++++..++....++...+",
|
||||
"+......+++......++.+++..+++.++....++...+",
|
||||
"+.....+++.......++.++....++.++....++...+",
|
||||
"+.....+++.......++.++....++.++....++...+",
|
||||
"+....+++........++.++....++.++....++...+",
|
||||
"+....++.........++.+++..+++..++..++....+",
|
||||
"+....++++++++...++..+++++++..++++++....+",
|
||||
"+....++++++++...++...+++++....++++.....+",
|
||||
"+......................................+",
|
||||
"++++++++++++++++++++++++++++++++++++++++"};
|
23
symbols/format2160i.xpm
Normal file
23
symbols/format2160i.xpm
Normal file
@ -0,0 +1,23 @@
|
||||
/* XPM */
|
||||
static const char *const format2160i_xpm[] = {
|
||||
"43 18 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"+++++++++++++++++++++++++++++++++++++++++++",
|
||||
"+.........................................+",
|
||||
"+.....++++......++..++++++....++++........+",
|
||||
"+...+++++++..+++++.++++++++..++++++.......+",
|
||||
"+...++....++.+++++.+++...++..++..++.......+",
|
||||
"+.........++....++.++.......++....++......+",
|
||||
"+.........++....++.++.......++....++.++...+",
|
||||
"+.........++....++.++.+++...++....++.++...+",
|
||||
"+.......+++.....++.+++++++..++....++......+",
|
||||
"+......+++......++.+++..+++.++....++.++...+",
|
||||
"+.....+++.......++.++....++.++....++.++...+",
|
||||
"+.....+++.......++.++....++.++....++.++...+",
|
||||
"+....+++........++.++....++.++....++.++...+",
|
||||
"+....++.........++.+++..+++..++..++..++...+",
|
||||
"+....++++++++...++..+++++++..++++++..++...+",
|
||||
"+....++++++++...++...+++++....++++...++...+",
|
||||
"+.........................................+",
|
||||
"+++++++++++++++++++++++++++++++++++++++++++"};
|
23
symbols/format2160p.xpm
Normal file
23
symbols/format2160p.xpm
Normal file
@ -0,0 +1,23 @@
|
||||
/* XPM */
|
||||
static const char *const format2160p_xpm[] = {
|
||||
"47 18 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"+++++++++++++++++++++++++++++++++++++++++++++++",
|
||||
"+.............................................+",
|
||||
"+.....++++......++..++++++....++++............+",
|
||||
"+...+++++++..+++++.++++++++..++++++...........+",
|
||||
"+...++....++.+++++.+++...++..++..++...........+",
|
||||
"+.........++....++.++.......++....++..........+",
|
||||
"+.........++....++.++.......++....++..........+",
|
||||
"+.........++....++.++.+++...++....++.++++.....+",
|
||||
"+.......+++.....++.+++++++..++....++.+++++....+",
|
||||
"+......+++......++.+++..+++.++....++.++..++...+",
|
||||
"+.....+++.......++.++....++.++....++.++..++...+",
|
||||
"+.....+++.......++.++....++.++....++.+++++....+",
|
||||
"+....+++........++.++....++.++....++.++++.....+",
|
||||
"+....++.........++.+++..+++..++..++..++.......+",
|
||||
"+....++++++++...++..+++++++..++++++..++.......+",
|
||||
"+....++++++++...++...+++++....++++...++.......+",
|
||||
"+.............................................+",
|
||||
"+++++++++++++++++++++++++++++++++++++++++++++++"};
|
Loading…
Reference in New Issue
Block a user