1 Star 0 Fork 0

我的身份要低调/h264Analysis

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
Parser.js 6.96 KB
一键复制 编辑 原始数据 按行查看 历史
我的身份要低调 提交于 2022-04-06 09:14 +08:00 . sps pps parse
class BaseParser {
constructor(body, curByte = 0, curIndex = 1) {
// 读取到当前字节数
this.curByte = curByte;
// 读取字节的位置
this.curIndex = curIndex;
// uint8array => h264 unit info
this.body = body;
}
/**
* leadingzerobits:1前面的0个数
* read_bits:读取1后面leadingzerobits位
* codeNum = 2^leadingzerobits − 1 + read_bits( leadingZeroBits )
* @returns code_num
*/
readUV() {
let leadingzerobits = 0,
biteVal = 0;
while (!biteVal) {
biteVal = readBit(this.body[this.curByte], this.curIndex);
if (biteVal === 0) {
leadingzerobits++;
}
if (this.curIndex === 8) {
this.curIndex = 1;
this.curByte++;
} else {
this.curIndex++;
}
}
let code_num = "";
for (let index = 0; index < leadingzerobits; index++) {
code_num += readBit(this.body[this.curByte], this.curIndex);
if (this.curIndex === 8) {
this.curIndex = 1;
this.curByte++;
} else {
this.curIndex++;
}
}
return 2 ** leadingzerobits - 1 + parseInt(code_num, 2);
}
/**
* 第一步,通过bs_read_ue(),获取codeNum的值。
* 第二步:根据codeNum的奇偶性,计算出se(v)编码前的值
* codeNum & 0x01: 如果为奇数,codeNum = (codeNum + 1)/2
* : 如果为偶数,codeNum = -(codeNum/2)
* @returns code_num
*/
readSE() {
const code_num = this.readUV(this.body);
const isOdd = code_num % 2 === 1;
return isOdd ? (code_num + 1) / 2 : -(code_num / 2);
}
/**
* 读取指定位数的数据
* @param {number} len
*/
readBits(len) {
const code_num = "";
for (let index = 0; index < len; index++) {
code_num += readBit(this.body[this.curByte], this.curIndex);
if (this.curIndex === 8) {
this.curIndex = 1;
this.curByte++;
} else {
this.curIndex++;
}
}
return parseInt(code_num, 2);
}
}
class Sps extends BaseParser {
constructor(body) {
super(body);
this.profile_idc = this.readBits(8);
for (let index = 0; index < 6; index++) {
this[`constraint_set${index}_flag`] = this.readBits(1);
}
this.reserved_zero_2bits = this.readBits(2);
this.level_idc = this.readBits(8);
this.seq_parameter_set_id = this.readUV();
this.log2_max_frame_num_minus4 = this.readUV();
this.pic_order_cnt_type = this.readUV();
if (this.pic_order_cnt_type === 0) {
this.log2_max_pic_order_cnt_lsb_minus4 = readUV();
} else if (this.pic_order_cnt_type === 1) {
this.delta_pic_order_always_zero_flag = this.readBits(1);
this.offset_for_non_ref_pic = this.readSE();
this.offset_for_top_to_bottom_field = this.readSE();
this.num_ref_frames_in_pic_order_cnt_cycle = this.readUV();
this.offset_for_ref_frame = [];
for (let index = 0; index < this.num_ref_frames_in_pic_order_cnt_cycle; index++) {
this.offset_for_ref_frame.push(this.readSE());
}
this.max_num_ref_frames = this.readUV();
this.gaps_in_frame_num_value_allowed_flag = this.readBits(1);
this.pic_width_in_mbs_minus1 = this.readUV();
this.pic_height_in_map_units_minus1 = this.readUV();
this.frame_mbs_only_flag = this.readBits(1);
if (!this.frame_mbs_only_flag) {
this.mb_adaptive_frame_field_flag = this.readBits(1);
}
this.direct_8x8_inference_flag = this.readBits(1);
this.frame_cropping_flag = this.readBits(1);
if (this.frame_cropping_flag) {
this.frame_crop_left_offset = this.readUV();
this.frame_crop_right_offset = this.readUV();
this.frame_crop_top_offset = this.readUV();
this.frame_crop_bottom_offset = this.readUV();
}
this.vui_parameters_present_flag = this.readBits(1);
}
}
}
class Pps extends BaseParser {
constructor(body) {
super(body);
this.pic_parameter_set_id = this.readUV();
this.seq_parameter_set_id = this.readUV();
this.entropy_coding_mode_flag = this.readBits(1);
this.num_slice_groups_minus1 = this.readUV();
if (this.num_slice_groups_minus1 > 0) {
this.slice_group_map_type = this.readUV();
if (this.slice_group_map_type == 0) {
this.run_length_minus1 = [];
for (let index = 0; index < this.num_slice_groups_minus1; index++) {
this.run_length_minus1.push(this.readUV());
}
} else if (this.slice_group_map_type == 2) {
this.top_left = [];
this.bottom_right = [];
for (let index = 0; index < this.num_slice_groups_minus1; index++) {
this.top_left.push(this.readUV());
this.bottom_right.push(this.readUV());
}
} else if (this.slice_group_map_type === 3 || this.slice_group_map_type === 4 || this.slice_group_map_type === 5) {
this.slice_group_change_direction_flag = this.readBits(1);
this.slice_group_change_rate_minus1 = this.readUV();
} else if (this.slice_group_map_type == 6) {
this.pic_size_in_map_units_minus1 = this.readUV();
this.slice_group_id = [];
for (let index = 0; index < this.pic_size_in_map_units_minus1; index++) {
this.slice_group_id.push(this.readUV());
}
}
}
this.num_ref_idx_10_default_active_minus1 = this.readUV();
this.num_ref_idx_11_default_active_minus1 = this.readUV();
this.weighted_pred_flag = this.readBits(1);
this.weighted_bipred_idc = this.readBits(2);
this.pic_init_qp_minus26 = this.readSE();
this.pic_init_qs_minus26 = this.readSE();
this.chroma_qp_index_offset = this.readSE();
this.deblocking_filter_control_present_flag = this.readBits(1);
this.constrained_intra_pred_flag = this.readBits(1);
this.redundant_pic_present_flag = this.readBits(1);
// if (more_rbsp_data())
}
}
/**
* 读取指定位置的值
* @param {*} val
* @param {*} index
* @param {*} direction
* @returns
*/
function readBit(val, index, direction = "ltr") {
if (direction === "rtl") {
return (val >> (index - 1)) & 0x01;
} else if (direction === "ltr") {
return (val >> (8 - index)) & 0x01;
}
}
export function SpsParser(body) {
return new Sps(body);
}
export function PpsParser(body) {
return new Pps(body);
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/sunkingsss/h264-analysis.git
git@gitee.com:sunkingsss/h264-analysis.git
sunkingsss
h264-analysis
h264Analysis
master

搜索帮助