android13/hardware/rockchip/camera/tools/gen_sensor_graph_setting.py

329 lines
14 KiB
Python
Executable File

#!/usr/bin/env python
import sys
import xml.etree.ElementTree as ET
import xml.dom.minidom as minidom
import os
import datetime
from optparse import OptionParser
def cal_crop(source, target):
ratio_src = source['W'] * 1.0 / source['H']
ratio_dst = target['W'] * 1.0 / target['H']
ret = {}
if ratio_src == ratio_dst:
height = source['H']
width = source['W']
elif ratio_src > ratio_dst:
height = source['H']
width = int(height * ratio_dst)
else:
width = source['W']
height = int(width / ratio_dst)
height = height - height % 2
return {'W': width, 'H': height}
def cal_reso(reso, sp_reso, mp_reso):
ret = {}
""" sp_reso always smaller than mp_reso"""
if mp_reso:
ret['sensor'] = reso[0] if len(reso) == 1 or mp_reso['W'] > reso[1]['W'] else reso[1]
elif sp_reso:
ret['sensor'] = reso[0] if len(reso) == 1 or sp_reso['W'] > reso[1]['W'] else reso[1]
else:
raise Exception('Mp and SP both are NULL')
if mp_reso:
ret['mp_crop'] = cal_crop(ret['sensor'], mp_reso)
if sp_reso:
ret['sp_crop'] = cal_crop(ret['sensor'], sp_reso)
return ret
def gen_settings(root, key, sensor, sp_crop, sp, mp_crop, mp, mode):
""" for one stream, the sp and sp_crop are None """
active_outputs = 2 if sp else 1
setting = ET.SubElement(root, 'settings',
attrib={'key': str(key),
'id' : str(1),
'fps': str(sensor['FPS']),
'active_outputs': str(active_outputs)})
video = ET.SubElement(setting, 'video',
attrib={'width': str(mp['W']),
'height': str(mp['H']),
'stream_id': str(1),
'format': 'NV12',
'peer': 'output'})
v_crp = ET.SubElement(video, 'pcrp',
attrib={'width': str(mp_crop['W']),
'height': str(mp_crop['H'])})
v_rsz = ET.SubElement(video, 'prsz',
attrib={'width': str(mp['W']),
'height': str(mp['H'])})
if sp and sp_crop:
preview = ET.SubElement(setting, 'preview',
attrib={'width': str(sp['W']),
'height': str(sp['H']),
'stream_id': str(1),
'format': 'NV12',
'peer': 'output'})
p_crp = ET.SubElement(preview, 'pcrp',
attrib={'width': str(sp_crop['W']),
'height': str(sp_crop['H'])})
p_rsz = ET.SubElement(preview, 'prsz',
attrib={'width': str(sp['W']),
'height': str(sp['H'])})
else:
preview = ET.SubElement(setting, 'preview', attrib={'enabled': str(0)})
still = ET.SubElement(setting, 'still', attrib={'enabled': str(0)})
et_sensor = ET.SubElement(setting, 'sensor',
attrib={'stream_id': str(1),
'vflip': str(0),
'hflip': str(0),
'mode_id': str(sensor['W']) + 'x' + str(sensor['H']),
'analogue_gain': str(100),
'exposure': str(500)})
et_sensor_port = ET.SubElement(et_sensor, 'port_0',
attrib={'type': 'port',
'width': str(sensor['W']),
'height': str(sensor['H']),
'format': mode['sensor_fmt']})
csi = ET.SubElement(setting, 'csi_be_soc')
csi_output = ET.SubElement(csi, 'output',
attrib={'width': str(sensor['W']),
'height': str(sensor['H']),
'format': mode['sensor_fmt']})
imgu = ET.SubElement(setting, 'imgu', attrib={'stream_id': str(1)})
imgu_input = ET.SubElement(imgu, 'input',
attrib={'width': str(sensor['W']),
'height': str(sensor['H']),
'format': mode['sensor_fmt']})
iac = ET.SubElement(imgu_input, 'iac',
attrib={'width': str(sensor['W']),
'height': str(sensor['H'])})
imgu_output = ET.SubElement(imgu, 'output',
attrib={'width': str(sensor['W']),
'height': str(sensor['H']),
'format': 'NV16',
'pipe_output_id': str(0)})
ism = ET.SubElement(imgu_output, 'ism',
attrib={'width': str(sensor['W']),
'height': str(sensor['H'])})
def gen_sensor_modes(root, reso, mode):
et_mode = ET.SubElement(root, 'sensor_modes',
attrib={'sensor_name': mode['name'],
'i2c_address': mode['i2c_address'],
'csi_port': '0',
'metadata': '0',
'bayer_order': mode['bayer_order']})
et_bpp = ET.SubElement(et_mode, 'available_bit_per_pixel')
et_bpp_value = ET.SubElement(et_bpp, 'bpp', attrib={'value': str(mode['bpp'])})
et_pll = ET.SubElement(et_mode, 'pll_configs')
et_pll_item = ET.SubElement(et_pll, 'pll_config',
attrib={'id': '0',
'pixel_rate': str(mode['pixel_rate']),
'pixel_rate_csi': str(mode['pixel_rate']),
'bpp': str(mode['bpp'])})
i = 0
item_max = reso[0]
for item in reso:
et_item = ET.SubElement(et_mode, 'sensor_mode',
attrib={'name': str(item['W']) + 'x' + str(item['H']),
'id': str(i),
'width': str(item['W']),
'height': str(item['H']),
'fps': str(item['FPS']),
'csi_port': '0',
'scaler_pad': '1',
'target': '0',
'min_fll': '0',
'min_llp': '0'})
i = i + 1
et_pixel = ET.SubElement(et_item, 'pixel_array')
et_pixel_input = ET.SubElement(et_pixel, 'input',
attrib={'width': str(item_max['W']),
'height': str(item_max['H']),
'left': '0',
'top': '0'})
et_pixel_output = ET.SubElement(et_pixel, 'output',
attrib={'width': str(item['W']),
'height': str(item['H']),
'left': '0',
'top': '0'})
et_binner = ET.SubElement(et_item, 'binner',
attrib={'h_factor': str(item['binner_h']),
'v_factor': str(item['binner_w'])})
# binner input === max reso ?
et_binner_input = ET.SubElement(et_binner, 'input',
attrib={'width': str(item_max['W']),
'height': str(item_max['H']),
'left': '0',
'top': '0'})
et_binner_output = ET.SubElement(et_binner, 'output',
attrib={'width': str(item['W']),
'height': str(item['H']),
'left': '0',
'top': '0'})
def generate_xml(fn, reso, mode, target):
sp_max = {'W': 1920, 'H': 1080}
root = ET.Element('graph_settings')
gen_sensor_modes(root, reso, mode)
key = 7000
for mp in target:
for sp in target:
if sp['W'] > mp['W'] or sp['W'] > sp_max['W']:
continue
ret = cal_reso(reso, sp, mp)
gen_settings(root, key, ret['sensor'], ret['sp_crop'], sp, ret['mp_crop'], mp, mode)
key = key + 1
key = 8000
for mp in target:
ret = cal_reso(reso, None, mp)
gen_settings(root, key, ret['sensor'], None, None, ret['mp_crop'], mp, mode)
key = key + 1
# ET.dump(root)
xml = minidom.parseString(ET.tostring(root)).toprettyxml(indent=' ')
with open(fn, 'w') as f:
f.write(xml)
def get_user_paras():
try:
opt = OptionParser()
opt.add_option('--name',
dest="name",
type=str,
default="none",
help="sensor name which could be got from sys/class/video4linux/v4l-subdev2/name or cmd: media-ctl -p")
opt.add_option('--i2c_address',
dest="i2c_address",
type=str,
default="0-0000",
help="sensor i2c_address which could be got from sys/class/video4linux/v4l-subdev2/name or cmd: media-ctl -p")
opt.add_option('--bayer_order',
dest="bayer_order",
type=str,
default="BGGR",
help="sensor bayer_order which could be got from cmd: media-ctl -p")
opt.add_option('--sensor_fmt',
dest="sensor_fmt",
type=str,
default="BG10",
help="sensor fmt which could be got from cmd: media-ctl -p")
opt.add_option('--bpp',
dest="bpp",
type=int,
default=10,
help="sensor bpp")
opt.add_option('--pixel_rate',
dest="pixel_rate",
type=int,
default=180000000,
help="sensor pixel_rate ")
opt.add_option('--width',
dest="width",
type=int,
default=0,
help="sensor output width")
opt.add_option('--height',
dest="height",
type=int,
default=0,
help="sensor output height")
opt.add_option('--binner_width',
dest="binner_width",
type=int,
default=0,
help="sensor output binner width")
opt.add_option('--binner_height',
dest="binner_height",
type=int,
default=0,
help="sensor output binner height")
(options, args) = opt.parse_args()
is_valid_paras = True
error_messages = ["Config Err:"]
if not options.name:
error_messages.append("--name must be set;")
is_valid_paras = False
if not options.width:
error_messages.append("--width must be set;")
is_valid_paras = False
if not options.height:
error_messages.append("--height must be set;")
error_messages.append("if you do not clear how to config all the options, just config name, width, height")
is_valid_paras = False
if is_valid_paras:
return options
else:
for error_message in error_messages:
print(error_message)
opt.print_help()
return None
except Exception as ex:
print("exception :{0}".format(str(ex)))
return None
def main(argv):
opts = get_user_paras()
if not opts:
return None
else:
reso = [{'W': opts.width, 'H': opts.height, 'FPS': 30, 'binner_h': 1, 'binner_w': 1}]
if opts.binner_width and opts.binner_height:
reso.append({'W': opts.binner_width, 'H': opts.binner_height, 'FPS': 60,
'binner_h': 2, 'binner_w': 2})
mode = {'name': opts.name,
'i2c_address': opts.i2c_address,
'bayer_order': opts.bayer_order,
'bpp': opts.bpp,
'pixel_rate': opts.pixel_rate,
'sensor_fmt': opts.sensor_fmt}
settings = [{'W': 1920, 'H': 1080},
{'W': 1280, 'H': 960},
{'W': 1280, 'H': 720},
{'W': 800, 'H': 600},
{'W': 640, 'H': 480},
{'W': 352, 'H': 288},
{'W': 320, 'H': 240},
{'W': 176, 'H': 144}]
target = []
for s in settings:
if opts.width > s["W"] and opts.height > s["H"]:
target.append(s)
target.insert(0, {'W': opts.width, 'H': opts.height})
if opts.binner_width and opts.binner_height:
binners = {'W': opts.binner_width, 'H': opts.binner_height}
if binners not in target:
target.insert(0, binners)
target.sort(reverse=True)
print reso
print mode
print target
generate_xml('./graph_settings_' + opts.name + '.xml', reso, mode, target)
print "generate " + './graph_settings_' + opts.name + '.xml'
if __name__ == '__main__':
main(sys.argv)