Skip to content

Instantly share code, notes, and snippets.

@malthejorgensen
Last active February 9, 2022 08:48
Show Gist options
  • Save malthejorgensen/7edce7a944af32a3fe47162c8ce2f976 to your computer and use it in GitHub Desktop.
Save malthejorgensen/7edce7a944af32a3fe47162c8ce2f976 to your computer and use it in GitHub Desktop.
H.264 Codec String Parser (video, profile, level) - February 2022
// FROM: https://gist.github.com/eladkarako/119e91525d34db9f61cca23b18fd62a0#file-h264_codec_string_parser-js
//
// Changes:
// 1. Change to work on uppercase strings
// 2. Allow passing codec string as command line argument, e.g. `node h264_codec_string_parser.js avc1.42C03E`
// 3. Parse `constraint_set_flags` as well
//
ISOAVC_MAP = {
"avc1": "H.264"
,"avc2": "H.264"
,"svc1": "Scalable Video Coding"
,"mvc1": "Multiview Video Coding"
,"mvc2": "Multiview Video Coding"
};
PROFILE = { //https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles
"0": "No" // 0 - *** when profile=RCDO and level=0 - "RCDO" - RCDO bitstream MUST obey to all the constraints of the Baseline profile
,"42": "Baseline" // 66 in-decimal
,"4d": "Main" // 77 in-decimal
,"58": "Extended" // 88 in-decimal
,"64": "High" //100 in-decimal
,"6e": "High 10" //110 in-decimal
,"7a": "High 4:2:2" //122 in-decimal
,"f4": "High 4:4:4" //244 in-decimal
,"2c": "CAVLC 4:4:4" // 44 in-decimal
//profiles for SVC - Scalable Video Coding extension to H.264
,"53": "Scalable Baseline" // 83 in-decimal
,"56": "Scalable High" // 86 in-decimal
//profiles for MVC - Multiview Video Coding extension to H.264
,"80": "Stereo High" // 128 in-decimal
,"76": "Multiview High" // 118 in-decimal
,"8a": "Multiview Depth High" // 138 in-decimal
};
function avcoti_to_str(s){
var REGEX = /([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i
,matches
,profile_idc
,constraint_set_flags
,level_idc
;
if(false === REGEX.test(s)) throw new Error("error: please provide a 3-bytes hex-sequence for example: 42001e");
matches = s.match(REGEX);
matches.shift(); //kills first one (regex matchs entire string)
profile_idc = matches[0];
var orig_profile_idc = profile_idc;
profile_idc = PROFILE[profile_idc];
profile_idc = "string" === typeof profile_idc ? profile_idc : "Unknown"; //explicit fix.
// FROM: https://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/gst/qtdemux/qtdemux.c?id=ccef64be3996e6bb47a974cf64c0fa311c463700
// avc_profile_idc_to_string()
constraint_set_flags = parseInt(matches[1], 16);
console.log(matches[1]);
console.log(constraint_set_flags);
var csf1 = (constraint_set_flags & 0x40) >> 6;
var csf3 = (constraint_set_flags & 0x10) >> 4;
console.log(csf1);
console.log(csf3);
if (orig_profile_idc === '42' && csf1) {
// 66 in decimal
constraint_set_flags = ' Constrained';
} else if (orig_profile_idc === '6e' && csf3) {
// 110 in decimal
constraint_set_flags = ' Intra';
} else if (orig_profile_idc === '7a' && csf3) {
// 122 in decimal
constraint_set_flags = ' Intra';
} else if (orig_profile_idc === 'f4' && csf3) {
// 244 in decimal
constraint_set_flags = ' Intra';
} else if (orig_profile_idc === '2c') {
// 44 in decimal
constraint_set_flags = ' Intra';
} else {
constraint_set_flags = '';
}
level_idc = matches[2];
level_idc = Number.parseInt(level_idc, 16); //will give something like 30 (integer thirty)
level_idc = String(level_idc).split("").join(".") //will give something like "3.0"
return "\"" + profile_idc + constraint_set_flags + "\" Profile, Level " + level_idc;
}
function h264avc_to_string(s){
s = s.toLowerCase();
var REGEX = /(avc1|avc2|svc1|mvc1|mvc2)\.([0-9a-f]{6})/i
,matches
,avc_codec
;
if(false === REGEX.test("avc1.42001e")) throw new Error("Codec string is not formatted according to H.264/AVC standards for example avc1.42001e (maybe an iOS friendly version...)");
matches = s.match(REGEX);
matches.shift(); //first one is the entire-string.
avc_codec = ISOAVC_MAP[ matches[0] ];
avc_codec = "string" === typeof avc_codec ? avc_codec : "Unknown"; //explicit fix
return avc_codec + " Video (" + avcoti_to_str( matches[1] ) + ")";
}
//Try It...
//more examples in https://tools.ietf.org/id/draft-gellens-mime-bucket-bis-02.html#sec-5
// console.log(
// h264avc_to_string("avc1.42001e")
// ,h264avc_to_string("avc1.640029")
// )
console.log(process.argv[2]);
console.log(h264avc_to_string(process.argv[2]));
/************************************
* H.264-Codec Profile/Level Parser *
* /Elad Karako. August 2017 *
* /Malthe Jørgensen. February 2022 *
************************************/
/*
References:
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html
https://tools.ietf.org/html/draft-pantos-http-live-streaming-23
https://tools.ietf.org/html/rfc6381
https://tools.ietf.org/html/rfc6381#section-3.6
https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC
https://en.wikipedia.org/wiki/H.264#Levels
https://tools.ietf.org/html/draft-ietf-avt-rtp-h264-rcdo-08
http://h264bitstream.sourceforge.net/doxygen/0.1.5/structsps__t.html
https://www.iana.org/assignments/media-types/video/H264-SVC
https://tools.ietf.org/html/rfc6381#ref-AVC-Formats
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment