1
0
mirror of https://github.com/rofafor/vdr-plugin-femon.git synced 2023-10-10 13:36:53 +02:00

Fixed H.264 bitstream parsing.

This commit is contained in:
Rolf Ahrenberg 2009-08-31 19:12:15 +03:00
parent daf823435b
commit 453ca7a2a5
2 changed files with 63 additions and 56 deletions

View File

@ -60,6 +60,7 @@ cFemonH264::cFemonH264(cFemonVideoIf *videohandler)
m_PicStructPresentFlag(false), m_PicStructPresentFlag(false),
m_TimeOffsetLength(0) m_TimeOffsetLength(0)
{ {
reset();
} }
cFemonH264::~cFemonH264() cFemonH264::~cFemonH264()
@ -82,6 +83,8 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len)
buf += PesPayloadOffset(buf); buf += PesPayloadOffset(buf);
start = buf; start = buf;
reset();
for (;;) { for (;;) {
int consumed = 0; int consumed = 0;
@ -154,6 +157,13 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len)
return aud_found; return aud_found;
} }
void cFemonH264::reset()
{
m_CpbDpbDelaysPresentFlag = false;
m_PicStructPresentFlag = false;
m_TimeOffsetLength = 0;
}
const uint8_t *cFemonH264::nextStartCode(const uint8_t *start, const uint8_t *end) const uint8_t *cFemonH264::nextStartCode(const uint8_t *start, const uint8_t *end)
{ {
for (end -= 3; start < end; ++start) { for (end -= 3; start < end; ++start) {
@ -187,7 +197,7 @@ 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_flag, i, j;
cBitStream bs(buf, len); cBitStream bs(buf, len);
unsigned int width = m_Width; unsigned int width = m_Width;
@ -198,23 +208,26 @@ int cFemonH264::parseSPS(const uint8_t *buf, int len)
bool pic_struct_present_flag = m_PicStructPresentFlag; bool pic_struct_present_flag = m_PicStructPresentFlag;
unsigned int time_offset_length = m_TimeOffsetLength; unsigned int time_offset_length = m_TimeOffsetLength;
profile_idc = bs.getU8(); profile_idc = bs.getU8(); // profile_idc
//Dprintf("H.264 SPS: profile_idc %d", profile_idc); //Dprintf("H.264 SPS: profile_idc %d", profile_idc);
bs.skipBit(); // constraint_set0_flag
bs.skipBits(16); bs.skipBit(); // constraint_set1_flag
bs.skipBit(); // constraint_set2_flag
bs.skipBit(); // constraint_set3_flag
bs.skipBits(4); // reserved_zero_4bits
bs.skipBits(8); // level_idc
bs.skipUeGolomb(); // seq_parameter_set_id bs.skipUeGolomb(); // seq_parameter_set_id
if (profile_idc >= 100) { if ((profile_idc == 100) || (profile_idc == 110) || (profile_idc == 122) || (profile_idc == 144)) {
if (bs.getUeGolomb() == 3) // chroma_format_idc if (bs.getUeGolomb() == 3) // chroma_format_idc
bs.skipBit(); // residual_colour_transform_flag bs.skipBit(); // residual_colour_transform_flag
bs.skipUeGolomb(); // bit_depth_luma - 8 bs.skipUeGolomb(); // bit_depth_luma_minus8
bs.skipUeGolomb(); // bit_depth_chroma - 8 bs.skipUeGolomb(); // bit_depth_chroma_minus8
bs.skipBit(); // transform_bypass bs.skipBit(); // qpprime_y_zero_transform_bypass_flag
if (bs.getBit()) { // seq_scaling_matrix_present if (bs.getBit()) { // seq_scaling_matrix_present_flag
for (i = 0; i < 8; i++) { for (i = 0; i < 8; ++i) {
if (bs.getBit()) { // seq_scaling_list_present if (bs.getBit()) { // seq_scaling_list_present_flag[i]
int last = 8, next = 8, size = (i < 6) ? 16 : 64; int last = 8, next = 8, size = (i < 6) ? 16 : 64;
for (j = 0; j < size; j++) { for (j = 0; j < size; ++j) {
if (next) if (next)
next = (last + bs.getSeGolomb()) & 0xff; next = (last + bs.getSeGolomb()) & 0xff;
last = next ?: last; last = next ?: last;
@ -223,61 +236,53 @@ int cFemonH264::parseSPS(const uint8_t *buf, int len)
} }
} }
} }
bs.skipUeGolomb(); // log2_max_frame_num_minus4
bs.skipUeGolomb(); // log2_max_frame_num - 4 pic_order_cnt_type = bs.getUeGolomb(); // pic_order_cnt_type
pic_order_cnt_type = bs.getUeGolomb();
if (pic_order_cnt_type == 0) if (pic_order_cnt_type == 0)
bs.skipUeGolomb(); // log2_max_poc_lsb - 4 bs.skipUeGolomb(); // log2_max_pic_order_cnt_lsb_minus4
else if (pic_order_cnt_type == 1) { else if (pic_order_cnt_type == 1) {
bs.skipBit(); // delta_pic_order_always_zero bs.skipBit(); // delta_pic_order_always_zero
bs.skipSeGolomb(); // offset_for_non_ref_pic bs.skipSeGolomb(); // offset_for_non_ref_pic
bs.skipSeGolomb(); // offset_for_top_to_bottom_field bs.skipSeGolomb(); // offset_for_top_to_bottom_field
j = bs.getUeGolomb(); // num_ref_frames_in_pic_order_cnt_cycle j = bs.getUeGolomb(); // num_ref_frames_in_pic_order_cnt_cycle
for (i = 0; i < j; i++) for (i = 0; i < j; ++i)
bs.skipSeGolomb(); // offset_for_ref_frame[i] bs.skipSeGolomb(); // offset_for_ref_frame[i]
} }
bs.skipUeGolomb(); // ref_frames bs.skipUeGolomb(); // num_ref_frames
bs.skipBit(); // gaps_in_frame_num_allowed bs.skipBit(); // gaps_in_frame_num_value_allowed_flag
width = bs.getUeGolomb() + 1; // mbs width = bs.getUeGolomb() + 1; // pic_width_in_mbs_minus1
height = bs.getUeGolomb() + 1; // mbs height = bs.getUeGolomb() + 1; // pic_height_in_mbs_minus1
frame_mbs_only = bs.getBit(); frame_mbs_only_flag = bs.getBit(); // frame_mbs_only_flag
//Dprintf("H.264 SPS: pic_width: %u mbs", width); //Dprintf("H.264 SPS: pic_width: %u mbs", width);
//Dprintf("H.264 SPS: pic_height: %u mbs", height); //Dprintf("H.264 SPS: pic_height: %u mbs", height);
//Dprintf("H.264 SPS: frame only flag: %d", frame_mbs_only); //Dprintf("H.264 SPS: frame only flag: %d", frame_mbs_only_flag);
width *= 16; width *= 16;
height *= 16 * (2 - frame_mbs_only); height *= 16 * (2 - frame_mbs_only_flag);
if (!frame_mbs_only_flag)
if (!frame_mbs_only) { bs.skipBit(); // mb_adaptive_frame_field_flag
if (bs.getBit()) { // mb_adaptive_frame_field_flag
//Dprintf("H.264 SPS: MBAFF");
}
}
bs.skipBit(); // direct_8x8_inference_flag bs.skipBit(); // direct_8x8_inference_flag
if (bs.getBit()) { // frame_cropping_flag if (bs.getBit()) { // frame_cropping_flag
uint32_t crop_left = bs.getUeGolomb(); uint32_t crop_left, crop_right, crop_top, crop_bottom;
uint32_t crop_right = bs.getUeGolomb(); crop_left = bs.getUeGolomb(); // frame_crop_left_offset
uint32_t crop_top = bs.getUeGolomb(); crop_right = bs.getUeGolomb(); // frame_crop_rigth_offset
uint32_t crop_bottom = bs.getUeGolomb(); crop_top = bs.getUeGolomb(); // frame_crop_top_offset
//Dprintf("H.264 SPS: cropping %d %d %d %d", crop_left, crop_top, crop_right, crop_bottom); crop_bottom = bs.getUeGolomb(); // frame_crop_bottom_offset
//Dprintf("H.264 SPS: cropping %d %d %d %d", crop_left, crop_top, crop_right, crop_bottom);
width -= 2 * (crop_left + crop_right); width -= 2 * (crop_left + crop_right);
if (frame_mbs_only) if (frame_mbs_only_flag)
height -= 2 * (crop_top + crop_bottom); height -= 2 * (crop_top + crop_bottom);
else else
height -= 4 * (crop_top + crop_bottom); height -= 4 * (crop_top + crop_bottom);
} }
// VUI parameters // VUI parameters
if (bs.getBit()) { // vui_parameters_present_flag if (bs.getBit()) { // vui_parameters_present_flag
if (bs.getBit()) { // aspect_ratio_info_present if (bs.getBit()) { // aspect_ratio_info_present
uint32_t aspect_ratio_idc = bs.getU8(); uint32_t aspect_ratio_idc;
aspect_ratio_idc = bs.getU8(); // aspect_ratio_idc
//Dprintf("H.264 SPS: aspect_ratio_idc %d", aspect_ratio_idc); //Dprintf("H.264 SPS: aspect_ratio_idc %d", aspect_ratio_idc);
if (aspect_ratio_idc == 255) { // extended sar if (aspect_ratio_idc == 255) { // extended sar
bs.skipBit(); // sar_width bs.skipBits(16); // sar_width
bs.skipBit(); // sar_height bs.skipBits(16); // sar_height
aspect_ratio = VIDEO_ASPECT_RATIO_EXTENDED; aspect_ratio = VIDEO_ASPECT_RATIO_EXTENDED;
//Dprintf("H.264 SPS: aspect ratio extended"); //Dprintf("H.264 SPS: aspect ratio extended");
} }
@ -296,7 +301,6 @@ int cFemonH264::parseSPS(const uint8_t *buf, int len)
//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
bs.skipBit(); // video_full_range_flag
if (bs.getBit()) { // colour_description_present_flag if (bs.getBit()) { // colour_description_present_flag
bs.skipBits(8); // colour_primaries bs.skipBits(8); // colour_primaries
bs.skipBits(8); // transfer_characteristics bs.skipBits(8); // transfer_characteristics
@ -308,8 +312,10 @@ int cFemonH264::parseSPS(const uint8_t *buf, int len)
bs.skipUeGolomb(); // chroma_sample_loc_type_bottom_field bs.skipUeGolomb(); // chroma_sample_loc_type_bottom_field
} }
if (bs.getBit()) { // timing_info_present_flag if (bs.getBit()) { // timing_info_present_flag
bs.skipBits(32); // num_units_in_tick uint32_t num_units_in_tick, time_scale;
bs.skipBits(32); // time_scale num_units_in_tick = bs.getU32(); // num_units_in_tick
time_scale = bs.getU32(); // time_scale
//Dprintf("H.264 SPS: -> num_units_in_tick %d, time_scale %d", num_units_in_tick, time_scale);
bs.skipBit(); // fixed_frame_rate_flag bs.skipBit(); // fixed_frame_rate_flag
} }
int nal_hrd_parameters_present_flag = bs.getBit(); // nal_hrd_parameters_present_flag int nal_hrd_parameters_present_flag = bs.getBit(); // nal_hrd_parameters_present_flag
@ -401,8 +407,8 @@ int cFemonH264::parseSEI(const uint8_t *buf, int len)
bs.skipUeGolomb(); // dpb_output_delay bs.skipUeGolomb(); // dpb_output_delay
} }
if (m_PicStructPresentFlag) { // pic_struct_present_flag if (m_PicStructPresentFlag) { // pic_struct_present_flag
unsigned int pic_struct = bs.getBits(4); // pic_struct uint32_t pic_struct = bs.getBits(4); // pic_struct
if (pic_struct >= (sizeof(s_SeiNumClockTsTable) ) / sizeof(s_SeiNumClockTsTable[0])) if (pic_struct >= (sizeof(s_SeiNumClockTsTable)) / sizeof(s_SeiNumClockTsTable[0]))
return 0; return 0;
for (int i = 0; i < s_SeiNumClockTsTable[pic_struct]; ++i) { for (int i = 0; i < s_SeiNumClockTsTable[pic_struct]; ++i) {
if (bs.getBit()) { // clock_timestamp_flag[i] if (bs.getBit()) { // clock_timestamp_flag[i]
@ -421,7 +427,7 @@ int cFemonH264::parseSEI(const uint8_t *buf, int len)
scan = VIDEO_SCAN_RESERVED; scan = VIDEO_SCAN_RESERVED;
break; break;
} }
//Dprintf("\nH.264 SEI: -> scan type %d", bit_rate, scan); //Dprintf("\nH.264 SEI: -> scan type %d", scan);
bs.skipBit(); // nuit_field_based_flag bs.skipBit(); // nuit_field_based_flag
bs.skipBits(5); // counting_type bs.skipBits(5); // counting_type
full_timestamp_flag = bs.getBit(); // full_timestamp_flag full_timestamp_flag = bs.getBit(); // full_timestamp_flag

View File

@ -31,6 +31,7 @@ private:
bool m_PicStructPresentFlag; bool m_PicStructPresentFlag;
unsigned int m_TimeOffsetLength; unsigned int m_TimeOffsetLength;
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); int parseSPS(const uint8_t *buf, int len);