123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- "use strict";
- function H265SPSParser() {
- var vBitCount = 0;
- var spsMap = null;
- var pSPSBytes = null;
- function Constructor() {
- vBitCount = 0;
- spsMap = new Map();
- }
- function get_bit(base, offset) {
- var vCurBytes = (vBitCount + offset) >> 3;
- offset = (vBitCount + offset) & 0x00000007;
- return (((base[(vCurBytes)])) >> (0x7 - (offset & 0x7))) & 0x1;
- }
- function read_bits(pBuf, vReadBits) {
- var vCurBytes = vBitCount / 8;
- var vCurBits = vBitCount % 8;
- var vOffset = 0;
- var vTmp = 0,
- vTmp2 = 0;
- if (vReadBits == 1) {
- vTmp = get_bit(pBuf, vOffset);
- } else {
- for (var i = 0; i < vReadBits; i++) {
- vTmp2 = get_bit(pBuf, i);
- vTmp = (vTmp << 1) + vTmp2;
- }
- }
- vBitCount += vReadBits;
- return vTmp;
- }
- function ue(base, offset) {
- var zeros = 0,
- vTmp = 0,
- vReturn = 0;
- var vIdx = offset;
- do {
- vTmp = get_bit(base, vIdx++);
- if (vTmp == 0)
- zeros++;
- } while (0 == vTmp);
- if (zeros == 0) {
- vBitCount += 1;
- return 0;
- }
- // insert first 1 bit
- vReturn = 1 << zeros;
- for (var i = zeros - 1; i >= 0; i-- , vIdx++) {
- vTmp = get_bit(base, vIdx);
- vReturn |= vTmp << i;
- }
- vBitCount += zeros * 2 + 1;
- return (vReturn - 1);
- }
- function se(base, offset) {
- var vReturn = ue(base, offset);
- if (vReturn & 0x1) {
- return (vReturn + 1) / 2;
- } else {
- return -vReturn / 2;
- }
- }
- function byte_aligned() {
- if ((vBitCount & 0x00000007) == 0)
- return 1;
- else
- return 0;
- }
- function profile_tier_level(profilePresentFlag, maxNumSubLayersMinus1) {
- if (profilePresentFlag) {
- spsMap.set("general_profile_space", read_bits(pSPSBytes, 2));
- spsMap.set("general_tier_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_profile_idc", read_bits(pSPSBytes, 5));
- var generalProfileCompatibilityFlag = new Array(32);
- for (var j = 0; j < 32; j++) {
- generalProfileCompatibilityFlag[j] = read_bits(pSPSBytes, 1);
- }
- spsMap.set("general_progressive_source_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_interlaced_source_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_non_packed_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_frame_only_constraint_flag", read_bits(pSPSBytes, 1));
- var generalProfileIdc = spsMap.get("general_profile_idc");
- if (generalProfileIdc === 4 || generalProfileCompatibilityFlag[4] ||
- generalProfileIdc === 5 || generalProfileCompatibilityFlag[5] ||
- generalProfileIdc === 6 || generalProfileCompatibilityFlag[6] ||
- generalProfileIdc === 7 || generalProfileCompatibilityFlag[7]) {
- spsMap.set("general_max_12bit_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_max_10bit_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_max_8bit_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_max_422chroma_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_max_420chroma_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_max_monochrome_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_intra_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_one_picture_only_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_lower_bit_rate_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("general_reserved_zero_34bits", read_bits(pSPSBytes, 34));
- } else {
- spsMap.set("general_reserved_zero_43bits", read_bits(pSPSBytes, 43));
- }
- if ((generalProfileIdc >= 1 && generalProfileIdc <= 5) ||
- generalProfileCompatibilityFlag[1] || generalProfileCompatibilityFlag[2] ||
- generalProfileCompatibilityFlag[3] || generalProfileCompatibilityFlag[4] ||
- generalProfileCompatibilityFlag[5]) {
- /* The number of bits in this syntax structure is not affected by this condition */
- spsMap.set("general_inbld_flag", read_bits(pSPSBytes, 1));
- } else {
- spsMap.set("general_reserved_zero_bit", read_bits(pSPSBytes, 1));
- }
- }
- spsMap.set("general_level_idc", read_bits(pSPSBytes, 8));
- var subLayerProfilePresentFlag = new Array(maxNumSubLayersMinus1);
- var subLayerLevelPresentFlag = new Array(maxNumSubLayersMinus1);
- for (i = 0; i < maxNumSubLayersMinus1; i++) {
- subLayerProfilePresentFlag[i] = read_bits(pSPSBytes, 1);
- subLayerLevelPresentFlag[i] = read_bits(pSPSBytes, 1);
- }
- var reservedZero2bits = new Array(8);
- var subLayerProfileIdc = new Array(maxNumSubLayersMinus1);
- if (maxNumSubLayersMinus1 > 0) {
- for (var i = maxNumSubLayersMinus1; i < 8; i++) {
- reservedZero2bits[i] = read_bits(pSPSBytes, 2);
- }
- }
- for (var i = 0; i < maxNumSubLayersMinus1; i++) {
- if (subLayerProfilePresentFlag[i]) {
- spsMap.set("sub_layer_profile_space", read_bits(pSPSBytes, 2));
- spsMap.set("sub_layer_tier_flag", read_bits(pSPSBytes, 1));
- subLayerProfileIdc[i] = read_bits(pSPSBytes, 5);
- for (var j = 0; j < 32; j++) {
- subLayerProfileCompatibilityFlag[i][j] = read_bits(pSPSBytes, 1);
- }
- spsMap.set("sub_layer_progressive_source_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_interlaced_source_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_non_packed_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_frame_only_constraint_flag", read_bits(pSPSBytes, 1));
- if (subLayerProfileIdc[i] === 4 || subLayerProfileCompatibilityFlag[i][4] ||
- subLayerProfileIdc[i] === 5 || subLayerProfileCompatibilityFlag[i][5] ||
- subLayerProfileIdc[i] === 6 || subLayerProfileCompatibilityFlag[i][6] ||
- subLayerProfileIdc[i] === 7 || subLayerProfileCompatibilityFlag[i][7]) {
- /* The number of bits in this syntax structure is not affected by this condition */
- spsMap.set("sub_layer_max_12bit_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_max_10bit_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_max_8bit_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_max_422chroma_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_max_420chroma_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_max_monochrome_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_intra_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_one_picture_only_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_lower_bit_rate_constraint_flag", read_bits(pSPSBytes, 1));
- spsMap.set("sub_layer_reserved_zero_34bits", read_bits(pSPSBytes, 34));
- } else {
- spsMap.set("sub_layer_reserved_zero_43bits", read_bits(pSPSBytes, 43));
- }
- if ((subLayerProfileIdc[i] >= 1 && subLayerProfileIdc[i] <= 5) ||
- subLayerProfileCompatibilityFlag[1] || subLayerProfileCompatibilityFlag[2] ||
- subLayerProfileCompatibilityFlag[3] || subLayerProfileCompatibilityFlag[4] ||
- subLayerProfileCompatibilityFlag[5]) {
- /* The number of bits in this syntax structure is not affected by this condition */
- spsMap.set("sub_layer_inbld_flag", read_bits(pSPSBytes, 1));
- } else {
- spsMap.set("sub_layer_reserved_zero_bit", read_bits(pSPSBytes, 1));
- }
- }
- if (subLayerLevelPresentFlag[i]) {
- spsMap.set("sub_layer_level_idc", read_bits(pSPSBytes, 8));
- }
- }
- }
- Constructor.prototype = {
- parse: function (spsPayload) {
- pSPSBytes = spsPayload;
- //console.log("=========================SPS START=========================");
- vBitCount = 0;
- spsMap.clear();
- spsMap.set("forbidden_zero_bit", read_bits(pSPSBytes, 1));
- spsMap.set("nal_unit_type", read_bits(pSPSBytes, 6));
- spsMap.set("nuh_layer_id", read_bits(pSPSBytes, 6));
- spsMap.set("nuh_temporal_id_plus1", read_bits(pSPSBytes, 3));
- spsMap.set("sps_video_parameter_set_id", read_bits(pSPSBytes, 4));
- if (spsMap.get("nuh_layer_id") === 0) {
- spsMap.set("sps_max_sub_layers_minus1", read_bits(pSPSBytes, 3));
- } else {
- spsMap.set("sps_ext_or_max_sub_layers_minus1", read_bits(pSPSBytes, 3));
- }
- var MultiLayerExtSpsFlag = (spsMap.get("nuh_layer_id") !== 0 && spsMap.get("sps_ext_or_max_sub_layers_minus1") === 7);
- if (!MultiLayerExtSpsFlag) {
- spsMap.set("sps_max_sub_layers_minus1", read_bits(pSPSBytes, 1));
- //profile_tier_level(1, spsMap.get("sps_max_sub_layers_minus1"));
- }
- read_bits(pSPSBytes, 84);
- spsMap.set("sps_seq_parameter_set_id", ue(pSPSBytes, 0));
- if (MultiLayerExtSpsFlag) {
- spsMap.set("update_rep_format_flag", read_bits(pSPSBytes, 1));
- if (spsMap.get("update_rep_format_flag")) {
- spsMap.set("sps_rep_format_idx", read_bits(pSPSBytes, 8));
- }
- } else {
- spsMap.set("chroma_format_idc", ue(pSPSBytes, 0));
- if (spsMap.get("chroma_format_idc") === 3) {
- spsMap.set("separate_colour_plane_flag", read_bits(pSPSBytes, 1));
- }
- spsMap.set("pic_width_in_luma_samples", ue(pSPSBytes, 0));
- spsMap.set("pic_height_in_luma_samples", ue(pSPSBytes, 0));
- spsMap.set("conformance_window_flag", read_bits(pSPSBytes, 1));
- if (spsMap.get("conformance_window_flag")) {
- spsMap.set("conf_win_left_offset", ue(pSPSBytes, 0));
- spsMap.set("conf_win_right_offset", ue(pSPSBytes, 0));
- spsMap.set("conf_win_top_offset", ue(pSPSBytes, 0));
- spsMap.set("conf_win_bottom_offset", ue(pSPSBytes, 0));
- }
- }
- //console.log("=========================SPS END=========================");
- return true;
- },
- getSizeInfo: function () {
- var width = spsMap.get("pic_width_in_luma_samples");
- var height = spsMap.get("pic_height_in_luma_samples");
- if (spsMap.get("conformance_window_flag")) {
- var chromaFormatIdc = spsMap.get("chroma_format_idc");
- var separateColourPlaneFlag = spsMap.get("separate_colour_plane_flag");
- if (typeof separateColourPlaneFlag === "undefined") {
- separateColourPlaneFlag = 0;
- }
- var subWidthC = ((1 === chromaFormatIdc) || (2 === chromaFormatIdc)) && (0 === separateColourPlaneFlag) ? 2 : 1;
- var subHeightC = (1 === chromaFormatIdc) && (0 === separateColourPlaneFlag) ? 2 : 1;
- width -= (subWidthC * spsMap.get("conf_win_right_offset") + subWidthC * spsMap.get("conf_win_left_offset"));
- height -= (subHeightC * spsMap.get("conf_win_bottom_offset") + subHeightC * spsMap.get("conf_win_top_offset"));
- }
- var decodeSize = width * height;
- var sizeInfo = {
- 'width': width,
- 'height': height,
- 'decodeSize': decodeSize
- };
- return sizeInfo;
- },
- getSpsValue: function (key) {
- return spsMap.get(key);
- },
- };
- return new Constructor();
- }
|