+const MUXER_OPTS: &[NAOptionDefinition] = &[
+ NAOptionDefinition {
+ name: FORCE_STREAM_TAG_OPTION, description: FORCE_STREAM_TAG_OPTION_DESC,
+ opt_type: NAOptionDefinitionType::String(None) },
+];
+
+fn parse_tag(src: &[u8]) -> Option<ForcedTag> {
+ if !src.starts_with(b"stream") {
+ return None;
+ }
+ let mut pos = 6;
+ let mut stream = 0;
+ while pos < src.len() && src[pos].is_ascii_digit() {
+ stream = stream * 4 + u32::from(src[pos] - b'0');
+ if stream > (1 << 24) {
+ return None;
+ }
+ pos += 1;
+ }
+ if src.len() - pos != 3 + 2 * 4 || !src[pos..].starts_with(b"tag") {
+ return None;
+ }
+ pos += 3;
+ let mut tag = [0; 4];
+ for (sym, pair) in tag.iter_mut().zip(src[pos..].chunks_exact(2)) {
+ let c0 = match pair[0] {
+ b'0'..=b'9' => pair[0] - b'0',
+ b'a'..=b'f' => pair[0] - b'a' + 10,
+ b'A'..=b'F' => pair[0] - b'A' + 10,
+ _ => return None,
+ };
+ let c1 = match pair[1] {
+ b'0'..=b'9' => pair[1] - b'0',
+ b'a'..=b'f' => pair[1] - b'a' + 10,
+ b'A'..=b'F' => pair[1] - b'A' + 10,
+ _ => return None,
+ };
+ *sym = (c0 << 4) | c1;
+ }
+ Some(ForcedTag{ stream, tag })
+}
+