mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
* BitBuffer: add method to implement bit read operation. * Codec: demux hevc sps for profile level resolution. * Statistic: refine hevc profile level resolution. * Kernel: return error code for demux hevc. * Kernel: check bitstream length for hevc sps. * UTest: add BitBuffer read bits utest. * Kernel: refine print log and utest. * Kernel: add comment for hevc sps. Co-authored-by: winlin <winlin@vip.126.com>
This commit is contained in:
parent
e6c395e473
commit
a0803b556b
9 changed files with 729 additions and 19 deletions
|
@ -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);
|
c->width, c->height, c->video_data_rate / 1000, c->frame_rate, c->duration);
|
||||||
#ifdef SRS_H265
|
#ifdef SRS_H265
|
||||||
} else if (c->id == SrsVideoCodecIdHEVC) {
|
} else if (c->id == SrsVideoCodecIdHEVC) {
|
||||||
// TODO: FIXME: Use the correct information for HEVC.
|
err = stat->on_video_info(req_, c->id, c->hevc_profile, c->hevc_level, c->width, c->height);
|
||||||
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, profile=%s, level=%s, %dx%d, %dkbps, %.1ffps, %.1fs)",
|
||||||
srs_trace("%dB video sh, codec(%d)", msg->size, c->id);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
if (err != srs_success) {
|
if (err != srs_success) {
|
||||||
|
|
|
@ -143,8 +143,20 @@ srs_error_t SrsStatisticStream::dumps(SrsJsonObject* obj)
|
||||||
obj->set("video", video);
|
obj->set("video", video);
|
||||||
|
|
||||||
video->set("codec", SrsJsonAny::str(srs_video_codec_id2str(vcodec).c_str()));
|
video->set("codec", SrsJsonAny::str(srs_video_codec_id2str(vcodec).c_str()));
|
||||||
|
|
||||||
|
if (vcodec == SrsVideoCodecIdAVC) {
|
||||||
video->set("profile", SrsJsonAny::str(srs_avc_profile2str(avc_profile).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()));
|
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("width", SrsJsonAny::integer(width));
|
||||||
video->set("height", SrsJsonAny::integer(height));
|
video->set("height", SrsJsonAny::integer(height));
|
||||||
}
|
}
|
||||||
|
@ -335,7 +347,7 @@ SrsStatisticClient* SrsStatistic::find_client(string client_id)
|
||||||
return NULL;
|
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;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
@ -344,8 +356,19 @@ srs_error_t SrsStatistic::on_video_info(SrsRequest* req, SrsVideoCodecId vcodec,
|
||||||
|
|
||||||
stream->has_video = true;
|
stream->has_video = true;
|
||||||
stream->vcodec = vcodec;
|
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->width = width;
|
||||||
stream->height = height;
|
stream->height = height;
|
||||||
|
|
|
@ -70,6 +70,12 @@ public:
|
||||||
SrsAvcProfile avc_profile;
|
SrsAvcProfile avc_profile;
|
||||||
// The level_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45.
|
// The level_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45.
|
||||||
SrsAvcLevel avc_level;
|
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.
|
// The width and height in codec info.
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
@ -157,8 +163,7 @@ public:
|
||||||
virtual SrsStatisticClient* find_client(std::string client_id);
|
virtual SrsStatisticClient* find_client(std::string client_id);
|
||||||
public:
|
public:
|
||||||
// When got video info for stream.
|
// When got video info for stream.
|
||||||
virtual srs_error_t on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, SrsAvcProfile avc_profile,
|
virtual srs_error_t on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, int avc_profile, int avc_level, int width, int height);
|
||||||
SrsAvcLevel avc_level, int width, int height);
|
|
||||||
// When got audio info for stream.
|
// When got audio info for stream.
|
||||||
virtual srs_error_t on_audio_info(SrsRequest* req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate,
|
virtual srs_error_t on_audio_info(SrsRequest* req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate,
|
||||||
SrsAudioChannels asound_type, SrsAacObjectType aac_object);
|
SrsAudioChannels asound_type, SrsAacObjectType aac_object);
|
||||||
|
|
|
@ -379,6 +379,15 @@ bool SrsBitBuffer::empty() {
|
||||||
return stream->empty();
|
return stream->empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsBitBuffer::require_bits(int n)
|
||||||
|
{
|
||||||
|
if (n < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n <= left_bits();
|
||||||
|
}
|
||||||
|
|
||||||
int8_t SrsBitBuffer::read_bit() {
|
int8_t SrsBitBuffer::read_bit() {
|
||||||
if (!cb_left) {
|
if (!cb_left) {
|
||||||
srs_assert(!stream->empty());
|
srs_assert(!stream->empty());
|
||||||
|
@ -391,3 +400,75 @@ int8_t SrsBitBuffer::read_bit() {
|
||||||
return v;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -174,6 +174,14 @@ public:
|
||||||
public:
|
public:
|
||||||
bool empty();
|
bool empty();
|
||||||
int8_t read_bit();
|
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
|
#endif
|
||||||
|
|
|
@ -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()
|
SrsSample::SrsSample()
|
||||||
{
|
{
|
||||||
size = 0;
|
size = 0;
|
||||||
|
@ -882,6 +917,8 @@ srs_error_t SrsFormat::video_avc_demux(SrsBuffer* stream, int64_t timestamp)
|
||||||
// Parse the hevc vps/sps/pps
|
// Parse the hevc vps/sps/pps
|
||||||
srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream)
|
srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream)
|
||||||
{
|
{
|
||||||
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
int avc_extra_size = stream->size() - stream->pos();
|
int avc_extra_size = stream->size() - stream->pos();
|
||||||
if (avc_extra_size > 0) {
|
if (avc_extra_size > 0) {
|
||||||
char *copy_stream_from = stream->data() + stream->pos();
|
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
|
const int HEVC_MIN_SIZE = 23; // From configuration_version to numOfArrays
|
||||||
if (!stream->require(HEVC_MIN_SIZE)) {
|
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_);
|
SrsHevcDecoderConfigurationRecord* dec_conf_rec_p = &(vcodec->hevc_dec_conf_record_);
|
||||||
dec_conf_rec_p->configuration_version = stream->read_1bytes();
|
dec_conf_rec_p->configuration_version = stream->read_1bytes();
|
||||||
if (dec_conf_rec_p->configuration_version != 1) {
|
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)
|
// 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);
|
dec_conf_rec_p->bit_depth_luma_minus8, dec_conf_rec_p->bit_depth_chroma_minus8);
|
||||||
|
|
||||||
//avg_frame_rate: 16bits
|
//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),
|
//8bits: constant_frame_rate(2bits), num_temporal_layers(3bits),
|
||||||
// temporal_id_nested(1bit), length_size_minus_one(2bits)
|
// temporal_id_nested(1bit), length_size_minus_one(2bits)
|
||||||
data_byte = stream->read_1bytes();
|
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
|
// 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.
|
// length encoded with 1, 2, or 4 bytes, respectively.
|
||||||
if (vcodec->NAL_unit_length == 2) {
|
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();
|
uint8_t numOfArrays = stream->read_1bytes();
|
||||||
|
@ -965,7 +1002,7 @@ srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer* stream)
|
||||||
SrsHevcHvccNalu hevc_unit;
|
SrsHevcHvccNalu hevc_unit;
|
||||||
|
|
||||||
if (!stream->require(5)) {
|
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();
|
data_byte = stream->read_1bytes();
|
||||||
hevc_unit.array_completeness = (data_byte >> 7) & 0x01;
|
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();
|
data_item.nal_unit_length = stream->read_2bytes();
|
||||||
|
|
||||||
if (!stream->require(data_item.nal_unit_length)) {
|
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());
|
data_item.nal_unit_length, stream->left());
|
||||||
}
|
}
|
||||||
//copy vps/pps/sps data
|
//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);
|
hevc_unit.nal_data_vec.push_back(data_item);
|
||||||
}
|
}
|
||||||
dec_conf_rec_p->nalu_vec.push_back(hevc_unit);
|
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<int8_t> 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
|
#endif
|
||||||
|
|
||||||
srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer* stream)
|
srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer* stream)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class SrsBuffer;
|
class SrsBuffer;
|
||||||
|
class SrsBitBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The video codec id.
|
* The video codec id.
|
||||||
|
@ -502,6 +503,63 @@ struct SrsHevcDecoderConfigurationRecord {
|
||||||
uint8_t length_size_minus_one;
|
uint8_t length_size_minus_one;
|
||||||
std::vector<SrsHevcHvccNalu> nalu_vec;
|
std::vector<SrsHevcHvccNalu> 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<uint8_t> sub_layer_profile_present_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_level_present_flag;
|
||||||
|
uint8_t reserved_zero_2bits[8];
|
||||||
|
std::vector<uint8_t> sub_layer_profile_space;
|
||||||
|
std::vector<uint8_t> sub_layer_tier_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_profile_idc;
|
||||||
|
std::vector<std::vector<uint8_t> > sub_layer_profile_compatibility_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_progressive_source_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_interlaced_source_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_non_packed_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_frame_only_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_max_12bit_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_max_10bit_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_max_8bit_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_max_422chroma_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_max_420chroma_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_max_monochrome_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_intra_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_one_picture_only_constraint_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_lower_bit_rate_constraint_flag;
|
||||||
|
std::vector<uint64_t> sub_layer_reserved_zero_34bits;
|
||||||
|
std::vector<uint64_t> sub_layer_reserved_zero_43bits;
|
||||||
|
std::vector<uint8_t> sub_layer_inbld_flag;
|
||||||
|
std::vector<uint8_t> sub_layer_reserved_zero_bit;
|
||||||
|
std::vector<uint8_t> sub_layer_level_idc;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -627,6 +685,50 @@ enum SrsAvcLevel
|
||||||
};
|
};
|
||||||
std::string srs_avc_level2str(SrsAvcLevel level);
|
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.
|
* A sample is the unit of frame.
|
||||||
* It's a NALU for H.264.
|
* It's a NALU for H.264.
|
||||||
|
@ -741,6 +843,12 @@ public:
|
||||||
SrsAvcProfile avc_profile;
|
SrsAvcProfile avc_profile;
|
||||||
// level_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45.
|
// level_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45.
|
||||||
SrsAvcLevel avc_level;
|
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
|
// lengthSizeMinusOne, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
|
||||||
int8_t NAL_unit_length;
|
int8_t NAL_unit_length;
|
||||||
// Note that we may resize the vector, so the under-layer bytes may change.
|
// Note that we may resize the vector, so the under-layer bytes may change.
|
||||||
|
@ -874,6 +982,10 @@ private:
|
||||||
#ifdef SRS_H265
|
#ifdef SRS_H265
|
||||||
private:
|
private:
|
||||||
virtual srs_error_t hevc_demux_hvcc(SrsBuffer* stream);
|
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
|
#endif
|
||||||
private:
|
private:
|
||||||
// Parse the H.264 SPS/PPS.
|
// Parse the H.264 SPS/PPS.
|
||||||
|
|
|
@ -267,7 +267,8 @@
|
||||||
XX(ERROR_INOTIFY_WATCH , 3095, "InotfyWatch", "Failed to watch inotify for config listener") \
|
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_URL_UNESCAPE , 3096, "HttpUrlUnescape", "Failed to unescape URL for HTTP") \
|
||||||
XX(ERROR_HTTP_WITH_BODY , 3097, "HttpWithBody", "Failed for HTTP body") \
|
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. */
|
/* HTTP/StreamConverter protocol error. */
|
||||||
|
|
|
@ -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)
|
VOID TEST(KernelUtilityTest, CoverBitsBufferAll)
|
||||||
{
|
{
|
||||||
if (true) {
|
if (true) {
|
||||||
|
@ -4492,6 +4511,63 @@ VOID TEST(KernelUtilityTest, CoverBitsBufferAll)
|
||||||
srs_error_t err = srs_avc_nalu_read_bit(&bb, v);
|
srs_error_t err = srs_avc_nalu_read_bit(&bb, v);
|
||||||
HELPER_EXPECT_FAILED(err);
|
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
|
#ifndef SRS_OSX
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue