mirror of
https://github.com/rofafor/vdr-plugin-femon.git
synced 2023-10-10 11:36:53 +00:00
Fixed H.264 parser.
This commit is contained in:
parent
167da08ab3
commit
53b42a2d4a
3
HISTORY
3
HISTORY
@ -365,7 +365,8 @@ VDR Plugin 'femon' Revision History
|
|||||||
- Cleaned up compilation warnings.
|
- Cleaned up compilation warnings.
|
||||||
- Fixed font handling to be thread-safe.
|
- Fixed font handling to be thread-safe.
|
||||||
|
|
||||||
2009-07-xx: Version 1.7.3
|
2009-08-28: Version 1.7.3
|
||||||
|
|
||||||
- Removed OSD offset and height options.
|
- Removed OSD offset and height options.
|
||||||
- Added PES assembler.
|
- Added PES assembler.
|
||||||
|
- Added bitstream parsers for all codecs.
|
||||||
|
227
femonh264.c
227
femonh264.c
@ -42,9 +42,23 @@ const eVideoFormat cFemonH264::s_VideoFormats[] =
|
|||||||
VIDEO_FORMAT_RESERVED
|
VIDEO_FORMAT_RESERVED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uint8_t cFemonH264::s_SeiNumClockTsTable[9] =
|
||||||
|
{
|
||||||
|
1, 1, 1, 2, 2, 3, 3, 2, 3
|
||||||
|
};
|
||||||
|
|
||||||
cFemonH264::cFemonH264(cFemonVideoIf *videohandler)
|
cFemonH264::cFemonH264(cFemonVideoIf *videohandler)
|
||||||
: m_VideoHandler(videohandler)
|
: m_VideoHandler(videohandler),
|
||||||
|
m_Width(0),
|
||||||
|
m_Height(0),
|
||||||
|
m_AspectRatio(VIDEO_ASPECT_RATIO_INVALID),
|
||||||
|
m_Format(VIDEO_FORMAT_INVALID),
|
||||||
|
m_FrameRate(0),
|
||||||
|
m_BitRate(0),
|
||||||
|
m_Scan(VIDEO_SCAN_INVALID),
|
||||||
|
m_CpbDpbDelaysPresentFlag(false),
|
||||||
|
m_PicStructPresentFlag(false),
|
||||||
|
m_TimeOffsetLength(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +68,10 @@ cFemonH264::~cFemonH264()
|
|||||||
|
|
||||||
bool cFemonH264::processVideo(const uint8_t *buf, int len)
|
bool cFemonH264::processVideo(const uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
bool aud_found = false, sps_found = false, sei_found = true; // sei currently disabled
|
uint8_t nal_data[len];
|
||||||
|
bool aud_found = false, sps_found = false, sei_found = false;
|
||||||
|
const uint8_t *start = buf;
|
||||||
|
const uint8_t *end = start + len;
|
||||||
|
|
||||||
if (!m_VideoHandler)
|
if (!m_VideoHandler)
|
||||||
return false;
|
return false;
|
||||||
@ -63,10 +80,7 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len)
|
|||||||
if (!PesLongEnough(len))
|
if (!PesLongEnough(len))
|
||||||
return false;
|
return false;
|
||||||
buf += PesPayloadOffset(buf);
|
buf += PesPayloadOffset(buf);
|
||||||
|
start = buf;
|
||||||
const uint8_t *start = buf;
|
|
||||||
const uint8_t *end = start + len;
|
|
||||||
uint8_t nal_data[len];
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int consumed = 0;
|
int consumed = 0;
|
||||||
@ -81,7 +95,6 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len)
|
|||||||
switch (buf[4] >> 5) {
|
switch (buf[4] >> 5) {
|
||||||
case 0: case 3: case 5: // I_FRAME
|
case 0: case 3: case 5: // I_FRAME
|
||||||
//Dprintf("H.264: Found NAL AUD at offset %d/%d", buf - start, len);
|
//Dprintf("H.264: Found NAL AUD at offset %d/%d", buf - start, len);
|
||||||
m_VideoHandler->SetVideoCodec(VIDEO_CODEC_H264);
|
|
||||||
aud_found = true;
|
aud_found = true;
|
||||||
break;
|
break;
|
||||||
case 1: case 4: case 6: // P_FRAME;
|
case 1: case 4: case 6: // P_FRAME;
|
||||||
@ -101,7 +114,7 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len)
|
|||||||
sps_found = true;
|
sps_found = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#if 0
|
||||||
case NAL_SEI:
|
case NAL_SEI:
|
||||||
if (!sei_found) {
|
if (!sei_found) {
|
||||||
//Dprintf("H.264: Found NAL SEI at offset %d/%d", buf - start, len);
|
//Dprintf("H.264: Found NAL SEI at offset %d/%d", buf - start, len);
|
||||||
@ -111,7 +124,7 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len)
|
|||||||
sei_found = true;
|
sei_found = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -122,6 +135,22 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len)
|
|||||||
buf += consumed + 4;
|
buf += consumed + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aud_found) {
|
||||||
|
m_VideoHandler->SetVideoCodec(VIDEO_CODEC_H264);
|
||||||
|
if (sps_found) {
|
||||||
|
//Dprintf("H.264 SPS: -> video size %dx%d, aspect %d format %d", m_Width, m_Height, m_AspectRatio, m_Format);
|
||||||
|
m_VideoHandler->SetVideoFormat(m_Format);
|
||||||
|
m_VideoHandler->SetVideoSize(m_Width, m_Height);
|
||||||
|
m_VideoHandler->SetVideoAspectRatio(m_AspectRatio);
|
||||||
|
}
|
||||||
|
if (sei_found) {
|
||||||
|
//Dprintf("H.264 SEI: -> stream bitrate %.1f, frame rate %.1f scan %d", m_BitRate, m_FrameRate, m_Scan);
|
||||||
|
m_VideoHandler->SetVideoFramerate(m_FrameRate);
|
||||||
|
m_VideoHandler->SetVideoBitrate(m_BitRate);
|
||||||
|
m_VideoHandler->SetVideoScan(m_Scan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return aud_found;
|
return aud_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,11 +188,16 @@ int cFemonH264::nalUnescape(uint8_t *dst, const uint8_t *src, int len)
|
|||||||
int cFemonH264::parseSPS(const uint8_t *buf, int len)
|
int cFemonH264::parseSPS(const uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
int profile_idc, pic_order_cnt_type, frame_mbs_only, i, j;
|
int profile_idc, pic_order_cnt_type, frame_mbs_only, i, j;
|
||||||
unsigned int width = 0, height = 0;
|
|
||||||
eVideoAspectRatio aspect_ratio = VIDEO_ASPECT_RATIO_INVALID;
|
|
||||||
eVideoFormat format = VIDEO_FORMAT_INVALID;
|
|
||||||
cBitStream bs(buf, len);
|
cBitStream bs(buf, len);
|
||||||
|
|
||||||
|
unsigned int width = m_Width;
|
||||||
|
unsigned int height = m_Height;
|
||||||
|
eVideoAspectRatio aspect_ratio = m_AspectRatio;
|
||||||
|
eVideoFormat format = m_Format;
|
||||||
|
bool cpb_dpb_delays_present_flag = m_CpbDpbDelaysPresentFlag;
|
||||||
|
bool pic_struct_present_flag = m_PicStructPresentFlag;
|
||||||
|
unsigned int time_offset_length = m_TimeOffsetLength;
|
||||||
|
|
||||||
profile_idc = bs.getU8();
|
profile_idc = bs.getU8();
|
||||||
|
|
||||||
//Dprintf("H.264 SPS: profile_idc %d", profile_idc);
|
//Dprintf("H.264 SPS: profile_idc %d", profile_idc);
|
||||||
@ -255,21 +289,83 @@ int cFemonH264::parseSPS(const uint8_t *buf, int len)
|
|||||||
if (bs.getBit()) // overscan_info_present_flag
|
if (bs.getBit()) // overscan_info_present_flag
|
||||||
bs.skipBit(); // overscan_approriate_flag
|
bs.skipBit(); // overscan_approriate_flag
|
||||||
if (bs.getBit()) { // video_signal_type_present_flag
|
if (bs.getBit()) { // video_signal_type_present_flag
|
||||||
uint32_t video_format = bs.getBits(3);
|
uint32_t video_format;
|
||||||
|
video_format = bs.getBits(3); // video_format
|
||||||
if (video_format < sizeof(s_VideoFormats) / sizeof(s_VideoFormats[0])) {
|
if (video_format < sizeof(s_VideoFormats) / sizeof(s_VideoFormats[0])) {
|
||||||
format = s_VideoFormats[video_format];
|
format = s_VideoFormats[video_format];
|
||||||
//Dprintf("H.264 SPS: -> video format %d", format);
|
//Dprintf("H.264 SPS: -> video format %d", format);
|
||||||
}
|
}
|
||||||
|
bs.skipBit(); // video_full_range_flag
|
||||||
|
bs.skipBit(); // video_full_range_flag
|
||||||
|
if (bs.getBit()) { // colour_description_present_flag
|
||||||
|
bs.skipBits(8); // colour_primaries
|
||||||
|
bs.skipBits(8); // transfer_characteristics
|
||||||
|
bs.skipBits(8); // matrix_coefficients
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bs.getBit()) { // chroma_loc_info_present_flag
|
||||||
|
bs.skipUeGolomb(); // chroma_sample_loc_type_top_field
|
||||||
|
bs.skipUeGolomb(); // chroma_sample_loc_type_bottom_field
|
||||||
|
}
|
||||||
|
if (bs.getBit()) { // timing_info_present_flag
|
||||||
|
bs.skipBits(32); // num_units_in_tick
|
||||||
|
bs.skipBits(32); // time_scale
|
||||||
|
bs.skipBit(); // fixed_frame_rate_flag
|
||||||
|
}
|
||||||
|
int nal_hrd_parameters_present_flag = bs.getBit(); // nal_hrd_parameters_present_flag
|
||||||
|
if (nal_hrd_parameters_present_flag) {
|
||||||
|
int cpb_cnt_minus1;
|
||||||
|
cpb_cnt_minus1 = bs.getUeGolomb(); // cpb_cnt_minus1
|
||||||
|
bs.skipBits(4); // bit_rate_scale
|
||||||
|
bs.skipBits(4); // cpb_size_scale
|
||||||
|
for (int i = 0; i < cpb_cnt_minus1; ++i) {
|
||||||
|
bs.skipUeGolomb(); // bit_rate_value_minus1[i]
|
||||||
|
bs.skipUeGolomb(); // cpb_size_value_minus1[i]
|
||||||
|
bs.skipBit(); // cbr_flag[i]
|
||||||
|
}
|
||||||
|
bs.skipBits(5); // initial_cpb_removal_delay_length_minus1
|
||||||
|
bs.skipBits(5); // cpb_removal_delay_length_minus1
|
||||||
|
bs.skipBits(5); // dpb_output_delay_length_minus1
|
||||||
|
time_offset_length = bs.getBits(5); // time_offset_length
|
||||||
|
}
|
||||||
|
int vlc_hrd_parameters_present_flag = bs.getBit(); // vlc_hrd_parameters_present_flag
|
||||||
|
if (vlc_hrd_parameters_present_flag) {
|
||||||
|
int cpb_cnt_minus1;
|
||||||
|
cpb_cnt_minus1 = bs.getUeGolomb(); // cpb_cnt_minus1
|
||||||
|
bs.skipBits(4); // bit_rate_scale
|
||||||
|
bs.skipBits(4); // cpb_size_scale
|
||||||
|
for (int i = 0; i < cpb_cnt_minus1; ++i) {
|
||||||
|
bs.skipUeGolomb(); // bit_rate_value_minus1[i]
|
||||||
|
bs.skipUeGolomb(); // cpb_size_value_minus1[i]
|
||||||
|
bs.skipBit(); // cbr_flag[i]
|
||||||
|
}
|
||||||
|
bs.skipBits(5); // initial_cpb_removal_delay_length_minus1
|
||||||
|
bs.skipBits(5); // cpb_removal_delay_length_minus1
|
||||||
|
bs.skipBits(5); // dpb_output_delay_length_minus1
|
||||||
|
time_offset_length = bs.getBits(5); // time_offset_length
|
||||||
|
}
|
||||||
|
cpb_dpb_delays_present_flag = (nal_hrd_parameters_present_flag | vlc_hrd_parameters_present_flag);
|
||||||
|
if (cpb_dpb_delays_present_flag)
|
||||||
|
bs.skipBit(); // low_delay_hrd_flag
|
||||||
|
pic_struct_present_flag = bs.getBit(); // pic_struct_present_flag
|
||||||
|
if (bs.getBit()) { // bitstream_restriction_flag
|
||||||
|
bs.skipBit(); // motion_vectors_over_pic_boundaries_flag
|
||||||
|
bs.skipUeGolomb(); // max_bytes_per_pic_denom
|
||||||
|
bs.skipUeGolomb(); // max_bits_per_mb_denom
|
||||||
|
bs.skipUeGolomb(); // log2_max_mv_length_horizontal
|
||||||
|
bs.skipUeGolomb(); // log2_max_mv_length_vertical
|
||||||
|
bs.skipUeGolomb(); // num_reorder_frames
|
||||||
|
bs.skipUeGolomb(); // max_dec_frame_buffering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Dprintf("H.264 SPS: -> video size %dx%d, aspect %d", width, height, aspect_ratio);
|
m_Width = width;
|
||||||
|
m_Height = height;
|
||||||
if (m_VideoHandler) {
|
m_AspectRatio = aspect_ratio;
|
||||||
m_VideoHandler->SetVideoFormat(format);
|
m_Format = format;
|
||||||
m_VideoHandler->SetVideoSize(width, height);
|
m_CpbDpbDelaysPresentFlag = cpb_dpb_delays_present_flag;
|
||||||
m_VideoHandler->SetVideoAspectRatio(aspect_ratio);
|
m_PicStructPresentFlag = pic_struct_present_flag;
|
||||||
}
|
m_TimeOffsetLength = time_offset_length;
|
||||||
|
|
||||||
return (bs.getIndex() / 8);
|
return (bs.getIndex() / 8);
|
||||||
}
|
}
|
||||||
@ -277,10 +373,12 @@ int cFemonH264::parseSPS(const uint8_t *buf, int len)
|
|||||||
int cFemonH264::parseSEI(const uint8_t *buf, int len)
|
int cFemonH264::parseSEI(const uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
int num_referenced_subseqs, i;
|
int num_referenced_subseqs, i;
|
||||||
double frame_rate = 0, bit_rate = 0;
|
|
||||||
eVideoScan scan = VIDEO_SCAN_INVALID;
|
|
||||||
cBitStream bs(buf, len);
|
cBitStream bs(buf, len);
|
||||||
|
|
||||||
|
double frame_rate = m_FrameRate;
|
||||||
|
double bit_rate = m_BitRate;
|
||||||
|
eVideoScan scan = m_Scan;
|
||||||
|
|
||||||
while ((bs.getIndex() * 8 + 16) < len) { // sei_message
|
while ((bs.getIndex() * 8 + 16) < len) { // sei_message
|
||||||
int lastByte, payloadSize = 0, payloadType = 0;
|
int lastByte, payloadSize = 0, payloadType = 0;
|
||||||
|
|
||||||
@ -297,23 +395,60 @@ int cFemonH264::parseSEI(const uint8_t *buf, int len)
|
|||||||
} while (lastByte == 0xFF);
|
} while (lastByte == 0xFF);
|
||||||
|
|
||||||
switch (payloadType) { // sei_payload
|
switch (payloadType) { // sei_payload
|
||||||
//case 1: // pic_timing
|
case 1: // pic_timing
|
||||||
// ...
|
if (m_CpbDpbDelaysPresentFlag) { // cpb_dpb_delays_present_flag
|
||||||
// switch (bs.getBits(2)) { // ct_type
|
bs.skipUeGolomb(); // cpb_removal_delay
|
||||||
// case 0:
|
bs.skipUeGolomb(); // dpb_output_delay
|
||||||
// scan = VIDEO_SCAN_PROGRESSIVE;
|
}
|
||||||
// break;
|
if (m_PicStructPresentFlag) { // pic_struct_present_flag
|
||||||
// case 1:
|
unsigned int pic_struct = bs.getBits(4); // pic_struct
|
||||||
// scan = VIDEO_SCAN_INTERLACED;
|
if (pic_struct >= (sizeof(s_SeiNumClockTsTable) ) / sizeof(s_SeiNumClockTsTable[0]))
|
||||||
// break;
|
return 0;
|
||||||
// case 2:
|
for (int i = 0; i < s_SeiNumClockTsTable[pic_struct]; ++i) {
|
||||||
// scan = VIDEO_SCAN_UNKNOWN;
|
if (bs.getBit()) { // clock_timestamp_flag[i]
|
||||||
// break;
|
int full_timestamp_flag;
|
||||||
// default:
|
switch (bs.getBits(2)) { // ct_type
|
||||||
// scan = VIDEO_SCAN_RESERVED;
|
case 0:
|
||||||
// break;
|
scan = VIDEO_SCAN_PROGRESSIVE;
|
||||||
// }
|
break;
|
||||||
// break;
|
case 1:
|
||||||
|
scan = VIDEO_SCAN_INTERLACED;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
scan = VIDEO_SCAN_UNKNOWN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
scan = VIDEO_SCAN_RESERVED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Dprintf("\nH.264 SEI: -> scan type %d", bit_rate, scan);
|
||||||
|
bs.skipBit(); // nuit_field_based_flag
|
||||||
|
bs.skipBits(5); // counting_type
|
||||||
|
full_timestamp_flag = bs.getBit(); // full_timestamp_flag
|
||||||
|
bs.skipBit(); // discontinuity_flag
|
||||||
|
bs.skipBit(); // cnt_dropped_flag
|
||||||
|
bs.skipBits(8); // n_frames
|
||||||
|
if (full_timestamp_flag) {
|
||||||
|
bs.skipBits(6); // seconds_value
|
||||||
|
bs.skipBits(6); // minutes_value
|
||||||
|
bs.skipBits(5); // hours_value
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (bs.getBit()) { // seconds_flag
|
||||||
|
bs.skipBits(6); // seconds_value
|
||||||
|
if (bs.getBit()) { // minutes_flag
|
||||||
|
bs.skipBits(6); // minutes_value
|
||||||
|
if (bs.getBit()) // hours_flag
|
||||||
|
bs.skipBits(5); // hours_value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_TimeOffsetLength > 0)
|
||||||
|
bs.skipBits(m_TimeOffsetLength); // time_offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 12: // sub_seq_characteristics
|
case 12: // sub_seq_characteristics
|
||||||
bs.skipUeGolomb(); // sub_seq_layer_num
|
bs.skipUeGolomb(); // sub_seq_layer_num
|
||||||
@ -322,9 +457,9 @@ int cFemonH264::parseSEI(const uint8_t *buf, int len)
|
|||||||
bs.skipBits(32); // sub_seq_duration
|
bs.skipBits(32); // sub_seq_duration
|
||||||
if (bs.getBit()) { // average_rate_flag
|
if (bs.getBit()) { // average_rate_flag
|
||||||
bs.skipBit(); // accurate_statistics_flag
|
bs.skipBit(); // accurate_statistics_flag
|
||||||
bit_rate = bs.getU16(); // average_bit_rate
|
bit_rate = bs.getU16() / 1048.51; // average_bit_rate (1000 bit/s -> Mbit/s)
|
||||||
frame_rate = bs.getU16(); // average_frame_rate
|
frame_rate = bs.getU16() / 256.0; // average_frame_rate (frames/256s)
|
||||||
//Dprintf("H.264 SEI: -> stream bitrate %.1f, frame rate %.1f", sei->bitrate, sei->frame_rate);
|
//Dprintf("\nH.264 SEI: -> stream bitrate %.1f, frame rate %.1f", bit_rate, frame_rate);
|
||||||
}
|
}
|
||||||
num_referenced_subseqs = bs.getUeGolomb(); // num_referenced_subseqs
|
num_referenced_subseqs = bs.getUeGolomb(); // num_referenced_subseqs
|
||||||
for (i = 0; i < num_referenced_subseqs; ++i) {
|
for (i = 0; i < num_referenced_subseqs; ++i) {
|
||||||
@ -343,11 +478,9 @@ int cFemonH264::parseSEI(const uint8_t *buf, int len)
|
|||||||
bs.byteAlign();
|
bs.byteAlign();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_VideoHandler) {
|
m_FrameRate = frame_rate;
|
||||||
m_VideoHandler->SetVideoFramerate(frame_rate);
|
m_BitRate = bit_rate;
|
||||||
m_VideoHandler->SetVideoBitrate(bit_rate);
|
m_Scan = scan;
|
||||||
m_VideoHandler->SetVideoScan(scan);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (bs.getIndex() / 8);
|
return (bs.getIndex() / 8);
|
||||||
}
|
}
|
||||||
|
11
femonh264.h
11
femonh264.h
@ -20,6 +20,16 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
cFemonVideoIf *m_VideoHandler;
|
cFemonVideoIf *m_VideoHandler;
|
||||||
|
unsigned int m_Width;
|
||||||
|
unsigned int m_Height;
|
||||||
|
eVideoAspectRatio m_AspectRatio;
|
||||||
|
eVideoFormat m_Format;
|
||||||
|
double m_FrameRate;
|
||||||
|
double m_BitRate;
|
||||||
|
eVideoScan m_Scan;
|
||||||
|
bool m_CpbDpbDelaysPresentFlag;
|
||||||
|
bool m_PicStructPresentFlag;
|
||||||
|
unsigned int m_TimeOffsetLength;
|
||||||
|
|
||||||
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);
|
||||||
@ -28,6 +38,7 @@ private:
|
|||||||
|
|
||||||
static const eVideoAspectRatio s_AspectRatios[];
|
static const eVideoAspectRatio s_AspectRatios[];
|
||||||
static const eVideoFormat s_VideoFormats[];
|
static const eVideoFormat s_VideoFormats[];
|
||||||
|
static const uint8_t s_SeiNumClockTsTable[9];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cFemonH264(cFemonVideoIf *videohandler);
|
cFemonH264(cFemonVideoIf *videohandler);
|
||||||
|
14
femonosd.c
14
femonosd.c
@ -493,7 +493,7 @@ void cFemonOsd::Action(void)
|
|||||||
DrawStatusWindow();
|
DrawStatusWindow();
|
||||||
}
|
}
|
||||||
else if (m_SvdrpConnection.handle >= 0) {
|
else if (m_SvdrpConnection.handle >= 0) {
|
||||||
cmd.handle = m_SvdrpConnection.handle;
|
cmd.handle = m_SvdrpConnection.handle;
|
||||||
m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd);
|
m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd);
|
||||||
if (cmd.responseCode == 900) {
|
if (cmd.responseCode == 900) {
|
||||||
for (cLine *line = cmd.reply.First(); line; line = cmd.reply.Next(line)) {
|
for (cLine *line = cmd.reply.First(); line; line = cmd.reply.Next(line)) {
|
||||||
@ -576,7 +576,7 @@ void cFemonOsd::Show(void)
|
|||||||
if (channel) {
|
if (channel) {
|
||||||
IS_AUDIO_TRACK(track) ? apid[0] = channel->Apid(int(track - ttAudioFirst)) : apid[0] = channel->Apid(0);
|
IS_AUDIO_TRACK(track) ? apid[0] = channel->Apid(int(track - ttAudioFirst)) : apid[0] = channel->Apid(0);
|
||||||
IS_DOLBY_TRACK(track) ? dpid[0] = channel->Dpid(int(track - ttDolbyFirst)) : dpid[0] = channel->Dpid(0);
|
IS_DOLBY_TRACK(track) ? dpid[0] = channel->Dpid(int(track - ttDolbyFirst)) : dpid[0] = channel->Dpid(0);
|
||||||
m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vpid(), apid, dpid);
|
m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vtype(), channel->Vpid(), apid, dpid);
|
||||||
cDevice::ActualDevice()->AttachReceiver(m_Receiver);
|
cDevice::ActualDevice()->AttachReceiver(m_Receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -621,7 +621,7 @@ void cFemonOsd::ChannelSwitch(const cDevice * device, int channelNumber)
|
|||||||
if (channel) {
|
if (channel) {
|
||||||
IS_AUDIO_TRACK(track) ? apid[0] = channel->Apid(int(track - ttAudioFirst)) : apid[0] = channel->Apid(0);
|
IS_AUDIO_TRACK(track) ? apid[0] = channel->Apid(int(track - ttAudioFirst)) : apid[0] = channel->Apid(0);
|
||||||
IS_DOLBY_TRACK(track) ? dpid[0] = channel->Dpid(int(track - ttDolbyFirst)) : dpid[0] = channel->Dpid(0);
|
IS_DOLBY_TRACK(track) ? dpid[0] = channel->Dpid(int(track - ttDolbyFirst)) : dpid[0] = channel->Dpid(0);
|
||||||
m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vpid(), apid, dpid);
|
m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vtype(), channel->Vpid(), apid, dpid);
|
||||||
cDevice::ActualDevice()->AttachReceiver(m_Receiver);
|
cDevice::ActualDevice()->AttachReceiver(m_Receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -642,7 +642,7 @@ void cFemonOsd::SetAudioTrack(int Index, const char * const *Tracks)
|
|||||||
if (channel) {
|
if (channel) {
|
||||||
IS_AUDIO_TRACK(track) ? apid[0] = channel->Apid(int(track - ttAudioFirst)) : apid[0] = channel->Apid(0);
|
IS_AUDIO_TRACK(track) ? apid[0] = channel->Apid(int(track - ttAudioFirst)) : apid[0] = channel->Apid(0);
|
||||||
IS_DOLBY_TRACK(track) ? dpid[0] = channel->Dpid(int(track - ttDolbyFirst)) : dpid[0] = channel->Dpid(0);
|
IS_DOLBY_TRACK(track) ? dpid[0] = channel->Dpid(int(track - ttDolbyFirst)) : dpid[0] = channel->Dpid(0);
|
||||||
m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vpid(), apid, dpid);
|
m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vtype(), channel->Vpid(), apid, dpid);
|
||||||
cDevice::ActualDevice()->AttachReceiver(m_Receiver);
|
cDevice::ActualDevice()->AttachReceiver(m_Receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -693,7 +693,7 @@ bool cFemonOsd::SvdrpConnect(void)
|
|||||||
m_SvdrpPlugin->Service("SvdrpConnection-v1.0", &m_SvdrpConnection);
|
m_SvdrpPlugin->Service("SvdrpConnection-v1.0", &m_SvdrpConnection);
|
||||||
if (m_SvdrpConnection.handle >= 0) {
|
if (m_SvdrpConnection.handle >= 0) {
|
||||||
SvdrpCommand_v1_0 cmd;
|
SvdrpCommand_v1_0 cmd;
|
||||||
cmd.handle = m_SvdrpConnection.handle;
|
cmd.handle = m_SvdrpConnection.handle;
|
||||||
cmd.command = cString::sprintf("PLUG %s\r\n", PLUGIN_NAME_I18N);
|
cmd.command = cString::sprintf("PLUG %s\r\n", PLUGIN_NAME_I18N);
|
||||||
m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd);
|
m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd);
|
||||||
if (cmd.responseCode != 214) {
|
if (cmd.responseCode != 214) {
|
||||||
@ -716,7 +716,7 @@ bool cFemonOsd::SvdrpTune(void)
|
|||||||
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
||||||
if (channel) {
|
if (channel) {
|
||||||
SvdrpCommand_v1_0 cmd;
|
SvdrpCommand_v1_0 cmd;
|
||||||
cmd.handle = m_SvdrpConnection.handle;
|
cmd.handle = m_SvdrpConnection.handle;
|
||||||
cmd.command = cString::sprintf("CHAN %s\r\n", *channel->GetChannelID().ToString());
|
cmd.command = cString::sprintf("CHAN %s\r\n", *channel->GetChannelID().ToString());
|
||||||
m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd);
|
m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd);
|
||||||
if (cmd.responseCode == 250)
|
if (cmd.responseCode == 250)
|
||||||
@ -765,7 +765,7 @@ double cFemonOsd::GetDolbyBitrate(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
eOSState cFemonOsd::ProcessKey(eKeys Key)
|
eOSState cFemonOsd::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
eOSState state = cOsdObject::ProcessKey(Key);
|
eOSState state = cOsdObject::ProcessKey(Key);
|
||||||
if (state == osUnknown) {
|
if (state == osUnknown) {
|
||||||
switch (Key) {
|
switch (Key) {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "femoncfg.h"
|
#include "femoncfg.h"
|
||||||
#include "femonreceiver.h"
|
#include "femonreceiver.h"
|
||||||
|
|
||||||
cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[], int Dpid[])
|
cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vtype, int Vpid, int Apid[], int Dpid[])
|
||||||
: cReceiver(ChannelID, -1, Vpid, Apid, Dpid, NULL),
|
: cReceiver(ChannelID, -1, Vpid, Apid, Dpid, NULL),
|
||||||
cThread("femon receiver"),
|
cThread("femon receiver"),
|
||||||
m_Sleep(),
|
m_Sleep(),
|
||||||
@ -19,6 +19,7 @@ cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[
|
|||||||
m_DetectMPEG(this, this),
|
m_DetectMPEG(this, this),
|
||||||
m_DetectAAC(this),
|
m_DetectAAC(this),
|
||||||
m_DetectAC3(this),
|
m_DetectAC3(this),
|
||||||
|
m_VideoType(Vtype),
|
||||||
m_VideoPid(Vpid),
|
m_VideoPid(Vpid),
|
||||||
m_VideoPacketCount(0),
|
m_VideoPacketCount(0),
|
||||||
m_VideoBitrate(0.0),
|
m_VideoBitrate(0.0),
|
||||||
@ -28,7 +29,7 @@ cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[
|
|||||||
m_AudioBitrate(0.0),
|
m_AudioBitrate(0.0),
|
||||||
m_AudioValid(false),
|
m_AudioValid(false),
|
||||||
m_AC3Pid(Dpid[0]),
|
m_AC3Pid(Dpid[0]),
|
||||||
m_AC3PacketCount(0),
|
m_AC3PacketCount(0),
|
||||||
m_AC3Bitrate(0),
|
m_AC3Bitrate(0),
|
||||||
m_AC3Valid(false)
|
m_AC3Valid(false)
|
||||||
{
|
{
|
||||||
@ -93,10 +94,18 @@ void cFemonReceiver::Receive(uchar *Data, int Length)
|
|||||||
m_VideoPacketCount++;
|
m_VideoPacketCount++;
|
||||||
if (TsPayloadStart(Data)) {
|
if (TsPayloadStart(Data)) {
|
||||||
while (const uint8_t *p = m_VideoAssembler.GetPes(len)) {
|
while (const uint8_t *p = m_VideoAssembler.GetPes(len)) {
|
||||||
if (m_DetectMPEG.processVideo(p, len) || m_DetectH264.processVideo(p, len)) {
|
if (m_VideoType == 0x1B) { // MPEG4
|
||||||
m_VideoValid = true;
|
if (m_DetectH264.processVideo(p, len)) {
|
||||||
break;
|
m_VideoValid = true;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (m_DetectMPEG.processVideo(p, len)) {
|
||||||
|
m_VideoValid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_VideoAssembler.Reset();
|
m_VideoAssembler.Reset();
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ private:
|
|||||||
cFemonAC3 m_DetectAC3;
|
cFemonAC3 m_DetectAC3;
|
||||||
|
|
||||||
cTsToPes m_VideoAssembler;
|
cTsToPes m_VideoAssembler;
|
||||||
|
int m_VideoType;
|
||||||
int m_VideoPid;
|
int m_VideoPid;
|
||||||
int m_VideoPacketCount;
|
int m_VideoPacketCount;
|
||||||
double m_VideoBitrate;
|
double m_VideoBitrate;
|
||||||
@ -81,7 +82,7 @@ public:
|
|||||||
virtual void SetAC3LFE(bool onoff) { m_AC3Info.lfe = onoff; }
|
virtual void SetAC3LFE(bool onoff) { m_AC3Info.lfe = onoff; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[], int Dpid[]);
|
cFemonReceiver(tChannelID ChannelID, int Ca, int Vtype, int Vpid, int Apid[], int Dpid[]);
|
||||||
virtual ~cFemonReceiver();
|
virtual ~cFemonReceiver();
|
||||||
void Deactivate(void);
|
void Deactivate(void);
|
||||||
|
|
||||||
|
36
femontools.h
36
femontools.h
@ -79,23 +79,25 @@ public:
|
|||||||
cBitStream(const uint8_t *buf, const int len);
|
cBitStream(const uint8_t *buf, const int len);
|
||||||
~cBitStream();
|
~cBitStream();
|
||||||
|
|
||||||
int getBit();
|
int getBit();
|
||||||
uint32_t getBits(uint32_t n);
|
uint32_t getBits(uint32_t n);
|
||||||
void skipBits(uint32_t n);
|
void skipBits(uint32_t n);
|
||||||
uint32_t getUeGolomb();
|
uint32_t getUeGolomb();
|
||||||
int32_t getSeGolomb();
|
int32_t getSeGolomb();
|
||||||
void skipGolomb();
|
void skipGolomb();
|
||||||
void skipUeGolomb();
|
void skipUeGolomb();
|
||||||
void skipSeGolomb();
|
void skipSeGolomb();
|
||||||
void byteAlign();
|
void byteAlign();
|
||||||
void skipBit() { skipBits(1); }
|
|
||||||
uint32_t getU8() { return getBits(8); }
|
void skipBit() { skipBits(1); }
|
||||||
uint32_t getU16() { return ((getBits(8) << 8) | getBits(8)); }
|
uint32_t getU8() { return getBits(8); }
|
||||||
uint32_t getU24() { return ((getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); }
|
uint32_t getU16() { return ((getBits(8) << 8) | getBits(8)); }
|
||||||
uint32_t getU32() { return ((getBits(8) << 24) | (getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); }
|
uint32_t getU24() { return ((getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); }
|
||||||
bool isEOF() { return (index >= count); }
|
uint32_t getU32() { return ((getBits(8) << 24) | (getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); }
|
||||||
void reset() { index = 0; }
|
bool isEOF() { return (index >= count); }
|
||||||
int getIndex() { return (isEOF() ? count : index);}
|
void reset() { index = 0; }
|
||||||
|
int getIndex() { return (isEOF() ? count : index); }
|
||||||
|
const uint8_t *getData() { return (isEOF() ? NULL : data + (index / 8)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __FEMONTOOLS_H
|
#endif // __FEMONTOOLS_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user