From a5672f1e2dcb02f6353ac827585c57ef95800f83 Mon Sep 17 00:00:00 2001 From: Romain Bouqueau Date: Thu, 11 May 2023 15:37:40 -0400 Subject: [PATCH] chunked content script - see https://github.com/cta-wave/Test-Content/issues/41 --- README.md | 4 ++ chunked/gen.sh | 45 ++++++++++++++++++ chunked/isobmff_chunker.py | 96 ++++++++++++++++++++++++++++++++++++++ chunked/stream.mpd | 20 ++++++++ 4 files changed, 165 insertions(+) create mode 100755 chunked/gen.sh create mode 100755 chunked/isobmff_chunker.py create mode 100644 chunked/stream.mpd diff --git a/README.md b/README.md index f46e616..62b49cb 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,10 @@ cd .. * Inspect the [input list](switching_sets_single_track.csv). * Run ```./run-all.py```, and grab a cup of tea (or coffee). +### Switching Set X1 (ss1) + +The generation of current [Switching Set X1 (ss1)](https://github.com/cta-wave/Test-Content-Generation/issues/60) is done by executing ```ss1/gen.sh``` + ### Splicing tests The generation of current [splicing tests](https://github.com/cta-wave/Test-Content/issues/19) is done by executing ```splice/gen.sh ```. diff --git a/chunked/gen.sh b/chunked/gen.sh new file mode 100755 index 0000000..16b089f --- /dev/null +++ b/chunked/gen.sh @@ -0,0 +1,45 @@ +#!/usr/bin/bash +set -eux + +export BATCH="2023-04-28" + +export MPD=stream.mpd +export INPUT_STREAM_ID=t16 +export INPUT_DIR=output/cfhd_sets/12.5_25_50/$INPUT_STREAM_ID/$BATCH/ +export OUTPUT_STREAM_ID=chunked +export OUTPUT=chunked +export OUTPUT_DIR=output/cfhd_sets/12.5_25_50/$OUTPUT_STREAM_ID/$BATCH/ + + +# clean copy of input +mkdir -p $OUTPUT_DIR +rm -rf $OUTPUT_DIR/* +cp -r $INPUT_DIR/* $OUTPUT_DIR/ + + +####################################################### +# chunking +pushd $OUTPUT_DIR/1 + +## styp generation: take it from the first segment +head -c12 0.m4s > styp + +## chunk segments +for f in `ls *.m4s`; do + $(dirname $0)/isobmff_chunker.py 5 `basename $f .m4s` + rm $f +done + +rm styp + +## modify MPD +cp $(dirname $0)/stream.mpd ../stream.mpd + +popd +####################################################### + +# zip +pushd output +rm cfhd_sets/12.5_25_50/$OUTPUT_STREAM_ID/$BATCH/$INPUT_STREAM_ID.zip +zip -r cfhd_sets/12.5_25_50/$OUTPUT_STREAM_ID/$BATCH/$OUTPUT_STREAM_ID.zip cfhd_sets/12.5_25_50/$OUTPUT_STREAM_ID/$BATCH/* +popd diff --git a/chunked/isobmff_chunker.py b/chunked/isobmff_chunker.py new file mode 100755 index 0000000..5018817 --- /dev/null +++ b/chunked/isobmff_chunker.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +import sys +import struct + +def read_bytes(fobj, bytes): + data = fobj.read(bytes) + if len(data) != bytes: + raise RuntimeError('Not enough data: requested %d, read %d' % (bytes, len(data))) + return data + +def read_ulong(fobj): + return struct.unpack('>L', read_bytes(fobj, 4))[0] + +def read_ulonglong(fobj): + return struct.unpack('>Q', read_bytes(fobj, 8))[0] + +def read_fourcc(fobj): + return read_bytes(fobj, 4) + +def read_atom(fobj): + pos = fobj.tell() + size = read_ulong(fobj) + type = read_fourcc(fobj) + + if size == 1: + size = read_ulonglong(fobj) + elif size == 0: + fobj.seek(0, 2) + size = fobj.tell() - pos + fobj.seek(pos + 8) + + return size, type + +def isobmff_read_topboxes(f): + size = 0 + f.seek(0) + pos = 0 + f.seek(0, 2) + end = f.tell() + f.seek(0) + + result = [] + while 1: + if pos + size < end: + pos += size + f.seek(pos) + a = read_atom(f) + result.append(a) + size = a[0] + else: + break + + return result + +if __name__ == "__main__": + if len(sys.argv) != 3: + print(f"Usage: {sys.argv[0]} num_frag_per_chunk input_file") + sys.exit(1) + + num_frag_per_chunk = int(sys.argv[1]) + input_file = sys.argv[2] + + # open and parse + fi = open(input_file + ".m4s", 'rb') + boxes = isobmff_read_topboxes(fi) + fi.seek(0) + + # iterate on boxes + i_moof = -1 + i_chunk = -1 + global fo + fo = None + for b in boxes: + bytes = fi.read(b[0]); + if b[1] == b'styp': + continue + + if b[1] == b'moof': + i_moof += 1 + + if i_moof % num_frag_per_chunk == 0 and i_moof / num_frag_per_chunk != i_chunk: + # new chunk + if fo is not None: + fo.close() + i_chunk += 1 + fo = open(input_file + "_" + str(i_chunk) + ".m4s", 'wb') + styp = open("styp", 'rb') + fo.write(styp.read(12)) + styp.close(); + + fo.write(bytes) + + # close + fo.close() + fi.close() + sys.exit(0) diff --git a/chunked/stream.mpd b/chunked/stream.mpd new file mode 100644 index 0000000..516e7af --- /dev/null +++ b/chunked/stream.mpd @@ -0,0 +1,20 @@ + + + + + croatia, 1920x1080, 25.0fps, cfhd, Test Vector 16 + croatia_L1_1920x1080@25_30 version 4 (2023-02-13) + © Croatia (2019), credited to EBU, used and licensed under Creative Commons Attribution 4.0 International (CC BY 4.0) (https://creativecommons.org/licenses/by/4.0/) by the Consumer Technology Association (CTA)® / annotated, encoded and compressed from original. + + + + + + + + + + + + + \ No newline at end of file