From d66400f6e0cb2ce566a0e536acc66561ab2e8959 Mon Sep 17 00:00:00 2001 From: knj Date: Mon, 29 Aug 2022 14:53:58 +0200 Subject: [PATCH] add cut_bs.py script and correct path to it --- scripts/cut_bs.py | 122 ++++++++++++++++++++++++ scripts/pyivastest/IvasScriptsCommon.py | 4 +- 2 files changed, 124 insertions(+), 2 deletions(-) create mode 100755 scripts/cut_bs.py diff --git a/scripts/cut_bs.py b/scripts/cut_bs.py new file mode 100755 index 0000000000..261a66bc9f --- /dev/null +++ b/scripts/cut_bs.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 + +""" + (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import struct +import argparse +import os.path +import sys + +SID_BITS = {35, 48, 88, 100} +SYNC_WORDS = {b"!k", b" k"} + + +def cut_bs(fp, fp_out, start_frame=0, start_with_sid=False): + # cut until start frame + fr_cnt = 0 + cut_cnt = 0 + for cur_frame in range(start_frame): + sync_word = fp.read(2) + if sync_word == b"": + return (fr_cnt, cut_cnt) + if sync_word not in SYNC_WORDS: + raise ValueError("Bad Sync word!") + n_bits = struct.unpack("h", fp.read(2))[0] + fp.read(n_bits * 2) + fr_cnt += 1 + cut_cnt += 1 + if start_with_sid: + found = False + while not found: + sync_word = fp.read(2) + if sync_word == b"": + return (fr_cnt, cut_cnt) + if sync_word not in SYNC_WORDS: + raise ValueError("Bad Sync word!") + n_bits_bs = fp.read(2) + n_bits = struct.unpack("h", n_bits_bs)[0] + if n_bits in SID_BITS: + found = True + fp_out.write(sync_word) + fp_out.write(n_bits_bs) + fp_out.write(fp.read(n_bits * 2)) + else: + fp.read(n_bits * 2) + cut_cnt += 1 + fr_cnt += 1 + + # transfer remaining frames + while True: + sync_word = fp.read(2) + if sync_word == b"": + break + if sync_word not in SYNC_WORDS: + raise ValueError("Bad Sync word!") + n_bits_bs = fp.read(2) + n_bits = struct.unpack("h", n_bits_bs)[0] + fp_out.write(sync_word) + fp_out.write(n_bits_bs) + fp_out.write(fp.read(n_bits * 2)) + fr_cnt += 1 + + return (fr_cnt, cut_cnt) + + +if __name__ == "__main__": + my_parser = argparse.ArgumentParser( + description="Cut frames from the beginning of a G.192 bit stream file" + ) + my_parser.add_argument( + "--sid", "-s", help="Cut until the first SID frame", action="store_true" + ) + my_parser.add_argument( + "--frame", "-f", type=int, help="Number of frames to cut.", default=0 + ) + my_parser.add_argument("bs_in", type=str, help="G.192 bit stream file name to cut") + my_parser.add_argument("bs_out", type=str, help="Cut G.192 bit stream file name") + my_args = my_parser.parse_args() + if not os.path.exists(os.path.realpath(my_args.bs_in)): + print(f"\nInput file {my_args.bs_in} does not exist!") + sys.exit(-1) + if not os.path.exists(os.path.realpath(my_args.bs_out)): + print(f"\nOutput file {my_args.bs_out} does not exist, creating it!") + else: + print(f"\nOutput file {my_args.bs_out} does exist, overwriting it!") + + with open(my_args.bs_in, "rb") as fp_in: + with open(my_args.bs_out, "wb") as fp_out: + fr_cnt, cut_cnt = cut_bs( + fp_in, fp_out, start_frame=my_args.frame, start_with_sid=my_args.sid + ) + + if my_args.sid and (fr_cnt == cut_cnt): + print("Warning! No SID frame found in bitstream!") + print(f"Cut {cut_cnt} of {fr_cnt} frames from {my_args.bs_in}") diff --git a/scripts/pyivastest/IvasScriptsCommon.py b/scripts/pyivastest/IvasScriptsCommon.py index 7e84efc215..45631566e9 100644 --- a/scripts/pyivastest/IvasScriptsCommon.py +++ b/scripts/pyivastest/IvasScriptsCommon.py @@ -596,7 +596,7 @@ def runner_setup(runner, args): if args["sidstart"]: sidstart_cmd = [ - os.path.join(constants.SCRIPTS_BASE_DIR, "tools", "cut_bs.py"), + os.path.join(constants.SCRIPTS_BASE_DIR, "cut_bs.py"), "--sid", "{in_file}", "{out_file}", @@ -686,7 +686,7 @@ def analyzer_setup(analyzer, args): if args["sidstart"]: sidstart_cmd = [ - os.path.join(constants.SCRIPTS_BASE_DIR, "tools", "cut_bs.py"), + os.path.join(constants.SCRIPTS_BASE_DIR, "cut_bs.py"), "--sid", "{in_file}", "{out_file}", -- GitLab