diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index 94e4e5b757..72eb9d15ec 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -1074,9 +1074,10 @@ srs_error_t SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_se c->width, c->height, c->video_data_rate / 1000, c->frame_rate, c->duration); #ifdef SRS_H265 } else if (c->id == SrsVideoCodecIdHEVC) { - // TODO: FIXME: Use the correct information for HEVC. - err = stat->on_video_info(req_, c->id, c->avc_profile, c->avc_level, c->width, c->height); - srs_trace("%dB video sh, codec(%d)", msg->size, c->id); + err = stat->on_video_info(req_, c->id, c->hevc_profile, c->hevc_level, c->width, c->height); + srs_trace("%dB video sh, codec(%d, profile=%s, level=%s, %dx%d, %dkbps, %.1ffps, %.1fs)", + msg->size, c->id, srs_hevc_profile2str(c->hevc_profile).c_str(), srs_hevc_level2str(c->hevc_level).c_str(), + c->width, c->height, c->video_data_rate / 1000, c->frame_rate, c->duration); #endif } if (err != srs_success) { diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 9469c92c3a..128d1c62b5 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -143,8 +143,20 @@ srs_error_t SrsStatisticStream::dumps(SrsJsonObject* obj) obj->set("video", video); video->set("codec", SrsJsonAny::str(srs_video_codec_id2str(vcodec).c_str())); - video->set("profile", SrsJsonAny::str(srs_avc_profile2str(avc_profile).c_str())); - video->set("level", SrsJsonAny::str(srs_avc_level2str(avc_level).c_str())); + + if (vcodec == SrsVideoCodecIdAVC) { + video->set("profile", SrsJsonAny::str(srs_avc_profile2str(avc_profile).c_str())); + video->set("level", SrsJsonAny::str(srs_avc_level2str(avc_level).c_str())); +#ifdef SRS_H265 + } else if (vcodec == SrsVideoCodecIdHEVC) { + video->set("profile", SrsJsonAny::str(srs_hevc_profile2str(hevc_profile).c_str())); + video->set("level", SrsJsonAny::str(srs_hevc_level2str(hevc_level).c_str())); +#endif + } else { + video->set("profile", SrsJsonAny::str("Other")); + video->set("level", SrsJsonAny::str("Other")); + } + video->set("width", SrsJsonAny::integer(width)); video->set("height", SrsJsonAny::integer(height)); } @@ -335,7 +347,7 @@ SrsStatisticClient* SrsStatistic::find_client(string client_id) return NULL; } -srs_error_t SrsStatistic::on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, SrsAvcProfile avc_profile, SrsAvcLevel avc_level, int width, int height) +srs_error_t SrsStatistic::on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, int profile, int level, int width, int height) { srs_error_t err = srs_success; @@ -344,9 +356,20 @@ srs_error_t SrsStatistic::on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, stream->has_video = true; stream->vcodec = vcodec; - stream->avc_profile = avc_profile; - stream->avc_level = avc_level; - + + if (vcodec == SrsVideoCodecIdAVC) { + stream->avc_profile = (SrsAvcProfile)profile; + stream->avc_level = (SrsAvcLevel)level; +#ifdef SRS_H265 + } else if (vcodec == SrsVideoCodecIdHEVC) { + stream->hevc_profile = (SrsHevcProfile)profile; + stream->hevc_level = (SrsHevcLevel)level; +#endif + } else { + stream->avc_profile = (SrsAvcProfile)profile; + stream->avc_level = (SrsAvcLevel)level; + } + stream->width = width; stream->height = height; diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 985bd97f10..d217fde927 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -70,6 +70,12 @@ struct SrsStatisticStream SrsAvcProfile avc_profile; // The level_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45. SrsAvcLevel avc_level; +#ifdef SRS_H265 + // The profile_idc, T-REC-H.265-202108-I!!PDF-E.pdf, page 559. + SrsHevcProfile hevc_profile; + // The level_idc, T-REC-H.265-202108-I!!PDF-E.pdf, page 684. + SrsHevcLevel hevc_level; +#endif // The width and height in codec info. int width; int height; @@ -157,8 +163,7 @@ class SrsStatistic virtual SrsStatisticClient* find_client(std::string client_id); public: // When got video info for stream. - virtual srs_error_t on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, SrsAvcProfile avc_profile, - SrsAvcLevel avc_level, int width, int height); + virtual srs_error_t on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, int avc_profile, int avc_level, int width, int height); // When got audio info for stream. virtual srs_error_t on_audio_info(SrsRequest* req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate, SrsAudioChannels asound_type, SrsAacObjectType aac_object); diff --git a/trunk/src/kernel/srs_kernel_buffer.cpp b/trunk/src/kernel/srs_kernel_buffer.cpp index b4ac382fb2..4a8f150973 100644 --- a/trunk/src/kernel/srs_kernel_buffer.cpp +++ b/trunk/src/kernel/srs_kernel_buffer.cpp @@ -379,6 +379,15 @@ bool SrsBitBuffer::empty() { return stream->empty(); } +bool SrsBitBuffer::require_bits(int n) +{ + if (n < 0) { + return false; + } + + return n <= left_bits(); +} + int8_t SrsBitBuffer::read_bit() { if (!cb_left) { srs_assert(!stream->empty()); @@ -391,3 +400,75 @@ int8_t SrsBitBuffer::read_bit() { return v; } +int SrsBitBuffer::left_bits() +{ + return cb_left + stream->left() * 8; +} + +void SrsBitBuffer::skip_bits(int n) +{ + srs_assert(n <= left_bits()); + + for (int i = 0; i < n; i++) { + read_bit(); + } +} + +int32_t SrsBitBuffer::read_bits(int n) +{ + srs_assert(n <= left_bits()); + + int32_t v = 0; + for (int i = 0; i < n; i++) { + v |= (read_bit() << (n - i - 1)); + } + return v; +} + +int8_t SrsBitBuffer::read_8bits() +{ + // FAST_8 + if (!cb_left) { + srs_assert(!stream->empty()); + return stream->read_1bytes(); + } + + return read_bits(8); +} + +int16_t SrsBitBuffer::read_16bits() +{ + // FAST_16 + if (!cb_left) { + srs_assert(!stream->empty()); + return stream->read_2bytes(); + } + + return read_bits(16); +} + +int32_t SrsBitBuffer::read_32bits() +{ + // FAST_32 + if (!cb_left) { + srs_assert(!stream->empty()); + return stream->read_4bytes(); + } + + return read_bits(32); +} + +int32_t SrsBitBuffer::read_bits_ue() +{ + int32_t r = 0; + int i = 0; + + while((read_bit() == 0) && (i < 32) && (left_bits() > 0) ) { + i++; + } + + r = read_bits(i); + r += (1 << i) - 1; + + return r; +} diff --git a/trunk/src/kernel/srs_kernel_buffer.hpp b/trunk/src/kernel/srs_kernel_buffer.hpp index ae254f9432..b7ca9d4cb3 100644 --- a/trunk/src/kernel/srs_kernel_buffer.hpp +++ b/trunk/src/kernel/srs_kernel_buffer.hpp @@ -174,6 +174,14 @@ class SrsBitBuffer public: bool empty(); int8_t read_bit(); + bool require_bits(int n); + int left_bits(); + void skip_bits(int n); + int32_t read_bits(int n); + int8_t read_8bits(); + int16_t read_16bits(); + int32_t read_32bits(); + int32_t read_bits_ue(); }; #endif diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index ef15211dcc..86d9b49d2b 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -416,6 +416,41 @@ string srs_avc_level2str(SrsAvcLevel level) } } +#ifdef SRS_H265 + +string srs_hevc_profile2str(SrsHevcProfile profile) +{ + switch (profile) { + case SrsHevcProfileMain: return "Main"; + case SrsHevcProfileMain10: return "Main10"; + case SrsHevcProfileMainStillPicture: return "Main Still Picture"; + case SrsHevcProfileRext: return "Rext"; + default: return "Other"; + } +} + +string srs_hevc_level2str(SrsHevcLevel level) +{ + switch (level) { + case SrsHevcLevel_1: return "1"; + case SrsHevcLevel_2: return "2"; + case SrsHevcLevel_21: return "2.1"; + case SrsHevcLevel_3: return "3"; + case SrsHevcLevel_31: return "3.1"; + case SrsHevcLevel_4: return "4"; + case SrsHevcLevel_41: return "4.1"; + case SrsHevcLevel_5: return "5"; + case SrsHevcLevel_51: return "5.1"; + case SrsHevcLevel_52: return "5.2"; + case SrsHevcLevel_6: return "6"; + case SrsHevcLevel_61: return "6.1"; + case SrsHevcLevel_62: return "6.2"; + default: return "Other"; + } +} + +#endif + SrsSample::SrsSample() { size = 0; @@ -882,6 +917,8 @@ srs_error_t SrsFormat::video_avc_demux(SrsBuffer* stream, int64_t timestamp) // Parse the hevc vps/sps/pps srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream) { + srs_error_t err = srs_success; + int avc_extra_size = stream->size() - stream->pos(); if (avc_extra_size > 0) { char *copy_stream_from = stream->data() + stream->pos(); @@ -890,13 +927,13 @@ srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream) const int HEVC_MIN_SIZE = 23; // From configuration_version to numOfArrays if (!stream->require(HEVC_MIN_SIZE)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "requires %d only %d bytes", HEVC_MIN_SIZE, stream->left()); + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "requires %d only %d bytes", HEVC_MIN_SIZE, stream->left()); } SrsHevcDecoderConfigurationRecord* dec_conf_rec_p = &(vcodec->hevc_dec_conf_record_); dec_conf_rec_p->configuration_version = stream->read_1bytes(); if (dec_conf_rec_p->configuration_version != 1) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "invalid version=%d", dec_conf_rec_p->configuration_version); + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "invalid version=%d", dec_conf_rec_p->configuration_version); } // Read general_profile_space(2bits), general_tier_flag(1bit), general_profile_idc(5bits) @@ -934,7 +971,7 @@ srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream) dec_conf_rec_p->bit_depth_luma_minus8, dec_conf_rec_p->bit_depth_chroma_minus8); //avg_frame_rate: 16bits - dec_conf_rec_p->avg_frame_rate = stream->read_2bytes(); + vcodec->frame_rate = dec_conf_rec_p->avg_frame_rate = stream->read_2bytes(); //8bits: constant_frame_rate(2bits), num_temporal_layers(3bits), // temporal_id_nested(1bit), length_size_minus_one(2bits) data_byte = stream->read_1bytes(); @@ -952,7 +989,7 @@ srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream) // The value of this field shall be one of 0, 1, or 3 corresponding to a // length encoded with 1, 2, or 4 bytes, respectively. if (vcodec->NAL_unit_length == 2) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps lengthSizeMinusOne should never be 2"); + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sps lengthSizeMinusOne should never be 2"); } uint8_t numOfArrays = stream->read_1bytes(); @@ -965,7 +1002,7 @@ srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream) SrsHevcHvccNalu hevc_unit; if (!stream->require(5)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "requires 5 only %d bytes", stream->left()); + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "requires 5 only %d bytes", stream->left()); } data_byte = stream->read_1bytes(); hevc_unit.array_completeness = (data_byte >> 7) & 0x01; @@ -977,7 +1014,7 @@ srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream) data_item.nal_unit_length = stream->read_2bytes(); if (!stream->require(data_item.nal_unit_length)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "requires %d only %d bytes", + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "requires %d only %d bytes", data_item.nal_unit_length, stream->left()); } //copy vps/pps/sps data @@ -989,10 +1026,376 @@ srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream) hevc_unit.nal_data_vec.push_back(data_item); } dec_conf_rec_p->nalu_vec.push_back(hevc_unit); + + // demux nalu + if ((err = hevc_demux_vps_sps_pps(&hevc_unit)) != srs_success) { + return srs_error_wrap(err, "hevc demux vps sps pps failed"); + } } - return srs_success; + return err; +} + +srs_error_t SrsFormat::hevc_demux_vps_sps_pps(SrsHevcHvccNalu* nal) +{ + srs_error_t err = srs_success; + + // nal data + switch (nal->nal_unit_type) + { + case SrsHevcNaluType_VPS: + // TODO: FIXME: implements it. + break; + case SrsHevcNaluType_SPS: + err = hevc_demux_sps(nal); + break; + case SrsHevcNaluType_PPS: + // TODO: FIXME: implements it. + break; + default: + break; + } + + return err; } + +srs_error_t SrsFormat::hevc_demux_sps(SrsHevcHvccNalu* nal) +{ + srs_error_t err = srs_success; + + if (nal->nal_data_vec.empty()) { + return err; + } + + // FIXME: Support for multiple SPS, then pick the first non-empty one. + char* sps = (char*)(&nal->nal_data_vec[0].nal_unit_data[0]); + int nb_sps = nal->nal_data_vec[0].nal_unit_length; + + SrsBuffer stream(sps, nb_sps); + + // for NALU, ITU-T H.265 7.3.2.2 Sequence parameter set RBSP syntax + // T-REC-H.265-202108-I!!PDF-E.pdf, page 33. + if (!stream.require(1)) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "decode hevc sps requires 1 only %d bytes", stream.left()); + } + int8_t nutv = stream.read_1bytes(); + + // forbidden_zero_bit shall be equal to 0. + int8_t forbidden_zero_bit = (nutv >> 7) & 0x01; + if (forbidden_zero_bit) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc forbidden_zero_bit=%d shall be equal to 0", forbidden_zero_bit); + } + + // 7.4.2 NAL unit semantics + // T-REC-H.265-202108-I!!PDF-E.pdf, page 64. + // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1. + SrsHevcNaluType nal_unit_type = (SrsHevcNaluType)((nutv >> 1) & 0x3f); + if (nal_unit_type != SrsHevcNaluType_SPS) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc sps nal_unit_type=%d shall be equal to 33", nal_unit_type); + } + + // nuh(nuh_layer_id + nuh_temporal_id_plus1) + int8_t nuh = stream.read_1bytes(); + (void)nuh; + + // decode the rbsp from sps. + // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes. + std::vector rbsp(nb_sps); + + int nb_rbsp = 0; + while (!stream.empty()) { + rbsp[nb_rbsp] = stream.read_1bytes(); + + // XX 00 00 03 XX, the 03 byte should be drop. + if (nb_rbsp > 2 && rbsp[nb_rbsp - 2] == 0 && rbsp[nb_rbsp - 1] == 0 && rbsp[nb_rbsp] == 3) { + // read 1byte more. + if (stream.empty()) { + break; + } + rbsp[nb_rbsp] = stream.read_1bytes(); + nb_rbsp++; + + continue; + } + + nb_rbsp++; + } + + return hevc_demux_sps_rbsp((char*)&rbsp[0], nb_rbsp); +} + +srs_error_t SrsFormat::hevc_demux_sps_rbsp(char* rbsp, int nb_rbsp) +{ + srs_error_t err = srs_success; + + // we donot parse the detail of sps. + // @see https://github.com/ossrs/srs/issues/474 + if (!avc_parse_sps) { + return err; + } + + // reparse the rbsp. + SrsBuffer stream(rbsp, nb_rbsp); + + /* Rec. ITU-T H.265 7.3.2.2.1, page 35. + * seq_parameter_set_rbsp + * sps_video_parameter_set_id 4 bits + * sps_max_sub_layers_minus1 3 bits + * sps_temporal_id_nesting_flag 1 bit + * + * sps_seq_parameter_set_id v + * chroma_format_idc v + * if (chroma_format_idc == 3) + * separate_colour_plane_flag 1 bit + * pic_width_in_luma_samples v + * pic_height_in_luma_samples v + * conformance_window_flag 1 bit + * if (conformance_window_flag) { + * conf_win_left_offset v + * conf_win_right_offset v + * conf_win_top_offset v + * conf_win_bottom_offset v + * } + */ + if (!stream.require(2)) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sps requires 2 only %d bytes", stream.left()); + } + uint8_t nutv = stream.read_1bytes(); + (void)nutv; + + // id/minus/flag + int sps_video_parameter_set_id = (nutv >> 4) & 0x0f; + int sps_max_sub_layers_minus1 = (nutv >> 1) & 0x07; + int sps_temporal_id_nesting_flag = nutv & 0x01; + (void)sps_video_parameter_set_id; + (void)sps_temporal_id_nesting_flag; + + SrsBitBuffer bs(&stream); + + // profile tier level... + SrsHevcSpsProfileTierLevel profile_tier_level; + memset(&profile_tier_level, 0, sizeof(SrsHevcSpsProfileTierLevel)); + + if ((err = hevc_demux_sps_rbsp_ptl(&bs, &profile_tier_level, 1, sps_max_sub_layers_minus1)) != srs_success) { + return srs_error_wrap(err, "sps rbsp ptl sps_max_sub_layers_minus1=%d", sps_max_sub_layers_minus1); + } + + vcodec->hevc_profile = (SrsHevcProfile)profile_tier_level.general_profile_idc; + vcodec->hevc_level = (SrsHevcLevel)profile_tier_level.general_level_idc; + + // for sps_table + int sps_seq_parameter_set_id = bs.read_bits_ue(); + (void)sps_seq_parameter_set_id; + + int separate_colour_plane_flag = 0; + int chroma_format_idc = bs.read_bits_ue(); + if (chroma_format_idc == 3) { + separate_colour_plane_flag = bs.read_bits_ue(); + } + + int pic_width_in_luma_samples = bs.read_bits_ue(); + int pic_height_in_luma_samples = bs.read_bits_ue(); + vcodec->width = pic_width_in_luma_samples; + vcodec->height = pic_height_in_luma_samples; + + int conformance_window_flag = bs.read_bit(); + if (conformance_window_flag) { + int conf_win_left_offset = bs.read_bits_ue(); + int conf_win_right_offset = bs.read_bits_ue(); + int conf_win_top_offset = bs.read_bits_ue(); + int conf_win_bottom_offset = bs.read_bits_ue(); + + // Table 6-1, 7.4.3.2.1 + // Recalculate width and height + // Note: 1 is added to the manual, but it is not actually used + // https://github.com/mbunkus/mkvtoolnix/issues/1152 + int sub_width_c = ((1 == chroma_format_idc) || (2 == chroma_format_idc)) && (0 == separate_colour_plane_flag) ? 2 : 1; + int sub_height_c = (1 == chroma_format_idc) && (0 == separate_colour_plane_flag) ? 2 : 1; + vcodec->width -= (sub_width_c * conf_win_right_offset + sub_width_c * conf_win_left_offset); + vcodec->height -= (sub_height_c * conf_win_bottom_offset + sub_height_c * conf_win_top_offset); + } + + // TODO: FIXME: Implements it, you might parse remain bits for seq_parameter_set_rbsp. + // 7.4.3.2.1 + // T-REC-H.265-202108-I!!PDF-E.pdf, page 35 ~ page 36. + // bit_depth_luma_minus8 + // bit_depth_chroma_minus8 + + // 7.3.2.11 RBSP trailing bits syntax + // T-REC-H.265-202108-I!!PDF-E.pdf, page 41. + // rbsp_trailing_bits() + + return err; +} + +srs_error_t SrsFormat::hevc_demux_sps_rbsp_ptl(SrsBitBuffer* bs, SrsHevcSpsProfileTierLevel* ptl, int profile_resent_flag, int max_sub_layers_minus1) +{ + srs_error_t err = srs_success; + + if (profile_resent_flag) { + if (!bs->require_bits(88)) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl profile requires 88 only %d bits", bs->left_bits()); + } + + ptl->general_profile_space = bs->read_bits(2); + ptl->general_tier_flag = bs->read_bit(); + ptl->general_profile_idc = bs->read_bits(5); + for (int i = 0; i < 32; i++) { + ptl->general_profile_compatibility_flag[i] = bs->read_bit(); + } + + ptl->general_progressive_source_flag = bs->read_bit(); + ptl->general_interlaced_source_flag = bs->read_bit(); + ptl->general_non_packed_constraint_flag = bs->read_bit(); + ptl->general_frame_only_constraint_flag = bs->read_bit(); + if (ptl->general_profile_idc == 4 || ptl->general_profile_compatibility_flag[4] || + ptl->general_profile_idc == 5 || ptl->general_profile_compatibility_flag[5] || + ptl->general_profile_idc == 6 || ptl->general_profile_compatibility_flag[6] || + ptl->general_profile_idc == 7 || ptl->general_profile_compatibility_flag[7]) + { + ptl->general_max_12bit_constraint_flag = bs->read_bit(); + ptl->general_max_10bit_constraint_flag = bs->read_bit(); + ptl->general_max_8bit_constraint_flag = bs->read_bit(); + ptl->general_max_422chroma_constraint_flag = bs->read_bit(); + ptl->general_max_420chroma_constraint_flag = bs->read_bit(); + ptl->general_max_monochrome_constraint_flag = bs->read_bit(); + ptl->general_intra_constraint_flag = bs->read_bit(); + ptl->general_one_picture_only_constraint_flag = bs->read_bit(); + ptl->general_lower_bit_rate_constraint_flag = bs->read_bit(); + uint64_t tmp1 = bs->read_32bits(); + uint64_t tmp2 = bs->read_bits(2); + ptl->general_reserved_zero_34bits = tmp1 + tmp2; + } else { + uint64_t tmp1 = bs->read_32bits(); + uint64_t tmp2 = bs->read_bits(11); + ptl->general_reserved_zero_43bits = tmp1 + tmp2; + } + + if ((ptl->general_profile_idc >= 1 && ptl->general_profile_idc<=5) || + ptl->general_profile_compatibility_flag[1] || ptl->general_profile_compatibility_flag[2] || + ptl->general_profile_compatibility_flag[3] || ptl->general_profile_compatibility_flag[4] || + ptl->general_profile_compatibility_flag[5]) + { + ptl->general_inbld_flag = bs->read_bit(); + } else { + ptl->general_reserved_zero_bit = bs->read_bit(); + } + } + + if (!bs->require_bits(8)) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl level requires 8 only %d bits", bs->left_bits()); + } + + // level + ptl->general_level_idc = bs->read_8bits(); + + ptl->sub_layer_profile_present_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_level_present_flag.resize(max_sub_layers_minus1); + for (int i = 0; i < max_sub_layers_minus1; i++) { + if (!bs->require_bits(2)) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl present_flag requires 2 only %d bits", bs->left_bits()); + } + ptl->sub_layer_profile_present_flag[i] = bs->read_bit(); + ptl->sub_layer_level_present_flag[i] = bs->read_bit(); + } + + for (int i = max_sub_layers_minus1; max_sub_layers_minus1 > 0 && i < 8; i++) { + if (!bs->require_bits(2)) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl reserved_zero requires 2 only %d bits", bs->left_bits()); + } + ptl->reserved_zero_2bits[i] = bs->read_bits(2); + } + + ptl->sub_layer_profile_space.resize(max_sub_layers_minus1); + ptl->sub_layer_tier_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_profile_idc.resize(max_sub_layers_minus1); + ptl->sub_layer_profile_compatibility_flag.resize(max_sub_layers_minus1); + for (int i = 0; i < max_sub_layers_minus1; i++) { + ptl->sub_layer_profile_compatibility_flag[i].resize(32); + } + + ptl->sub_layer_progressive_source_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_interlaced_source_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_non_packed_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_frame_only_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_max_12bit_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_max_10bit_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_max_8bit_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_max_422chroma_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_max_420chroma_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_max_monochrome_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_intra_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_one_picture_only_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_lower_bit_rate_constraint_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_reserved_zero_34bits.resize(max_sub_layers_minus1); + ptl->sub_layer_reserved_zero_43bits.resize(max_sub_layers_minus1); + ptl->sub_layer_inbld_flag.resize(max_sub_layers_minus1); + ptl->sub_layer_reserved_zero_bit.resize(max_sub_layers_minus1); + ptl->sub_layer_level_idc.resize(max_sub_layers_minus1); + for (int i = 0; i < max_sub_layers_minus1; i++) { + if (ptl->sub_layer_profile_present_flag[i]) { + if (!bs->require_bits(88)) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl sub_layer_profile requires 88 only %d bits", bs->left_bits()); + } + ptl->sub_layer_profile_space[i] = bs->read_bits(2); + ptl->sub_layer_tier_flag[i] = bs->read_bit(); + ptl->sub_layer_profile_idc[i] = bs->read_bits(5); + for (int j = 0; j < 32; j++) { + ptl->sub_layer_profile_compatibility_flag[i][j] = bs->read_bit(); + } + + ptl->sub_layer_progressive_source_flag[i] = bs->read_bit(); + ptl->sub_layer_interlaced_source_flag[i] = bs->read_bit(); + ptl->sub_layer_non_packed_constraint_flag[i] = bs->read_bit(); + ptl->sub_layer_frame_only_constraint_flag[i] = bs->read_bit(); + if (ptl->sub_layer_profile_idc[i] == 4 || ptl->sub_layer_profile_compatibility_flag[i][4] || + ptl->sub_layer_profile_idc[i] == 5 || ptl->sub_layer_profile_compatibility_flag[i][5] || + ptl->sub_layer_profile_idc[i] == 6 || ptl->sub_layer_profile_compatibility_flag[i][6] || + ptl->sub_layer_profile_idc[i] == 7 || ptl->sub_layer_profile_compatibility_flag[i][7]) + { + ptl->sub_layer_max_12bit_constraint_flag[i] = bs->read_bit(); + ptl->sub_layer_max_10bit_constraint_flag[i] = bs->read_bit(); + ptl->sub_layer_max_8bit_constraint_flag[i] = bs->read_bit(); + ptl->sub_layer_max_422chroma_constraint_flag[i] = bs->read_bit(); + ptl->sub_layer_max_420chroma_constraint_flag[i] = bs->read_bit(); + ptl->sub_layer_max_monochrome_constraint_flag[i] = bs->read_bit(); + ptl->sub_layer_intra_constraint_flag[i] = bs->read_bit(); + ptl->sub_layer_one_picture_only_constraint_flag[i] = bs->read_bit(); + ptl->sub_layer_lower_bit_rate_constraint_flag[i] = bs->read_bit(); + uint64_t tmp1 = bs->read_32bits(); + uint64_t tmp2 = bs->read_bits(2); + ptl->sub_layer_reserved_zero_34bits[i] = tmp1 + tmp2; + } else { + uint64_t tmp1 = bs->read_32bits(); + uint64_t tmp2 = bs->read_bits(11); + ptl->sub_layer_reserved_zero_43bits[i] = tmp1 + tmp2; + } + + // to check + if ((ptl->sub_layer_profile_idc[i]>=1 && ptl->sub_layer_profile_idc[i] <= 5) || + ptl->sub_layer_profile_compatibility_flag[i][1] || + ptl->sub_layer_profile_compatibility_flag[i][2] || + ptl->sub_layer_profile_compatibility_flag[i][3] || + ptl->sub_layer_profile_compatibility_flag[i][4] || + ptl->sub_layer_profile_compatibility_flag[i][5]) + { + ptl->sub_layer_inbld_flag[i] = bs->read_bit(); + } else { + ptl->sub_layer_reserved_zero_bit[i] = bs->read_bit(); + } + } + + if (ptl->sub_layer_level_present_flag[i]) { + if (!bs->require_bits(8)) { + return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl sub_layer_level requires 8 only %d bits", bs->left_bits()); + } + ptl->sub_layer_level_idc[i] = bs->read_8bits(); + } + } + + return err; +} + #endif srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer* stream) diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 682d4bca91..b5f2cb65b6 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -13,6 +13,7 @@ #include class SrsBuffer; +class SrsBitBuffer; /** * The video codec id. @@ -502,6 +503,63 @@ struct SrsHevcDecoderConfigurationRecord { uint8_t length_size_minus_one; std::vector nalu_vec; }; + + +/** + Profile, tier and level + @see 7.3.3 Profile, tier and level syntax +*/ +struct SrsHevcSpsProfileTierLevel +{ + uint8_t general_profile_space; + uint8_t general_tier_flag; + uint8_t general_profile_idc; + uint8_t general_profile_compatibility_flag[32]; + uint8_t general_progressive_source_flag; + uint8_t general_interlaced_source_flag; + uint8_t general_non_packed_constraint_flag; + uint8_t general_frame_only_constraint_flag; + uint8_t general_max_12bit_constraint_flag; + uint8_t general_max_10bit_constraint_flag; + uint8_t general_max_8bit_constraint_flag; + uint8_t general_max_422chroma_constraint_flag; + uint8_t general_max_420chroma_constraint_flag; + uint8_t general_max_monochrome_constraint_flag; + uint8_t general_intra_constraint_flag; + uint8_t general_one_picture_only_constraint_flag; + uint8_t general_lower_bit_rate_constraint_flag; + uint64_t general_reserved_zero_34bits; // todo + uint64_t general_reserved_zero_43bits; // todo + uint8_t general_inbld_flag; + uint8_t general_reserved_zero_bit; + uint8_t general_level_idc; + std::vector sub_layer_profile_present_flag; + std::vector sub_layer_level_present_flag; + uint8_t reserved_zero_2bits[8]; + std::vector sub_layer_profile_space; + std::vector sub_layer_tier_flag; + std::vector sub_layer_profile_idc; + std::vector > sub_layer_profile_compatibility_flag; + std::vector sub_layer_progressive_source_flag; + std::vector sub_layer_interlaced_source_flag; + std::vector sub_layer_non_packed_constraint_flag; + std::vector sub_layer_frame_only_constraint_flag; + std::vector sub_layer_max_12bit_constraint_flag; + std::vector sub_layer_max_10bit_constraint_flag; + std::vector sub_layer_max_8bit_constraint_flag; + std::vector sub_layer_max_422chroma_constraint_flag; + std::vector sub_layer_max_420chroma_constraint_flag; + std::vector sub_layer_max_monochrome_constraint_flag; + std::vector sub_layer_intra_constraint_flag; + std::vector sub_layer_one_picture_only_constraint_flag; + std::vector sub_layer_lower_bit_rate_constraint_flag; + std::vector sub_layer_reserved_zero_34bits; + std::vector sub_layer_reserved_zero_43bits; + std::vector sub_layer_inbld_flag; + std::vector sub_layer_reserved_zero_bit; + std::vector sub_layer_level_idc; +}; + #endif /** @@ -627,6 +685,50 @@ enum SrsAvcLevel }; std::string srs_avc_level2str(SrsAvcLevel level); +#ifdef SRS_H265 + +/** + * the profile for hevc/h.265. + * @see Annex A Profiles and levels, T-REC-H.265-202108-I!!PDF-E.pdf, page 559. + */ +enum SrsHevcProfile +{ + SrsHevcProfileReserved = 0, + + // @see ffmpeg, libavcodec/avcodec.h:2986 + SrsHevcProfileMain = 1, + SrsHevcProfileMain10 = 2, + SrsHevcProfileMainStillPicture = 3, + SrsHevcProfileRext = 4, +}; +std::string srs_hevc_profile2str(SrsHevcProfile profile); + +/** + * the level for hevc/h.265. + * @see Annex A Profiles and levels, T-REC-H.265-202108-I!!PDF-E.pdf, page 684. + */ +enum SrsHevcLevel +{ + SrsHevcLevelReserved = 0, + + SrsHevcLevel_1 = 30, + SrsHevcLevel_2 = 60, + SrsHevcLevel_21 = 63, + SrsHevcLevel_3 = 90, + SrsHevcLevel_31 = 93, + SrsHevcLevel_4 = 120, + SrsHevcLevel_41 = 123, + SrsHevcLevel_5 = 150, + SrsHevcLevel_51 = 153, + SrsHevcLevel_52 = 156, + SrsHevcLevel_6 = 180, + SrsHevcLevel_61 = 183, + SrsHevcLevel_62 = 186, +}; +std::string srs_hevc_level2str(SrsHevcLevel level); + +#endif + /** * A sample is the unit of frame. * It's a NALU for H.264. @@ -741,6 +843,12 @@ class SrsVideoCodecConfig : public SrsCodecConfig SrsAvcProfile avc_profile; // level_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45. SrsAvcLevel avc_level; +#ifdef SRS_H265 + // The profile_idc, T-REC-H.265-202108-I!!PDF-E.pdf, page 559. + SrsHevcProfile hevc_profile; + // The level_idc, T-REC-H.265-202108-I!!PDF-E.pdf, page 684. + SrsHevcLevel hevc_level; +#endif // lengthSizeMinusOne, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16 int8_t NAL_unit_length; // Note that we may resize the vector, so the under-layer bytes may change. @@ -874,6 +982,10 @@ class SrsFormat #ifdef SRS_H265 private: virtual srs_error_t hevc_demux_hvcc(SrsBuffer* stream); + virtual srs_error_t hevc_demux_vps_sps_pps(SrsHevcHvccNalu* nal); + virtual srs_error_t hevc_demux_sps(SrsHevcHvccNalu* nal); + virtual srs_error_t hevc_demux_sps_rbsp(char* rbsp, int nb_rbsp); + virtual srs_error_t hevc_demux_sps_rbsp_ptl(SrsBitBuffer* bs, SrsHevcSpsProfileTierLevel* ptl, int profile_resent_flag, int max_sub_layers_minus1); #endif private: // Parse the H.264 SPS/PPS. diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 4a5553e293..79988d266c 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -267,7 +267,8 @@ XX(ERROR_INOTIFY_WATCH , 3095, "InotfyWatch", "Failed to watch inotify for config listener") \ XX(ERROR_HTTP_URL_UNESCAPE , 3096, "HttpUrlUnescape", "Failed to unescape URL for HTTP") \ XX(ERROR_HTTP_WITH_BODY , 3097, "HttpWithBody", "Failed for HTTP body") \ - XX(ERROR_HEVC_DISABLED , 3098, "HevcDisabled", "HEVC is disabled") + XX(ERROR_HEVC_DISABLED , 3098, "HevcDisabled", "HEVC is disabled") \ + XX(ERROR_HEVC_DECODE_ERROR , 3099, "HevcDecode", "HEVC decode av stream failed") /**************************************************/ /* HTTP/StreamConverter protocol error. */ diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 6ba29930d4..b76cc99868 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -4455,6 +4455,25 @@ VOID TEST(KernelMp3Test, CoverAll) } } +/** +* test the bitbuffer utility, access require +*/ +VOID TEST(KernelUtilityTest, BitBufferRequire) +{ + char data[128]; + SrsBuffer b(data, 128); + SrsBitBuffer bb(&b); + + EXPECT_TRUE(bb.require_bits(1)); + EXPECT_TRUE(bb.require_bits(1024)); + + bb.read_bits(1000); + EXPECT_TRUE(bb.require_bits(1)); + + bb.read_bits(24); + EXPECT_FALSE(bb.require_bits(1)); +} + VOID TEST(KernelUtilityTest, CoverBitsBufferAll) { if (true) { @@ -4492,6 +4511,63 @@ VOID TEST(KernelUtilityTest, CoverBitsBufferAll) srs_error_t err = srs_avc_nalu_read_bit(&bb, v); HELPER_EXPECT_FAILED(err); } + + if (true) { + SrsBuffer b((char*)"\x20\x01", 2); + SrsBitBuffer bb(&b); + + int8_t v = bb.read_8bits(); + EXPECT_EQ(0x20, v); + } + + if (true) { + SrsBuffer b((char*)"\x04\x00\x01\x01", 4); + SrsBitBuffer bb(&b); + + int16_t v = bb.read_16bits(); + EXPECT_EQ(0x0400, v); + } + + if (true) { + SrsBuffer b((char*)"\x00\x00\x04\x00\x01\x01", 6); + SrsBitBuffer bb(&b); + + int32_t v = bb.read_32bits(); + EXPECT_EQ(0x0400, v); + } + + if (true) { + SrsBuffer b((char*)"\x00\x28\x08\x02\xd1\x65\x95\x9a", 8); + SrsBitBuffer bb(&b); + + int32_t v = bb.read_bits_ue(); + EXPECT_EQ(1280, v); + + v = bb.read_bits_ue(); + EXPECT_EQ(720, v); + } + + if (true) { + SrsBuffer b((char*)"\x10\x00\x04\x00\x01\x01\x04\x00", 8); + SrsBitBuffer bb(&b); + + int32_t v = bb.read_bits(1); + EXPECT_EQ(0, v); + + v = bb.read_bits(7); + EXPECT_EQ(0x10, v); + + v = bb.read_bits(13); + EXPECT_EQ(0, v); + + v = bb.read_bits(20); + //100 0000 0000 0000 0001 0 + EXPECT_EQ(0x80002, v); + + v = bb.read_bits(23); + //000 0001 0000 0100 0000 0000 + EXPECT_EQ(0x10400, v); + } } #ifndef SRS_OSX