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);
|
||||
#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) {
|
||||
|
|
|
@ -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,8 +356,19 @@ 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;
|
||||
|
|
|
@ -70,6 +70,12 @@ public:
|
|||
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 @@ public:
|
|||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -174,6 +174,14 @@ public:
|
|||
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
|
||||
|
|
|
@ -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<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
|
||||
|
||||
srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer* stream)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <vector>
|
||||
|
||||
class SrsBuffer;
|
||||
class SrsBitBuffer;
|
||||
|
||||
/**
|
||||
* The video codec id.
|
||||
|
@ -502,6 +503,63 @@ struct SrsHevcDecoderConfigurationRecord {
|
|||
uint8_t length_size_minus_one;
|
||||
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
|
||||
|
||||
/**
|
||||
|
@ -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 @@ public:
|
|||
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 @@ private:
|
|||
#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.
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue