diff --git "a/design/dfx/\344\272\213\344\273\266\350\256\276\350\256\241.md" "b/design/dfx/\344\272\213\344\273\266\350\256\276\350\256\241.md" index 67b502a8660c1c34dd4cbef035d032229769ab1f..3063907024b82a7e89e9dad09989788ac1ef8c9b 100644 --- "a/design/dfx/\344\272\213\344\273\266\350\256\276\350\256\241.md" +++ "b/design/dfx/\344\272\213\344\273\266\350\256\276\350\256\241.md" @@ -1,54 +1,115 @@ ## 1. 故障事件 -### 1.1 播放 +故障事件一次一打,每个事件收集的信息都不一样 +### 1.1 SOURCE_FAILURE +当前在播放器 set source流程失败时打点,后续下沉source模块 ```json { APP_NAME: string, INSTANCE_ID: string, + CALLER_TYPE: string, SOURCE_TYPE: int8, //数据源类型枚举 SOURCE_URI: string, - VIDEO_CODEC: string, - AUDIO_CODEC: string, - CONTAINER_FORMAT: string, - ERROR_CODE: int32, // 与player错误码维持一致 ERROR_MESG: string, } ``` -### 1.2 录制 +### 1.2 DEMUXER_FAILURE +当前在播放器 prepare流程失败时打点,后续下沉demuxer模块 ```json { APP_NAME: string, INSTANCE_ID: string, + CALLER_TYPE: string, + SOURCE_TYPE: int8, //数据源类型枚举 + CONTAINER_FORMAT: string, + STREAM_TYPE: string, + ERROR_MESG: string, +} +``` +### 1.3 AUDIO_CODEC_FAILURE +- player start后音频解码失败时打点 +- recorder start后音频编码失败时打点 +- 后续下沉audio codec模块 +```json +{ + APP_NAME: string, + INSTANCE_ID: string, + CALLER_TYPE: string, + AUDIO_CODEC: string, + ERROR_MESG: string, +} +``` +### 1.4 VIDEO_CODEC_FAILURE +- player start后视频解码失败时打点 +- recorder start后视频编码失败时打点 +- 后续下沉video codec模块 +```json +{ + APP_NAME: string, + INSTANCE_ID: string, + CALLER_TYPE: string, + VIDEO_CODEC: string, + ERROR_MESG: string, +} +``` +### 1.5 MUXER_FAILURE +当前在recorder start后,封装失败时打点,后续下沉muxer模块 +```json +{ + APP_NAME: string, + INSTANCE_ID: string, + CALLER_TYPE: string, VIDEO_CODEC: string, AUDIO_CODEC: string, CONTAINER_FORMAT: string, - AUDIO_SOURCE_TYPE: int32, // 音频源类型枚举 - ERROR_CODE: int32, // 与recorder错误码维持一致 ERROR_MESG: string, - } ``` -### 1.3 录屏 +### 1.6 RECORD_AUDIO_FAILURE +录制过程中与音频输入相关的故障事件 +```json +{ + APP_NAME: string, + INSTANCE_ID: string, + AUDIO_SOURCE_TYPE: int32, + ERROR_MESG: string, +} +``` +### 1.7 SCREEN_CAPTURE_FAILURE +录屏故障事件 ```json { APP_NAME: string, INSTANCE_ID: string, CAPTURE_MODE: int8, // 模式枚举,视频,音频,视频+音频 DATA_MODE: int8, // 数据类型枚举,buffer,sufrace,file - CONTAINER_FORMAT: string, ERROR_CODE: int32, // 与screen capture错误码维持一致 ERROR_MESG: string, - } ``` -### 1.4 DRM +### 1.8 DRM_DECRTPYION_FAILURE +DRM解密故障事件 +```json +{ + APP_NAME: string, + INSTANCE_ID: string, + ERROR_CODE: int32, + ERROR_MESG: string, + DECRYPT_ALGO: string, + DECRYPT_KEYID: string, + DECRYPT_IV: string, +} +``` +### 1.9 DRM_COMMON_FAILURE +DRM通用故障事件 ```json DRM_COMMON_FAILURE { APP_NAME: string, INSTANCE_ID: string, - ERROR_CODE: int32, // 与drm错误码维持一致 + ERROR_CODE: int32, ERROR_MESG: string, + EXTRA_MESG: string, EXTRA_MESG: string, // 处理响应失败时填写响应字符串 } @@ -63,10 +124,58 @@ DRM_DECRYPTION_FAILURE DECRYPT_IV: string, } ``` -## 2. 统计事件 -- 各个模块独立上报统计事件:PLAYER_EVENT,RECORDER_EVENT,SCREEN_CAPTURE_EVENT,... +## 2. 行为事件 +### 2.1 DRM_SERVICE_INFO +```json +{ + MODULE: string, + TIME: uint32, + SERVICE_NAME: string, + ACTION: string, // 启动或退出 + MEMORY: uint32, // kb +} +``` +### 2.2 DRM_LICENSE_DOWNLOAD_INFO +```json +{ + MODULE: string, + TIME: uint32, + APP_NAME: string, + INSTANCE_ID: string, + DRM_NAME: string, + DRM_UUID: string, + CLIENT_VERSION: string, + LICENSE_TYPE: string, + GENERATION_DURATION: uint32, + GENERATION_RESULT: string, + PROCESS_DURATION: uint32, + PROCESS_RESULT: string, +} +``` +### 2.3 DRM_CERTIFICATION_DOWNLOAD_INFO +```json +{ + MODULE: string, + TIME: uint32, + APP_NAME: string, + INSTANCE_ID: string, + DRM_NAME: string, + DRM_UUID: string, + CLIENT_VERSION: string, + GENERATION_DURATION: uint32, + GENERATION_RESULT: string, + PROCESS_DURATION: uint32, + PROCESS_RESULT: string, + CALL_SERVER_TIME: uint32, + SERVER_COST_DURATION: uint32, + SERVER_RESULT: string, +} +``` +## 3. 统计事件 +- 各个模块独立上报统计事件 - 每个统计事件以app为单位聚合 - 每个app的统计事件包含多次独立媒体事件 +### 3.0 上报事件定义 ```json { EVENTS: array, // [appEvent1, appEvent2,...],每个appEvent都是json格式的string @@ -79,7 +188,8 @@ DRM_DECRYPTION_FAILURE mediaEvents: [mediaEvent1, mediaEvent2,...], // 每个mediaEvent是该app的一次独立的播放/录制/录屏 } ``` -### 2.1 播放mediaEvent +### 3.1 PLAYER_STATISTICS +当前在player engine内收集信息,后续下沉到avcodec模块,并在服务进程汇总 ```json { // 事件结果 @@ -89,14 +199,18 @@ DRM_DECRYPTION_FAILURE playDuration: int32, // source信息 sourceType: int32, // 类型枚举,本地、流媒体... - sourceUrl?: string, - sourceIp?: string, // 近国内打点 + sourceUrl: string, + sourceIp: string, // 仅国内打点 avgDownloadRate: int32, containerMime: string, + // video参数 videoMime: string, videoResolution: string, + vidroFrameRate: float, + videoBitdepth: int8, videoBitrate: int32, hdrType: int8, // hdr类型枚举 + // audio参数 audioMime: string, audioSampleRate: int32, audioChannelCount: int32, @@ -105,6 +219,7 @@ DRM_DECRYPTION_FAILURE isDrmProtected: bool, // 性能信息 startLatency: int32, + avgDownloadSpeed: int32, maxSeekLatency: int32, maxAccurateSeekLatency: int32, lagTimes: int32, @@ -113,7 +228,8 @@ DRM_DECRYPTION_FAILURE maxSurfaceSwapLatency: int32, } ``` -### 2.2 录制mediaEvent +### 3.2 RECORDER_STATISTICS +当前在record engine内收集信息,后续下沉到avcodec模块,并在服务进程汇总 ```json { // 事件结果 @@ -134,7 +250,7 @@ DRM_DECRYPTION_FAILURE startLatency: int32, } ``` -### 2.3 录屏mediaEvent +### 3.3 SCREEN_CAPTURE_STATISTICS ```json { // 事件结果 @@ -153,8 +269,7 @@ DRM_DECRYPTION_FAILURE startLatency: int32, } ``` - -### 2.4 DRM mediaEvent +### 3.4 DRM_STATISTICS ```json { APP_NAME: string, @@ -168,50 +283,74 @@ DRM_DECRYPTION_FAILURE DECRYPT_MAX_DURATION: uint32 // ms } ``` - -## 3. 行为事件 -### 3.1 DRM +### 3.5 DEMUXER_STATISTICS +【后续计划】 ```json -DRM_SERVICE_INFO { - MODULE: string, - TIME: uint32, - SERVICE_NAME: string, - ACTION: string, // 启动或退出 - MEMORY: uint32, // kb -} + // 事件结果 + errCode: int32, + errMsg?: string, + // 数据时长 + dataDuration:int32, + // 格式信息 + sourceType: int32, // 类型枚举,本地、流媒体... + sourceUrl: string, + sourceIp: string, // 仅国内打点 + avgDownloadRate: int32, + containerMime: string, + // 性能信息 + avgDownloadSpeed: int32, -DRM_LICENSE_DOWNLOWD_INFO +} +``` +### 3.6 VIDEO_CODEC_STATISTICS +【后续计划】 +```json { - MODULE: string, - TIME: uint32, - APP_NAME: string, - INSTANCE_ID: string, - DRM_NAME: string, - DRM_UUID: string, - CLIENT_VERSION: string, - LICENSE_TYPE: string, - GENERATION_DURATION: uint32, - GENERATION_RESULT: string, - PROCESS_DURATION: uint32, - PROCESS_RESULT: string, + // 事件结果 + errCode: int32, + errMsg?: string, + // 数据时长 + dataDuration:int32, + // 格式信息 + videoMime: string, + videoResolution: string, + videoBitdepth: int8, + vidroFrameRate: float, + videoBitrate: int32, + hdrType: int8, // hdr类型枚举 + } +``` +### 3.7 AUDIO_CODEC_STATISTICS +【后续计划】 +```json +{ + // 事件结果 + errCode: int32, + errMsg?: string, + // 数据时长 + dataDuration:int32, + // 格式信息 + audioMime: string, + audioSampleRate: int32, + audioChannelCount: int32, + audioBitrate: int32, -DRM_CERTIFICATE_DOWNLOWD_INFO +} +``` +### 3.8 MUXER_STATISTICS +【后续计划】 +```json { - MODULE: string, - TIME: uint32, - APP_NAME: string, - INSTANCE_ID: string, - DRM_NAME: string, - DRM_UUID: string, - CLIENT_VERSION: string, - GENERATION_DURATION: uint32, - GENERATION_RESULT: string, - PROCESS_DURATION: uint32, - PROCESS_RESULT: string, - CALL_SERVER_TIME: uint32, - SERVER_COST_DURATION: uint32, - SERVER_RESULT: string, + // 事件结果 + errCode: int32, + errMsg?: string, + // 数据时长 + dataDuration:int32, + // 格式信息 + videoMime: string, + audioMime: string, + containerMime: string, } -``` \ No newline at end of file +``` diff --git "a/design/dfx/\350\247\206\351\242\221\346\241\206\346\236\266DFX\350\256\276\350\256\241.md" "b/design/dfx/\350\247\206\351\242\221\346\241\206\346\236\266DFX\350\256\276\350\256\241.md" index 64e3fdd0fadeae05f933b2fb40b7681b82984628..ba0162a369d38661fe3e032c8b937a07bdd3f361 100644 --- "a/design/dfx/\350\247\206\351\242\221\346\241\206\346\236\266DFX\350\256\276\350\256\241.md" +++ "b/design/dfx/\350\247\206\351\242\221\346\241\206\346\236\266DFX\350\256\276\350\256\241.md" @@ -5,53 +5,96 @@ 视频框架整体流程,和DFX事件打点主要涉及新增(红色)、修改(黄色)的模块参见下图: ![DFX逻辑架构图](images/dfx-arch.PNG) -## 1. 事件设计 +## 1. 播放链路设计 -故障事件:根据视频框架的业务特点,把业务流程中关键的故障(用户会感知,而不是一个局部流程)及时上报,并同时报告完整的相关定位信息(比如trace、log等),支撑问题定位。 +播放链路主要为了将同一个player/recorder/retriever/av_codec调用过程整个链路主要的对象都串联一起。例如整个播放链路涉及以下对象:app -> avplayer对象 -> avcodec对象 -> hdi decoder对象。将所有链路对象串联后,可以更加方便的分析多实例场景下各链路情况,同时也利于相关信息打印和事件上报。 -统计事件:根据视频框架业务演进的需要,关键的KPI指标,设计统计事件,统计关键信息。 - -### 1.1 事件管理服务 (需要复用Media Foundation/MediaMonitor服务) -职责: -1. 提供事件记录接口,支持player framework, avcodec各个业务流程,调用事件记录接口,记录事件信息到事件管理服务。(接口和实现,放在 media_foundation,音频可能也会使用) -2. 记录并管理事件信息。 -3. 事件持久化到cache文件。 -4. 按照规定的上报机制,上报事件。 -5. 定义事件类型、名称、字段等数据结构。 -6. 统计事件,把所有事件记录信息转换为统计事件(json字符串)。 - -### 1.2 入口对象整体调用流程 - -#### 1.2.1 player framework 对象跟踪方式 -app -> js -> napi -> avplayer -> pipeline/filter -> module -> plugin - -1. napi创建实例(avplayer, avrecorder, avscreencapture等)的时候,就会创建HiTraceChainId。 - 后续所有调用流程,都能获取到入口实例对象的id。 -2. 借助 log trace id,它是唯一绑定一个实例的,还可以跨进程访问。 - 调用 HiTraceChain::GetId().GetChainId() 即可在任意位置获取到id,后面也称为instanceId。 +### 1.1 HiTraceChain 工具 ``` class HiTraceChain final { public: + // 上层实例创建时调用 + static HiTraceId Begin(const string &name, int flags); + // 上次实例析构时调用 + static void End(const HiTraceId &id); + // Get trace id of current thread, and return a invalid trace id if no // trace id belong to current thread. static HiTraceId GetId(); } ``` +- 通过HiTraceChain工具可以创建一个独一无二的id,绑定创建id的实例 +- 一个实例创建的id,在这个实例发起的调用中都可以通过HiTraceChain::GetId().GetChainId()获取,可以跨IPC +- 此id可以称为instanceId,用于串接媒体业务的调用流程 +- instanceId会体现在HiLog中 -#### 1.2.2 avcodec 原子能力入口调用方式 -app -> ndk -> ndk_impl -> demuxer -> module -> plugin +### 1.2 入口对象整体调用流程 -1. ndk_impl 实现里面,创建 HiTraceChainId。 -2. 后续的所有调用流程,包括记录信息,都是跟 player framework 一样,复用相同的代码。 +- player_framework 播放/录制/录屏 实例跟踪方式:在napi对象创建的时候,获取instanceID +``` +app -> js -> napi -> avplayer -> pipeline/filter -> module -> plugin +``` +- av_codec 原子能力 实例跟踪方式:在ndk_impl对象创建的时候,获取instanceID +``` +app -> ndk -> ndk_impl -> avcodec -> module -> plugin +``` + +napi/ndk_impl创建的时候,同步通过HiTraceChain工具创建一个id,后续所有调用流程,都能获取到入口实例对象的id。 -原子能力需要做一个自己的 Monitor 线程。 +### 1.3 媒体业务整体链路打通 -### 1.3 接口设计 +两个不同进程的媒体实例可以根据instanceID关联,但无法根据instanceID直接获得媒体通路的链路。需要新增MediaChainManager工具,将同一个instanceID、不同进程的实例连接起来。 -**事件定义** +#### 1.3.1 当前策略 +player、recorder自行将app->player_framework流程打通,使用FAKEPOINTER命名AVCodec实例,进行流程串接。 -事件类型分为以下几种,定义在CallType枚举中。 +#### 1.3.2 后续优化策略 +依赖avcodec、hdi codec串接后续流程 +```c++ +class MediaChainManager { + static void AddChain(meta{avcodec_name:"VideoDec#id1", hdi_codec_name:"HDIDec#id2"}); + static void RemoveChain(meta{avcodec_name:"VideoDec#id1", hdi_codec_name:"HDIDec#id2"}); + static void RemoveInstance(id); // 用入口对象唯一实例id + /* + * MediaChain是一个list,其中每个Node代表一个媒体资源实例 + * 一条MediaChain上每个node都属于同一个instanceID + */ + map> mediaChains; +} +``` +构建MediaChain需要上下游节点的信息,AVCodec需要新增接口接受player/recorder的信息。 +```cpp +// 现有接口 +static std::shared_ptr CreateByMime(const std::string &mime); +// 新增create接口,可以返回AVCodec创建的错误码 +static int32_t CreateByMime(const std::string &mime, const Format &format, std::shared_ptr &codec); +// Format新增key,由PlayerFramework调用时传入 +constexpr char AV_CODEC_FORWARD_CALLER_PID; // 调用AVPlayer的app的uid +constexpr char AV_CODEC_FORWARD_CALLER_PROCESS_NAME; // 调用AVPlayer的app的process name,比如抖音 +``` +- 新接口中,错误码通过返回值带出 +- callerInfo通过format传递给CodecServer +- format复用现有IPC序列化/反序列化,后续支持进一步扩展可传递的信息 + +通过这种方式,由media_service进程拉起的codec实例也能知道外部调用方是谁,在构建MediaChain、事件大点时都可以利用这些信息。 + +## 2. 事件设计 +媒体业务目前设计了三类事件: + +- 故障事件:根据视频框架的业务特点,把业务流程中关键的故障(用户会感知,而不是一个局部流程)及时上报,并同时报告完整的相关定位信息(比如trace、log等),支撑问题定位。 +- 统计事件:根据视频框架业务演进的需要,关键的KPI指标,设计统计事件,统计关键信息。 +- 行为事件:由App触发的特定业务行为,比如DRM解密服务的创建。 + +### 2.1 事件管理服务 (需要复用Media Foundation/MediaMonitor服务) +职责: +1. 提供事件记录接口:支持player framework、avcodec、drm framework等业务流程,调用事件记录接口,记录事件信息到事件管理服务。(接口和实现放在media_foundation代码仓,其他媒体模块可能也会使用) +2. 记录并管理事件信息:定义事件类型、名称、字段等数据结构,对各个模块上报的信息进行统计汇总,并按照规定的上报机制上报事件。 +3. 事件持久化到cache文件:降低内存开销,系统异常时能恢复历史统计信息。 + +### 2.2 事件接口设计 + +- 事件类型定义:即应用调用媒体能力的接口,可以分为以下几种: ```cpp enum CallType { AVPLAYER, @@ -61,7 +104,7 @@ enum CallType { AVDEMUXER, AVMUXER, VIDEO_DECODER, - VIDEO_DECODER, + VIDEO_ENCODER, AUDIO_DECODER, AUDIO_ENCODER, SOUNDPOOL, @@ -69,131 +112,82 @@ enum CallType { AVTRANSCODER } ``` +- 事件数据结构定义 -**打点** +对于单次事件(例如播放器的一次播放、codec的一次解码生命周期),所有需要打点的内容以key-value的方式保存在Meta中。受限于Meta的跨IPC能力,事件的key定义需要以特殊的方式定义,参考media_foundation/src/meta/meta.cpp中的添加方式。 -MediaInfo用来保存单次事件(例如播放player)所有需要打点的内容,以key-value的方式保存,key定义在XXXInfo枚举中。 -```c++ -class MediaInfo { - Meta; -} +MediaInfo的key最大程度复用已有定义,参考media_foundation/interface/innerapi/meta/meta_key.h。但也可能需要新增key -player涉及的key -{ - time_stamp : string - source_type : string - url : string - demuxer_type : string - audio_decoder_type : string - bit_rate : int32_t - average_frame_rate : int32_t - video_height : int32_t - video_width : int32_t - play_duration : int32_t - sample_rate : int32_t - channels : int32_t - audio_mime : string - video_mime : string -} +- 事件上报(媒体DFX服务)接口设计 +MediaEvent提供事件创建、修改、上报的接口。务在调用方开始处(例如播放过程的setSource方法)需要先调用一次CreateMediaInfo并传入callType,这个操作会在callType对应的map中新增本次事件的MediaInfo。后续整个流程的打点只需要调用GetMediaInfo方法并往MediaInfo传入key-value即可。 -recorder涉及的key -{ - time_stamp : string - audio_source_type : string - audio_encoder : string - audio_bit_rate : int32_t - audio_sample_rate : int32_t - audio_channels : int32_t - video_source_type : string - video_encoder : string - recorder_video_width : int32_t - recorder_video_height : int32_t - video_bit_rate : int32_t - video_frame_rate : int32_t - recorder_count : int32_t - output_format : string - recorder_duration : int32_t -} - -MetadataRetriver涉及的key -{ - time_stamp : string - retriever_player_type : string - get_frame_type : string - retriever_count : int32_t - device_model : string - chip_board : string -} -``` +- MediaEvent接口设计目标是独立运行在DFX进程中,媒体各个模块均可以访问。受限于当前能力完备性,第一步先存活在调用者进程中,各个模块独立打点。 -**事件记录及上报** - -MediaEvent用来获取MediaInfo对象和事件上报功能,业务在调用方开始处(例如播放过程的setSource方法)需要先调用一次CreateMediaInfo并传入callType(CallType)和pid,CreateMediaInfo会新生成callType对应的map,里面保存了一系列MediaInfo,后续整个流程的打点只需要调用GetMediaInfo方法并往MediaInfo传入key-value即可。 ```c++ class MediaEvent { - static void CreateMediaInfo(callType, appPid); // 以player为例,内部产生针对当前这次播放对应的MediaInfo实例,SetSource()里调用。内部实现调用 HiTraceChain::GetId().GetChainId() 获得标识player的唯一instanceId。 - static shared_ptr GetMediaInfo(callType, appPid); // 以player为例,获取当前播放对应的信息记录实例。 - static void Report(); // 上报事件时,MonitorServer调用 MediaEvent::Report 即可,同时清空数据。 - - map>> map_; + /* + * 创建一次统计事件的MediaInfo,调用方只需要传入callType、uid + * 以player为例,可以在SetSource()里调用 + * 内部实现需要调用HiTraceChain::GetId().GetChainId() + * 获得标识player的唯一instanceId,与这个事件关联起来 + */ + static void CreateMediaInfo(callType, appUid); + + /* + * 向当前instanceID的最新的MediaInfo里追加统计信息info + */ + static void AppendMediaInfo(Meta &info); + + /* + * 上报当前实例的MediaInfo,上报后不可再更新 + * 内部根据实例唯一的instanceId,锁定最新的MediaInfo + * 由于上报后无法再获取和修改,因此需要在实例析构时进行上报 + */ + static void ReportMediaInfo(); + + /* + * 实时上报一个行为事件 + * 事件类型包含在Meta中 + * 实时上报到系统大数据模块,无需存储/汇总info + */ + static bool ReportBehaviorEvent(callerType, eventName, Meta &info); + + /* + * 实时上报一个故障事件 + * 事件类型包含在Meta中 + * 实时上报到系统大数据模块,无需存储/汇总info + */ + static bool ReportFaultEvent(callerType, eventName, Meta &info); + +private: + map>>> map_; + map> idMap_; } ``` +### 2.3 事件上报机制设计 -保存到本地(可以考虑使用sql_lite,待讨论)。MediaEvent构造方法中执行定时逻辑,默认为每晚8点上报,同时需要做离散操作(例如离散19:30-20:30),防止出现浪涌现象。 - -音频原子能力存活在应用进程,可能无法直接写文件(待讨论) - -### 1.4 事件上报机制设计 +MediaDFX模块上报事件到系统DFX模块,需要用到系统[HiSysEvent打点接口](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging.md#/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md)。 -MediaEvent::Report事件上报需要用到系统[HiSysEvent打点接口](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging.md#/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md)。 - -以player为例,需要在hisysevent.yaml文件中定义player相关事件,当前需要将MediaInfo都汇聚成json字符串上报。 - -**业务中打点方式** +- 需要在hisysevent.yaml文件中定义事件相关事件,并将MediaInfo都汇聚成yaml中定义的事件类型进行上报。 ```c++ -HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, "PLAY_INFO_EVENT", +// 接口调用示例 +HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::MULTIMEDIA, "PLAY_INFO_EVENT", HiviewDFX::HiSysEvent::EventType::STATISTIC, "PLAY_INFO", xxx(汇总所有播放信息的json字符串)); -HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, "RECORD_INFO_EVENT", +HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::MULTIMEDIA, "RECORD_INFO_EVENT", HiviewDFX::HiSysEvent::EventType::STATISTIC, "RECORD_INFO", xxx(汇总所有录制信息的json字符串)); -... ``` -Domain定义在hisysevent.h中,目前没有player_framework相关的Domain,需要新增。 - -注:av_session业务中已经存在类似打点工具avsession_sysevent.h,除了封装HiSysEventWrite立刻打点的接口外,还提供了定制化的接口用来保存事件的参数,每隔一个小时会尝试上报一次事件。 +Domain定义在hisysevent.h中,目前可以统一使用Multimedia的domain。 -## 2. 播放链路设计 +### 2.4 后续优化策略 +- DFX能力IPC化 +- 大点数据保存到本地(可以考虑使用sql_lite,待讨论)。MediaEvent构造方法中执行定时逻辑,默认为每晚8点上报,同时需要做离散操作(例如离散19:30-20:30),防止出现浪涌现象。音频原子能力存活在应用进程,可能无法直接写文件(待讨论) -播放链路主要为了将同一个player/recorder/retriever/av_codec调用过程整个链路主要的对象都串联一起。 -例如整个播放链路涉及以下对象:app -> avplayer对象 -> avcodec对象 -> hisi decoder对象。 -将所有链路对象串联后,可以更加方便的分析多实例场景下各链路情况,同时也利于相关信息打印和事件上报。 +注:av_session业务中已经存在类似打点工具avsession_sysevent.h,除了封装HiSysEventWrite立刻打点的接口外,还提供了定制化的接口用来保存事件的参数,每隔一个小时会尝试上报一次事件。 -### 2.1 接口设计 -```c++ -class MediaChainManager { - static void AddInfo(meta{avcodec_name:"video_hw_decoder#xxxx", hisicodec_name:"video_hw_decoder#xxxx"}); - static void RemoveInfo(meta{avcodec_name:"video_hw_decoder#xxxx", hisicodec_name:"video_hw_decoder#xxxx"}); - static void RemoveInstance(id); // 用入口对象唯一实例id - // 设计一个数据结构 app -> 实例 -> avcodec -> hisi 实例的 - // MediaChain: app -> 实例 -> avcodec -> hisi 实例的, 可以存字符串 - // 实例销毁时,list对应 实例的内容要删除。 - list list; -} -``` -### 2.2 player/recorder到avcodec的链路打通 -```cpp -// 现有接口 -static std::shared_ptr CreateByMime(const std::string &mime); -// 新增create接口 -static int32_t CreateByMime(const std::string &mime, const Format &format, std::shared_ptr &codec); -// Format新增key,由PlayerFramework调用时传入 -constexpr char AV_CODEC_FORWARD_CALLER_PID; // 调用AVPlayer的app的uid -constexpr char AV_CODEC_FORWARD_CALLER_PROCESS_NAME; // 调用AVPlayer的app的process name,比如抖音 -``` -- 新接口中,错误码通过返回值带出 -- callerInfo通过format传递给CodecServer -- format复用现有IPC序列化/反序列化,后续支持进一步扩展可传递的信息 \ No newline at end of file +## 3. 点位设计 +见事件设计 \ No newline at end of file