结果类型(result_type)

本文详细介绍了Struts2框架中的各种结果类型,包括dispatcher、redirect、chain、redirectAction等,并解释了它们的工作原理及使用场景。通过具体的配置示例帮助开发者更好地理解和应用这些结果类型。
结果类型(result_type):默认为dispatcher,运用服务器跳转,跳转到结果页面, redirect 跳转到视图(JSP) 、chain forward 到action 、redirctAction 客户端跳转,跳转到Action
//index.jsp
result 类型:
<br />
<ol>
<li> <!-- 地址框显示action -->
<a href="r/r1">dispatcher</a> 运用服务器跳转,跳转到结果页面(体现在struts.xml配置中)
</li>
<li> <!-- 地址框显示JSP -->
<a href="r/r2">redirect</a> 跳转到视图(JSP)
</li>
<li> <!-- 地址框显示action -->
<a href="r/r3">chain</a> forward 到action
</li>
<li> <!-- 地址框显示JSP -->
<a href="r/r4">redirctAction</a> 客户端跳转,跳转到Action
</li>
<li>
freemarker
</li>
<li>
httpheader 发http头信息
</li>
<li>
stream 下载
</li>
<li>
velocity
</li>
<li>
xslt 与xml相关的语言
</li>
<li>
plaintext 显示页面源码,用于教学网站
</li>
<li>
tiles 将页面分块
</li>
</ol>
<br>
//struts.xml
<constant name="struts.devMode" value="true" />
<package name="resultTypes" namespace="/r" extends="struts-default">
<action name="r1"><!-- 地址框显示action -->
<result type="dispatcher">/r1.jsp</result> <!-- dispatcher只能跳转到页面,不能是action -->
</action>

<action name="r2"> <!-- 地址框显示JSP -->
<result type="redirect">/r2.jsp</result> <!-- 表示跳转到r2.jsp -->
</action>

<action name="r3"><!-- 地址框显示本action -->
<result type="chain">r1</result> <!-- 跳转到r1 action -->
</action>

<action name="r4">
<result type="redirectAction">r2</result> <!-- 地址框显示目的JSP -->
</action>
</package>
给我详细但是又通俗的讲一下: AMS设计文档 版本/状态 作者 起止日期 描述 V0.1/草稿 杨威 2018-2-26 创建文档 V0.2 许楚萍 2019.7.9 框架更新,新增结果后处理 1. 引言 AMS(Algorithmic Management System)旨在对IPC上运行的音视频算法进行统一管理。在原有libSmart的基础上,主要做了如下改进: AMS模块完全由数据驱动,每个模块可看成独立的数据加工者,消耗数据并产生新的数据 拆解Common部分成各个独立的模块,使其能独立参与编译(有依赖关系的除外) 与芯片底层的数据交互(如帧、硬件帧差)使用环作为缓存 与芯片或机型相关的配置从AMS代码中抽离成config文件,减少AMS的重编译和发布次数 ​ 2. 架构和数据流 AMS(Algorithmic Management System)旨在对IPC上运行的音视频算法进行统一管理。 2.1 文件组织 对AMS进行文件划分如下: 音频侦测与识别(ADR,audio detection and recognition) 音频质量改善(AQI,audio quality improvement) 视频侦测与识别(VDR,video detection and recognition) 视频质量改善(VQI,video quality improvement) 每个模块下辖多个子模块,具体如下图所示: 每个子模块的文件夹下包含该模块的头文件、源文件和Makefile。 AMS使用repo进行代码版本管理(repo用于方便管理多个git库而开发的python脚本)。AMS的库划分如下所示: ams库:ams文件夹下除/src/vdr、/src/adr、/src/vqi之外的所有文件,主要包含ams框架和pc_dbug /vdr/basic_processing库:/ams/src/vdr/basic_processing /vdr/behavior库:/ams/src/vdr/behavior /vdr/detection库:/ams/src/vdr/detection /vdr/functional库:/ams/src/vdr/functional /vdr/recognition库:/ams/src/vdr/recognition /vdr/TENN库:/ams/src/vdr/TENN /vdr/utils库:/ams/src/vdr/utils /adr/aframe库:/ams/src/adr/aframe /adr/functional库:/ams/src/adr/functional /adr/recognition库:/ams/src/adr/recognition /adr/utils库:/ams/src/adr/utils 所有库都可以使用git进行独立的版本控制。 2.2 数据流 VDR包含的算法及数据流走向如下图所示: 整个VDR可能由一种或多种来自于芯片底层的 数据源驱动 。当底层的这些数据有更新的时候,会通过某种方式通知AMS,并将新的数据传给AMS,算法因此产生一条消耗处理该数据的流水线,并相应的产生一次结果。 2.2.1 数据源的接收和分发 AMS需要接收芯片底层的源数据,然后分发给内部算法进行处理。在设计方面,需要考虑以下几点(以接收视频帧数据为例): 在有新帧的时候,才进行收帧和分发处理的动作 分发处理不能对收帧线程产生阻塞 避免重复拷贝 基于以上考虑,我们采用注册回调机制、设计缓存数据环来对收发帧数据进行管理。要点如下(参照下图): ams 向数据采集模块(avdc)注册回调函数:vframe_recv_cb avdc 在获取到新帧的时候,调用 vframe_recv_cb 函数,该回调函数主要完成以下任务: 取出环上空余位置(tail),如果没有空余位置,则舍弃掉该帧 将该帧数据拷贝(图中粗实线)至环上 以某种方式通知ams有新的一帧数据到来 ams模块在收到有新帧的消息时,调用 vframe_new_data_cb 函数,该函数主要完成以下任务: 取出环上一帧数据(head),如果没有,则直接返回 遍历 vdr_list 中的所有子模块,如果该模块关注帧数据(由attribute设置),则通过调用该模块的 trigger 函数将帧数据分发给其进行处理(分发的只是指针,并不做拷贝) AMS用g_trigger_node数组记录所有DATA_TYPE与算法模块的callback(即各模块的trigger 函数)之间的驱动关系。 g_trigger_node数组结构如下图所示: B模块在程序初始化阶段,自己的callback通过以下方式注册给g_trigger_node数组。 C /* * 以MD模块为例 * DATA_TYPE_FG_DIFF2是MD模块的驱动数据 * md_trigger是MD模块的trigger函数,用于接收和处理模块的驱动数据 */ alg_trigger_add(md_trigger, DATA_TYPE_FG_DIFF2); 当模块产生新数据DATA_TYPE_xx时,在g_trigger_node查找并触发其对应的算法callback,将此数据分发给此callback进行处理,此callback继续产生新的数据,依次往下按照深度优先顺序嵌套调用。 以vframe为例,具体调用过程如下图所示: 2.1.2. 环的设计与管理 以帧数据环的设计为例,目前使用数组来实现环。数组只保存帧数据的描述结构(VFRAME_DESC),分发也只分发该描述。由于描述中带有具体数据的地址,因此分发过程不涉及拷贝,其映射关系如下图: 具体数据结构定义如下: C /* 环上每个节点的内容 */ typedef struct _VFRAME_DESC { U64 stamps; /* 帧产生的时间 */ U16 refcnt; /* 引用计数,表明多少上层应用正在使用该帧 */ U16 collect_type; /* 采集的帧类型:单独Y、YUV420、YUV444. */ VFRAME *y, *u, *v; }VFRAME_DESC; /* 环 */ typedef struct _VFRAME_DESC_RING { VFRAME_DESC buffer[VFRAME_DESC_RING_SIZE]; /* 静态数组实现环 */ U8 head; /* 环头 */ U8 tail; /* 环尾 */ U16 reserved; /* 保留字段 */ VFRAME *data; /* 帧数据的首地址 */ }VFRAME_DESC_RING; 环上数据的生产者和消费者处于不同线程。需要使用 head、tail 以及每个环数据的 refcnt 来对环进行管理。tail 用于标识可能的放数据的位置;head 用于标识可能的取数据的位置;refcnt 用于标识某个数据的引用计数,不为0表示该数据正在被占用,不能被覆盖。环的管理方式具体如下: 在取出环尾空余位置时,如果尾部下一个位置(tail+1)的 refcnt 不为0,则返回NULL,表示没有空余位置 在取出环头数据进行分发后,直接向head后移;接收模块在使用该desc前对其attach(refcnt+1),使用后对其detach(refcnt-1) 2 模块抽象 VDR模块中的每个算法子模块都是一个VDR数据结构的一个实例,VDR的抽象结构如下所示: C /* 视频事件侦测与识别算法 */ typedef struct _VDR { char name[VDR_NAME_SIZE]; U8 event; /* 关注的事件类型 */ S32 (*init)(); /* 算法初始化,读取用户配置、系统参数,并配置到算法&ISP生效; */ S32 (*deinit)(); /* 算法去初始化,释放各功能资源 */ S32 (*reload)(); /* 算法配置更新。NSD有更新对应的参数时,会发送DMS消息,对应的进程关注消息并重载; */ S32 (*control)(U8 event_type, ALG_CONTROL alg_control); /* 算法控制,包括算法暂停、继续、清除缓存等 */ U32 (*status)(); /* 获取算法当前状态,如启用、停用等,详细待定 */ }VDR; typedef ALG_NODE VDR; VDR的抽象结构如上所示。对于隶属于VDR模块的每个子模块,如vframe、md等,均是VDR数据结构的一个实例。各成员具体含义如下: name 算法的名字。如MD算法模块的名字为"vdr_md",OD算法模块的名字为"vdr_od"。 event 算法关注的事件类型,包括电机转动事件、画面变化所引发的reset事件、COM口事件 init 算法的初始化函数。程序启动阶段会被调用,用于读取用户配置、系统参数,并配置到算法 deinit 算法的去初始化函数。AMS线程关闭时被调用,用于释放各功能资源。 reload 算法的加载配置函数。在该模块的相关配置数据被更改时会被调用,主要用于读取用户配置。 status 上层获取算法内部数据或信息的函数。 control 算法的控制函数。当事件发生时被调用,用于修改算法开关、控制算法状态(包括STATE_RUNNING, STATE_RESET, STATE_RELOAD)。每个算法在新的驱动源到来时处理算法主流程之前,首先根据算法状态来调用reload或reset,然后根据算法开关来决定是否运行算法主流程。 ##3 算法配置 3.1 配置数据 参考《AMS配置数据.md》,AMS涉及的配置主要有以下四种: 编译时配置 该配置需在编译时指定,用于确定参与编译的文件及相关宏定义 运行时不变配置 该配置是指在运行时不会被改变的配置 此配置只需在程序启动的时候通过init进行一次加载,之后不需要也不会被改变 运行时可变系统配置 该配置是指IPC系统本身的一些属性信息,算法处理过程中需要知道这些属性,根据这些属性的不同做相应的处理,如红外灯状态、电机状态等 这些属性在运行时是可变的,需要系统实时的配置给算法 运行时可变用户配置 该配置是指用户在功能页面上可调的针对该功能的配置。如移动侦测的用户配置为:开关、灵敏度和检测区域。 ​ 3.2 配置的加载 各个模块的配置数据加载分两种情况: 程序启动时,init 函数中加载配置 程序运行时,配置数据有变化时加载配置 通过ds_read方法加载配置,配置路径和配置模型定义在”slp_model.h“。 C ds_read(MOTION_DETECT_PATH, (void *)&motion_det, sizeof(MOTION_DETECT)) 运行时加载配置仍然通过回调的形式,在 ams_event.h 中定义一个消息id,并为该消息关联一个reload函数,当dms收到该类型的消息时,表明配置数据有变化,然后调用reload函数加载更新。 C /* 关注用户配置变化 */ msg_attach_handler(AMS_VDR_MD_RELOAD, md_reload); 4 结果后处理 结果后处理是指对于有些算法结果(如MD_RESULT),根据用户配置或系统配置,需要对算法的结果再进一步处理(如人形增强MD)。目前需要后处理的模块包括: 人形增强:ID,CD, GR, TT, PF, HD, CGD 人脸增强:CGD 车辆增强:PKD 对于需要结果后处理的模块,与trigger类似,AMS用g_post_proc数组记录所有RESULT_TYPE与算法模块的后处理函数(即各模块的xx_integrate 函数)之间的对应关系。 模块在程序初始化阶段,将自己的后处理函数通过以下方式注册给g_post_proc数组。 C /* * 以MD模块为例 * RESULT_TYPE_MD是MD模块关注的结果数据 * md_integrate是MD模块的后处理函数,用于接收和处理结果数据 */ post_proc_add(md_integrate, RESULT_TYPE_MD); 当A模块产生新的结果类型RESULT_TYPE_A时,在g_post_proc查找其对应的算法后处理函数,如果B模块已将自己的后处理函数添加RESULT_TYPE_A的列表中,则触发此后处理函数将结果分发给B进行后处理。 C /* * 以MD模块为例 * RESULT_TYPE_MD是MD模块产生的结果数据 * md_context->md_result是MD模块的运行结果 */ post_proc_trigger((void *)&md_context->md_result, RESULT_TYPE_MD); 以MD后处理(PD增强MD)为例,后处理流程如下所示: MD模块的后处理指的是用PD结果增强MD,后处理所需要的结果数据由各模块发出并触发MD后处理,当所有所需数据到齐时MD执行后处理流程,将最终的MD结果发送给上层。 对于不需要后处理的模块,如AOD,可以直接在算法流程处理完之后发送结果给上层,无需添加AOD后处理。
最新发布
08-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值