1 Star 0 Fork 13

Anonymity / Node-Media-Server

forked from nygula / Node-Media-Server 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
node_core_av.js 13.42 KB
一键复制 编辑 原始数据 按行查看 历史
illuspas 提交于 2018-01-31 23:35 . Update node_core_av.js
//
// Created by Mingliang Chen on 17/12/21.
// illuspas[a]gmail.com
// Copyright (c) 2017 Nodemedia. All rights reserved.
//
const Bitop = require('./node_core_bitop');
const AAC_SAMPLE_RATE = [
96000, 88200, 64000, 48000,
44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000,
7350, 0, 0, 0
];
const AAC_CHANNELS = [
0, 1, 2, 3, 4, 5, 6, 8
];
const AUDIO_CODEC_NAME = [
'',
'ADPCM',
"MP3",
"LinearLE",
"Nellymoser16",
"Nellymoser8",
"Nellymoser",
"G711A",
"G711U",
"",
"AAC",
"Speex",
"",
"",
"MP3-8K",
"DeviceSpecific",
"Uncompressed"
];
const AUDIO_SOUND_RATE = [
5512, 11025, 22050, 44100
];
const VIDEO_CODEC_NAME = [
"",
"Jpeg",
"Sorenson-H263",
"ScreenVideo",
"On2-VP6",
"On2-VP6-Alpha",
"ScreenVideo2",
"H264",
"",
"",
"",
"",
"H265"
];
function getObjectType(bitop) {
let audioObjectType = bitop.read(5);
if (audioObjectType === 31) {
audioObjectType = bitop.read(6) + 32;
}
return audioObjectType;
}
function getSampleRate(bitop, info) {
info.sampling_index = bitop.read(4);
return info.sampling_index == 0x0f ? bitop.read(24) : AAC_SAMPLE_RATE[info.sampling_index];
}
function readAACSpecificConfig(aacSequenceHeader) {
let info = {};
let bitop = new Bitop(aacSequenceHeader);
bitop.read(16);
info.object_type = getObjectType(bitop);
info.sample_rate = getSampleRate(bitop, info);
info.chan_config = bitop.read(4);
if (info.chan_config < AAC_CHANNELS.length) {
info.channels = AAC_CHANNELS[info.chan_config];
}
info.sbr = -1;
info.ps = -1;
if (info.object_type == 5 || info.object_type == 29) {
if (info.object_type == 29) {
info.ps = 1;
}
info.ext_object_type = 5;
info.sbr = 1;
info.sample_rate = getSampleRate(bitop, info);
info.object_type = getObjectType(bitop);
}
return info;
}
function getAACProfileName(info) {
switch (info.object_type) {
case 1:
return "Main";
case 2:
if (info.ps > 0) {
return "HEv2";
}
if (info.sbr > 0) {
return "HE";
}
return "LC";
case 3:
return "SSR";
case 4:
return "LTP";
case 5:
return "SBR";
default:
return "";
}
}
function readH264SpecificConfig(avcSequenceHeader) {
let info = {};
let profile_idc, width, height, crop_left, crop_right,
crop_top, crop_bottom, frame_mbs_only, n, cf_idc,
num_ref_frames;
let bitop = new Bitop(avcSequenceHeader);
bitop.read(48);
info.width = 0;
info.height = 0;
do {
info.profile = bitop.read(8);
info.compat = bitop.read(8);
info.level = bitop.read(8);
info.nalu = (bitop.read(8) & 0x03) + 1;
info.nb_sps = bitop.read(8) & 0x1F;
if (info.nb_sps == 0) {
break;
}
/* nal size */
bitop.read(16);
/* nal type */
if (bitop.read(8) != 0x67) {
break;
}
/* SPS */
profile_idc = bitop.read(8);
/* flags */
bitop.read(8);
/* level idc */
bitop.read(8);
/* SPS id */
bitop.read_golomb();
if (profile_idc == 100 || profile_idc == 110 ||
profile_idc == 122 || profile_idc == 244 || profile_idc == 44 ||
profile_idc == 83 || profile_idc == 86 || profile_idc == 118) {
/* chroma format idc */
cf_idc = bitop.read_golomb();
if (cf_idc == 3) {
/* separate color plane */
bitop.read(1);
}
/* bit depth luma - 8 */
bitop.read_golomb();
/* bit depth chroma - 8 */
bitop.read_golomb();
/* qpprime y zero transform bypass */
bitop.read(1);
/* seq scaling matrix present */
if (bitop.read(1)) {
for (n = 0; n < (cf_idc != 3 ? 8 : 12); n++) {
/* seq scaling list present */
if (bitop.read(1)) {
/* TODO: scaling_list()
if (n < 6) {
} else {
}
*/
}
}
}
}
/* log2 max frame num */
bitop.read_golomb();
/* pic order cnt type */
switch (bitop.read_golomb()) {
case 0:
/* max pic order cnt */
bitop.read_golomb();
break;
case 1:
/* delta pic order alwys zero */
bitop.read(1);
/* offset for non-ref pic */
bitop.read_golomb();
/* offset for top to bottom field */
bitop.read_golomb();
/* num ref frames in pic order */
num_ref_frames = bitop.read_golomb();
for (n = 0; n < num_ref_frames; n++) {
/* offset for ref frame */
bitop.read_golomb();
}
}
/* num ref frames */
info.avc_ref_frames = bitop.read_golomb();
/* gaps in frame num allowed */
bitop.read(1);
/* pic width in mbs - 1 */
width = bitop.read_golomb();
/* pic height in map units - 1 */
height = bitop.read_golomb();
/* frame mbs only flag */
frame_mbs_only = bitop.read(1);
if (!frame_mbs_only) {
/* mbs adaprive frame field */
bitop.read(1);
}
/* direct 8x8 inference flag */
bitop.read(1);
/* frame cropping */
if (bitop.read(1)) {
crop_left = bitop.read_golomb();
crop_right = bitop.read_golomb();
crop_top = bitop.read_golomb();
crop_bottom = bitop.read_golomb();
} else {
crop_left = 0;
crop_right = 0;
crop_top = 0;
crop_bottom = 0;
}
info.level = info.level / 10.0;
info.width = (width + 1) * 16 - (crop_left + crop_right) * 2;
info.height = (2 - frame_mbs_only) * (height + 1) * 16 - (crop_top + crop_bottom) * 2;
} while (0);
return info;
}
function HEVCParsePtl(bitop, hevc, max_sub_layers_minus1) {
let general_ptl = {};
general_ptl.profile_space = bitop.read(2);
general_ptl.tier_flag = bitop.read(1);
general_ptl.profile_idc = bitop.read(5);
general_ptl.profile_compatibility_flags = bitop.read(32);
general_ptl.general_progressive_source_flag = bitop.read(1);
general_ptl.general_interlaced_source_flag = bitop.read(1);
general_ptl.general_non_packed_constraint_flag = bitop.read(1);
general_ptl.general_frame_only_constraint_flag = bitop.read(1);
bitop.read(32);
bitop.read(12);
general_ptl.level_idc = bitop.read(8);
general_ptl.sub_layer_profile_present_flag = [];
general_ptl.sub_layer_level_present_flag = [];
for (let i = 0; i < max_sub_layers_minus1; i++) {
general_ptl.sub_layer_profile_present_flag[i] = bitop.read(1);
general_ptl.sub_layer_level_present_flag[i] = bitop.read(1);
}
if (max_sub_layers_minus1 > 0) {
for (let i = max_sub_layers_minus1; i < 8; i++) {
bitop.read(2)
}
}
general_ptl.sub_layer_profile_space = [];
general_ptl.sub_layer_tier_flag = [];
general_ptl.sub_layer_profile_idc = [];
general_ptl.sub_layer_profile_compatibility_flag = [];
general_ptl.sub_layer_progressive_source_flag = [];
general_ptl.sub_layer_interlaced_source_flag = [];
general_ptl.sub_layer_non_packed_constraint_flag = [];
general_ptl.sub_layer_frame_only_constraint_flag = [];
general_ptl.sub_layer_level_idc = [];
for (let i = 0; i < max_sub_layers_minus1; i++) {
if (general_ptl.sub_layer_profile_present_flag[i]) {
general_ptl.sub_layer_profile_space[i] = bitop.read(2);
general_ptl.sub_layer_tier_flag[i] = bitop.read(1);
general_ptl.sub_layer_profile_idc[i] = bitop.read(5);
general_ptl.sub_layer_profile_compatibility_flag[i] = bitop.read(32);
general_ptl.sub_layer_progressive_source_flag[i] = bitop.read(1);
general_ptl.sub_layer_interlaced_source_flag[i] = bitop.read(1);
general_ptl.sub_layer_non_packed_constraint_flag[i] = bitop.read(1);
general_ptl.sub_layer_frame_only_constraint_flag[i] = bitop.read(1);
bitop.read(32);
bitop.read(12);
}
if (general_ptl.sub_layer_level_present_flag[i]) {
general_ptl.sub_layer_level_idc[i] = bitop.read(8);
}
else {
general_ptl.sub_layer_level_idc[i] = 1;
}
}
return general_ptl;
}
function HEVCParseSPS(SPS, hevc) {
let psps = {};
let NumBytesInNALunit = SPS.length;
let NumBytesInRBSP = 0;
let rbsp_array = [];
let bitop = new Bitop(SPS);
bitop.read(1);//forbidden_zero_bit
bitop.read(6);//nal_unit_type
bitop.read(6);//nuh_reserved_zero_6bits
bitop.read(3);//nuh_temporal_id_plus1
for (let i = 2; i < NumBytesInNALunit; i++) {
if (i + 2 < NumBytesInNALunit && bitop.look(24) == 0x000003) {
rbsp_array.push(bitop.read(8));
rbsp_array.push(bitop.read(8));
i += 2;
let emulation_prevention_three_byte = bitop.read(8); /* equal to 0x03 */
} else {
rbsp_array.push(bitop.read(8));
}
}
let rbsp = Buffer.from(rbsp_array);
let rbspBitop = new Bitop(rbsp);
psps.sps_video_parameter_set_id = rbspBitop.read(4);
psps.sps_max_sub_layers_minus1 = rbspBitop.read(3);
psps.sps_temporal_id_nesting_flag = rbspBitop.read(1);
psps.profile_tier_level = HEVCParsePtl(rbspBitop, hevc, psps.sps_max_sub_layers_minus1);
psps.sps_seq_parameter_set_id = rbspBitop.read_golomb();
psps.chroma_format_idc = rbspBitop.read_golomb();
if (psps.chroma_format_idc == 3) {
psps.separate_colour_plane_flag = rbspBitop.read(1);
} else {
psps.separate_colour_plane_flag = 0;
}
psps.pic_width_in_luma_samples = rbspBitop.read_golomb();
psps.pic_height_in_luma_samples = rbspBitop.read_golomb();
psps.conformance_window_flag = rbspBitop.read(1);
if (psps.conformance_window_flag) {
let vert_mult = 1 + (psps.chroma_format_idc < 2);
let horiz_mult = 1 + (psps.chroma_format_idc < 3);
psps.conf_win_left_offset = rbspBitop.read_golomb() * horiz_mult;
psps.conf_win_right_offset = rbspBitop.read_golomb() * horiz_mult;
psps.conf_win_top_offset = rbspBitop.read_golomb() * vert_mult;
psps.conf_win_bottom_offset = rbspBitop.read_golomb() * vert_mult;
}
// console.log(psps);
return psps;
}
function readHEVCSpecificConfig(hevcSequenceHeader) {
let info = {};
info.width = 0;
info.height = 0;
info.profile = 0;
info.level = 0;
// let bitop = new Bitop(hevcSequenceHeader);
// bitop.read(48);
hevcSequenceHeader = hevcSequenceHeader.slice(5);
do {
let hevc = {};
if (hevcSequenceHeader.length < 23) {
break;
}
hevc.configurationVersion = hevcSequenceHeader[0];
if (hevc.configurationVersion != 1) {
break;
}
hevc.general_profile_space = (hevcSequenceHeader[1] >> 6) & 0x03;
hevc.general_tier_flag = (hevcSequenceHeader[1] >> 5) & 0x01;
hevc.general_profile_idc = hevcSequenceHeader[1] & 0x1F;
hevc.general_profile_compatibility_flags = (hevcSequenceHeader[2] << 24) | (hevcSequenceHeader[3] << 16) | (hevcSequenceHeader[4] << 8) | hevcSequenceHeader[5];
hevc.general_constraint_indicator_flags = ((hevcSequenceHeader[6] << 24) | (hevcSequenceHeader[7] << 16) | (hevcSequenceHeader[8] << 8) | hevcSequenceHeader[9]);
hevc.general_constraint_indicator_flags = (hevc.general_constraint_indicator_flags << 16) | (hevcSequenceHeader[10] << 8) | hevcSequenceHeader[11];
hevc.general_level_idc = hevcSequenceHeader[12];
hevc.min_spatial_segmentation_idc = ((hevcSequenceHeader[13] & 0x0F) << 8) | hevcSequenceHeader[14];
hevc.parallelismType = hevcSequenceHeader[15] & 0x03;
hevc.chromaFormat = hevcSequenceHeader[16] & 0x03;
hevc.bitDepthLumaMinus8 = hevcSequenceHeader[17] & 0x07;
hevc.bitDepthChromaMinus8 = hevcSequenceHeader[18] & 0x07;
hevc.avgFrameRate = (hevcSequenceHeader[19] << 8) | hevcSequenceHeader[20];
hevc.constantFrameRate = (hevcSequenceHeader[21] >> 6) & 0x03;
hevc.numTemporalLayers = (hevcSequenceHeader[21] >> 3) & 0x07;
hevc.temporalIdNested = (hevcSequenceHeader[21] >> 2) & 0x01;
hevc.lengthSizeMinusOne = hevcSequenceHeader[21] & 0x03;
let numOfArrays = hevcSequenceHeader[22];
let p = hevcSequenceHeader.slice(23);
for (let i = 0; i < numOfArrays; i++) {
if (p.length < 3) {
brak;
}
let nalutype = p[0];
let n = (p[1]) << 8 | p[2];
// console.log(nalutype, n);
p = p.slice(3);
for (let j = 0; j < n; j++) {
if (p.length < 2) {
break;
}
k = (p[0] << 8) | p[1];
// console.log('k', k);
if (p.length < 2 + k) {
break;
}
p = p.slice(2);
if (nalutype == 33) {
//SPS
let sps = Buffer.alloc(k);
p.copy(sps, 0, 0, k);
// console.log(sps, sps.length);
hevc.psps = HEVCParseSPS(sps, hevc);
info.profile = hevc.general_profile_idc;
info.level = hevc.general_level_idc / 30.0;
info.width = hevc.psps.pic_width_in_luma_samples - (hevc.psps.conf_win_left_offset + hevc.psps.conf_win_right_offset);
info.height = hevc.psps.pic_height_in_luma_samples - (hevc.psps.conf_win_top_offset + hevc.psps.conf_win_bottom_offset);
}
p = p.slice(k);
}
}
} while (0);
return info;
}
function readAVCSpecificConfig(avcSequenceHeader) {
let codec_id = avcSequenceHeader[0] & 0x0f;
if (codec_id == 7) {
return readH264SpecificConfig(avcSequenceHeader);
} else if (codec_id == 12) {
return readHEVCSpecificConfig(avcSequenceHeader);
}
}
function getAVCProfileName(info) {
switch (info.profile) {
case 1:
return "Main";
case 2:
return "Main 10";
case 3:
return "Main Still Picture";
case 66:
return "Baseline";
case 77:
return "Main";
case 100:
return "High";
default:
return "";
}
}
module.exports = {
AUDIO_SOUND_RATE,
AUDIO_CODEC_NAME,
VIDEO_CODEC_NAME,
readAACSpecificConfig,
getAACProfileName,
readAVCSpecificConfig,
getAVCProfileName,
};
1
https://gitee.com/csjiabin/Node-Media-Server.git
git@gitee.com:csjiabin/Node-Media-Server.git
csjiabin
Node-Media-Server
Node-Media-Server
master

搜索帮助