1# Copyright 2024 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Combine separate feature combinations results (.pb) into one.""" 15 16import os 17import re 18import sys 19 20from google.protobuf import text_format 21import feature_combination_info_pb2 22 23_DEBUG = False 24 25 26def main(): 27 """Combine the feature combination verification tests into a single file. 28 29 Command line arguments: 30 pb_file_0: the relative path of the first pb file (camera 0, for example) 31 to be combined 32 pb_file_1: the relative path of the scond pb file (camera 1, for example) 33 to be combined 34 """ 35 # Validate input file paths 36 if len(sys.argv) != 3: 37 raise ValueError(f'{sys.argv[0]} pb_file_0 pb_file_1') 38 for file_path in sys.argv[1:]: 39 if not os.path.isfile(file_path): 40 raise ValueError(f'{file_path} does not exist') 41 42 # Combine the input proto files 43 pb_file_0_name = sys.argv[1] 44 pb_file_1_name = sys.argv[2] 45 with open(pb_file_0_name, 'rb') as file_0: 46 msg_0 = feature_combination_info_pb2.FeatureCombinationDatabase() 47 msg_0.ParseFromString(file_0.read()) 48 with open(pb_file_1_name, 'rb') as file_1: 49 msg_1 = feature_combination_info_pb2.FeatureCombinationDatabase() 50 msg_1.ParseFromString(file_1.read()) 51 52 # Validate protos in the 2 input files 53 if msg_0.build_fingerprint != msg_1.build_fingerprint: 54 raise ValueError('Build fingerprint not matching:' 55 f'{msg_0.build_fingerprint} vs ' 56 f'{msg_1.build_fingerprint}') 57 if len(msg_0.feature_combination_for_camera) != 1: 58 raise ValueError(f'{msg_0.build_fingerprint} ' 59 'must contain 1 camera, but contains ' 60 f'{len(msg_0.feature_combination_for_camera)}') 61 if len(msg_1.feature_combination_for_camera) != 1: 62 raise ValueError(f'{msg_1.build_fingerprint} ' 63 'must contain 1 camera, but contains ' 64 f'{len(msg_1.feature_combination_for_camera)}') 65 if (msg_0.feature_combination_for_camera[0].camera_id == 66 msg_1.feature_combination_for_camera[0].camera_id): 67 raise ValueError(f'proto files have duplicate camera id: ' 68 f'{msg_0.feature_combination_for_camera[0].camera_id}') 69 70 if msg_1.timestamp_in_sec > msg_0.timestamp_in_sec: 71 msg_0.timestamp_in_sec = msg_1.timestamp_in_sec 72 73 msg_0.feature_combination_for_camera.append( 74 msg_1.feature_combination_for_camera[0] 75 ) 76 77 build_id = re.sub(r'[/:]', '_', msg_0.build_fingerprint) 78 file_name = f'{build_id}.pb' 79 with open(file_name, 'wb') as f: 80 f.write(msg_0.SerializeToString()) 81 82 if _DEBUG: 83 txtpb_file_name = f'{build_id}.txtpb' 84 with open(txtpb_file_name, 'w') as tf: 85 tf.write(text_format.MessageToString(msg_0)) 86 87if __name__ == '__main__': 88 main() 89