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),
|
formatM(VIDEO_FORMAT_INVALID),
|
||||||
frameRateM(0),
|
frameRateM(0),
|
||||||
bitRateM(0),
|
bitRateM(0),
|
||||||
scanM(VIDEO_SCAN_INVALID)
|
scanM(VIDEO_SCAN_PROGRESSIVE)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
@ -28,7 +28,8 @@ cFemonH265::~cFemonH265()
|
|||||||
|
|
||||||
bool cFemonH265::processVideo(const uint8_t *bufP, int lenP)
|
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 *buf = bufP;
|
||||||
const uint8_t *start = buf;
|
const uint8_t *start = buf;
|
||||||
const uint8_t *end = start + lenP;
|
const uint8_t *end = start + lenP;
|
||||||
@ -54,8 +55,18 @@ bool cFemonH265::processVideo(const uint8_t *bufP, int lenP)
|
|||||||
switch ((buf[3] >> 1) & 0x3F) {
|
switch ((buf[3] >> 1) & 0x3F) {
|
||||||
case NAL_AUD:
|
case NAL_AUD:
|
||||||
if (!aud_found) {
|
if (!aud_found) {
|
||||||
aud_found = true;
|
|
||||||
debug2("%s Found NAL AUD at offset %d/%d", __PRETTY_FUNCTION__, int(buf - start), lenP);
|
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;
|
break;
|
||||||
|
|
||||||
@ -63,7 +74,7 @@ bool cFemonH265::processVideo(const uint8_t *bufP, int lenP)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aud_found)
|
if (aud_found && sps_found)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
buf += consumed + 4;
|
buf += consumed + 4;
|
||||||
@ -71,15 +82,18 @@ bool cFemonH265::processVideo(const uint8_t *bufP, int lenP)
|
|||||||
|
|
||||||
if (aud_found) {
|
if (aud_found) {
|
||||||
videoHandlerM->SetVideoCodec(VIDEO_CODEC_H265);
|
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->SetVideoFormat(formatM);
|
||||||
//videoHandlerM->SetVideoSize(widthM, heightM);
|
|
||||||
//videoHandlerM->SetVideoAspectRatio(aspectRatioM);
|
//videoHandlerM->SetVideoAspectRatio(aspectRatioM);
|
||||||
//videoHandlerM->SetVideoBitrate(bitRateM);
|
//videoHandlerM->SetVideoBitrate(bitRateM);
|
||||||
//videoHandlerM->SetVideoScan(scanM);
|
//videoHandlerM->SetVideoFramerate(frameRateM);
|
||||||
//videoHandlerM->SetVideoFramerate((scanM == VIDEO_SCAN_PROGRESSIVE) ? (frameRateM / 2) : frameRateM);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return aud_found;
|
return sps_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cFemonH265::reset()
|
void cFemonH265::reset()
|
||||||
@ -116,3 +130,74 @@ int cFemonH265::nalUnescape(uint8_t *dstP, const uint8_t *srcP, int lenP)
|
|||||||
|
|
||||||
return d;
|
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();
|
void reset();
|
||||||
const uint8_t *nextStartCode(const uint8_t *start, const uint8_t *end);
|
const uint8_t *nextStartCode(const uint8_t *start, const uint8_t *end);
|
||||||
int nalUnescape(uint8_t *dst, const uint8_t *src, int len);
|
int nalUnescape(uint8_t *dst, const uint8_t *src, int len);
|
||||||
|
int parseSPS(const uint8_t *buf, int len);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cFemonH265(cFemonVideoIf *videoHandlerP);
|
cFemonH265(cFemonVideoIf *videoHandlerP);
|
||||||
|
9
osd.c
9
osd.c
@ -307,7 +307,14 @@ void cFemonOsd::DrawStatusWindow(void)
|
|||||||
OSDDRAWSTATUSBM(OSDSPACING);
|
OSDDRAWSTATUSBM(OSDSPACING);
|
||||||
}
|
}
|
||||||
if (receiverM) {
|
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()) {
|
switch (receiverM->VideoScan()) {
|
||||||
case VIDEO_SCAN_INTERLACED: bm = &OSDSYMBOL(SYMBOL_FORMAT_1080i); break;
|
case VIDEO_SCAN_INTERLACED: bm = &OSDSYMBOL(SYMBOL_FORMAT_1080i); break;
|
||||||
case VIDEO_SCAN_PROGRESSIVE: bm = &OSDSYMBOL(SYMBOL_FORMAT_1080p); 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/six.xpm"
|
||||||
#include "symbols/seven.xpm"
|
#include "symbols/seven.xpm"
|
||||||
#include "symbols/eight.xpm"
|
#include "symbols/eight.xpm"
|
||||||
|
#include "symbols/format2160.xpm"
|
||||||
|
#include "symbols/format2160i.xpm"
|
||||||
|
#include "symbols/format2160p.xpm"
|
||||||
#include "symbols/format1080.xpm"
|
#include "symbols/format1080.xpm"
|
||||||
#include "symbols/format1080i.xpm"
|
#include "symbols/format1080i.xpm"
|
||||||
#include "symbols/format1080p.xpm"
|
#include "symbols/format1080p.xpm"
|
||||||
@ -89,6 +92,9 @@ static cBitmap bmFive(five_xpm);
|
|||||||
static cBitmap bmSix(six_xpm);
|
static cBitmap bmSix(six_xpm);
|
||||||
static cBitmap bmSeven(seven_xpm);
|
static cBitmap bmSeven(seven_xpm);
|
||||||
static cBitmap bmEight(eight_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 bmFormat1080(format1080_xpm);
|
||||||
static cBitmap bmFormat1080i(format1080i_xpm);
|
static cBitmap bmFormat1080i(format1080i_xpm);
|
||||||
static cBitmap bmFormat1080p(format1080p_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(bmSix.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_SIX
|
||||||
cacheM.Append(bmSeven.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_SEVEN
|
cacheM.Append(bmSeven.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_SEVEN
|
||||||
cacheM.Append(bmEight.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_EIGHT
|
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(bmFormat1080.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_1080
|
||||||
cacheM.Append(bmFormat1080i.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_1080i
|
cacheM.Append(bmFormat1080i.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_1080i
|
||||||
cacheM.Append(bmFormat1080p.Scaled(yFactorM, yFactorM, antiAliasM)); // SYMBOL_FORMAT_1080p
|
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_SIX,
|
||||||
SYMBOL_SEVEN,
|
SYMBOL_SEVEN,
|
||||||
SYMBOL_EIGHT,
|
SYMBOL_EIGHT,
|
||||||
|
SYMBOL_FORMAT_2160,
|
||||||
|
SYMBOL_FORMAT_2160i,
|
||||||
|
SYMBOL_FORMAT_2160p,
|
||||||
SYMBOL_FORMAT_1080,
|
SYMBOL_FORMAT_1080,
|
||||||
SYMBOL_FORMAT_1080i,
|
SYMBOL_FORMAT_1080i,
|
||||||
SYMBOL_FORMAT_1080p,
|
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