1// Copyright (c) 2021 Huawei Device Co., Ltd. 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14import { TraficEnum } from './utils/QueryEnum'; 15import { FrameAnimationStruct } from '../ui-worker/ProcedureWorkerFrameAnimation'; 16import { FrameSpacingStruct } from '../ui-worker/ProcedureWorkerFrameSpacing'; 17 18export const chartFrameAnimationDataProtoSql = (args: any): string => { 19 return ` 20 SELECT 21 a.id AS animationId, 22 0 AS status, 23 ( 24 CASE WHEN a.input_time NOT NULL 25 THEN ( a.input_time - ${args.recordStartNS} ) 26 ELSE ( a.start_point - ${args.recordStartNS} ) 27 END 28 ) AS startTs, 29 ( a.start_point - ${args.recordStartNS} ) AS endTs, 30 a.name AS name 31 FROM 32 animation AS a 33 UNION 34 SELECT 35 a.id AS animationId, 36 1 AS status, 37 ( 38 CASE WHEN a.input_time NOT NULL 39 THEN ( a.input_time - ${args.recordStartNS} ) 40 ELSE ( a.start_point - ${args.recordStartNS} ) 41 END 42 ) AS startTs, 43 ( a.end_point - ${args.recordStartNS} ) AS endTs, 44 a.name AS name 45 FROM 46 animation AS a;`; 47}; 48 49export const chartFrameDynamicDataProtoSql = (args: any): string => { 50 return ` 51 SELECT 52 dy.id, 53 dy.x, 54 dy.y, 55 dy.width, 56 dy.height, 57 dy.alpha, 58 (dy.end_time - ${args.recordStartNS}) AS ts, 59 dy.name as appName, 60 ((dy.end_time - ${args.recordStartNS}) / (${Math.floor((args.endNS - args.startNS) / args.width)})) AS px 61 FROM 62 dynamic_frame AS dy 63 WHERE ts >= ${Math.floor(args.startNS)} 64 and ts <= ${Math.floor(args.endNS)}`; 65}; 66 67export const chartFrameSpacingDataProtoSql = (args: any): string => { 68 return ` 69 SELECT 70 d.id, 71 d.x, 72 d.y, 73 d.width AS currentFrameWidth, 74 d.height AS currentFrameHeight, 75 (d.end_time - ${args.recordStartNS}) AS currentTs, 76 d.name AS nameId, 77 ((d.end_time - ${args.recordStartNS}) / (${Math.floor((args.endNS - args.startNS) / args.width)})) AS px 78 FROM 79 dynamic_frame AS d 80 WHERE currentTs >= ${Math.floor(args.startNS)} 81 and currentTs <= ${Math.floor(args.endNS)} 82 group by px;`; 83}; 84 85export function frameAnimationReceiver(data: any, proc: Function): void { 86 let res = proc(chartFrameAnimationDataProtoSql(data.params)); 87 let transfer = data.params.trafic !== TraficEnum.SharedArrayBuffer; 88 let frameAnimation = new FrameAnimation(data, res, transfer); 89 let unitIndex: number = 1; 90 let isIntersect = (a: FrameAnimationStruct, b: FrameAnimationStruct): boolean => 91 Math.max(a.startTs! + a.dur!, b.startTs! + b.dur!) - Math.min(a.startTs!, b.startTs!) < a.dur! + b.dur!; 92 let depths: any[] = []; 93 for (let index: number = 0; index < res.length; index++) { 94 let itemData = res[index]; 95 data.params.trafic === TraficEnum.ProtoBuffer && (itemData = itemData.frameAnimationData); 96 itemData.dur = itemData.endTs - itemData.startTs; 97 if (!itemData.dur || itemData.dur < 0) { 98 continue; 99 } 100 if (depths.length === 0) { 101 itemData.depth = 0; 102 depths[0] = itemData; 103 } else { 104 let depthIndex: number = 0; 105 let isContinue: boolean = true; 106 while (isContinue) { 107 if (isIntersect(depths[depthIndex], itemData)) { 108 if (depths[depthIndex + unitIndex] === undefined || !depths[depthIndex + unitIndex]) { 109 itemData.depth = depthIndex + unitIndex; 110 depths[depthIndex + unitIndex] = itemData; 111 isContinue = false; 112 } 113 } else { 114 itemData.depth = depthIndex; 115 depths[depthIndex] = itemData; 116 isContinue = false; 117 } 118 depthIndex++; 119 } 120 } 121 frameAnimation.animationId[index] = itemData.animationId; 122 frameAnimation.status[index] = itemData.status; 123 frameAnimation.startTs[index] = itemData.startTs; 124 frameAnimation.endTs[index] = itemData.endTs; 125 frameAnimation.dur[index] = itemData.dur; 126 frameAnimation.depth[index] = itemData.depth; 127 } 128 postFrameAnimationMessage(data, transfer, frameAnimation, res.length); 129} 130function postFrameAnimationMessage(data: any, transfer: boolean, frameAnimation: FrameAnimation, len: number) { 131 (self as unknown as Worker).postMessage( 132 { 133 id: data.id, 134 action: data.action, 135 results: transfer 136 ? { 137 animationId: frameAnimation.animationId.buffer, 138 status: frameAnimation.status.buffer, 139 startTs: frameAnimation.startTs.buffer, 140 endTs: frameAnimation.endTs.buffer, 141 dur: frameAnimation.dur.buffer, 142 depth: frameAnimation.depth.buffer, 143 } 144 : {}, 145 len: len, 146 transfer: transfer, 147 }, 148 transfer 149 ? [ 150 frameAnimation.animationId.buffer, 151 frameAnimation.status.buffer, 152 frameAnimation.startTs.buffer, 153 frameAnimation.endTs.buffer, 154 frameAnimation.dur.buffer, 155 frameAnimation.depth.buffer, 156 ] 157 : [] 158 ); 159} 160class FrameAnimation { 161 animationId: Uint16Array; 162 status: Uint16Array; 163 startTs: Float64Array; 164 endTs: Float64Array; 165 dur: Float64Array; 166 depth: Uint16Array; 167 168 constructor(data: any, res: any[], transfer: boolean) { 169 this.animationId = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.animationId); 170 this.status = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.status); 171 this.startTs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startTs); 172 this.endTs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.endTs); 173 this.dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur); 174 this.depth = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.depth); 175 } 176} 177 178export function frameDynamicReceiver(data: any, proc: Function): void { 179 let res = proc(chartFrameDynamicDataProtoSql(data.params)); 180 let transfer = data.params.trafic !== TraficEnum.SharedArrayBuffer; 181 let id = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.id); 182 let x = new Float32Array(transfer ? res.length : data.params.sharedArrayBuffers.x); 183 let y = new Float32Array(transfer ? res.length : data.params.sharedArrayBuffers.y); 184 let width = new Float32Array(transfer ? res.length : data.params.sharedArrayBuffers.width); 185 let height = new Float32Array(transfer ? res.length : data.params.sharedArrayBuffers.height); 186 let alpha = new Float32Array(transfer ? res.length : data.params.sharedArrayBuffers.alpha); 187 let ts = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.ts); 188 for (let index: number = 0; index < res.length; index++) { 189 let itemData = res[index]; 190 data.params.trafic === TraficEnum.ProtoBuffer && (itemData = itemData.frameDynamicData); 191 id[index] = itemData.id; 192 x[index] = Number(itemData.x); 193 y[index] = Number(itemData.y); 194 width[index] = Number(itemData.width); 195 height[index] = Number(itemData.height); 196 alpha[index] = Number(itemData.alpha); 197 ts[index] = itemData.ts; 198 } 199 (self as unknown as Worker).postMessage( 200 { 201 id: data.id, 202 action: data.action, 203 results: transfer 204 ? { 205 id: id.buffer, 206 x: x.buffer, 207 y: y.buffer, 208 width: width.buffer, 209 height: height.buffer, 210 alpha: alpha.buffer, 211 ts: ts.buffer, 212 } 213 : {}, 214 len: res.length, 215 transfer: transfer, 216 }, 217 transfer ? [id.buffer, x.buffer, y.buffer, width.buffer, height.buffer, alpha.buffer, ts.buffer] : [] 218 ); 219} 220 221export function frameSpacingReceiver(data: any, proc: Function): void { 222 let res = proc(chartFrameSpacingDataProtoSql(data.params)); 223 let transfer = data.params.trafic !== TraficEnum.SharedArrayBuffer; 224 let frameSpacing = new FrameSpacing(data, res.length, transfer); 225 let nameDataMap: Map<string, Array<FrameSpacingStruct>> = new Map(); 226 for (let index: number = 0; index < res.length; index++) { 227 let itemData = res[index]; 228 data.params.trafic === TraficEnum.ProtoBuffer && (itemData = itemData.frameSpacingData); 229 if (nameDataMap.has(itemData.nameId)) { 230 setSpacingStructs(nameDataMap, itemData, data); 231 } else { 232 setNameDataMap(nameDataMap, itemData); 233 } 234 frameSpacing.id[index] = itemData.id; 235 frameSpacing.x[index] = Number(itemData.x); 236 frameSpacing.y[index] = Number(itemData.y); 237 frameSpacing.currentFrameWidth[index] = Number(itemData.currentFrameWidth); 238 frameSpacing.currentFrameHeight[index] = Number(itemData.currentFrameHeight); 239 frameSpacing.currentTs[index] = itemData.currentTs; 240 frameSpacing.frameSpacingResult[index] = Number(itemData.frameSpacingResult); 241 frameSpacing.preTs[index] = itemData.preTs; 242 frameSpacing.preFrameWidth[index] = Number(itemData.preFrameWidth); 243 frameSpacing.preFrameHeight[index] = Number(itemData.preFrameHeight); 244 frameSpacing.preX[index] = Number(itemData.preX); 245 frameSpacing.preY[index] = Number(itemData.preY); 246 } 247 postFrameSpacingMessage(data, transfer, frameSpacing, res.length); 248} 249function postFrameSpacingMessage(data: any, transfer: boolean, frameSpacing: FrameSpacing, len: number) { 250 (self as unknown as Worker).postMessage( 251 { 252 id: data.id, 253 action: data.action, 254 results: transfer 255 ? { 256 id: frameSpacing.id.buffer, 257 x: frameSpacing.x.buffer, 258 y: frameSpacing.y.buffer, 259 currentFrameWidth: frameSpacing.currentFrameWidth.buffer, 260 currentFrameHeight: frameSpacing.currentFrameHeight.buffer, 261 currentTs: frameSpacing.currentTs.buffer, 262 frameSpacingResult: frameSpacing.frameSpacingResult.buffer, 263 preTs: frameSpacing.preTs.buffer, 264 preFrameWidth: frameSpacing.preFrameWidth.buffer, 265 preFrameHeight: frameSpacing.preFrameHeight.buffer, 266 preX: frameSpacing.preX.buffer, 267 preY: frameSpacing.preY.buffer, 268 } 269 : {}, 270 len: len, 271 transfer: transfer, 272 }, 273 transfer 274 ? [ 275 frameSpacing.id.buffer, 276 frameSpacing.x.buffer, 277 frameSpacing.y.buffer, 278 frameSpacing.currentFrameWidth.buffer, 279 frameSpacing.currentFrameHeight.buffer, 280 frameSpacing.currentTs.buffer, 281 frameSpacing.frameSpacingResult.buffer, 282 frameSpacing.preTs.buffer, 283 frameSpacing.preFrameWidth.buffer, 284 frameSpacing.preFrameHeight.buffer, 285 frameSpacing.preX.buffer, 286 frameSpacing.preY.buffer, 287 ] 288 : [] 289 ); 290} 291function setSpacingStructs( 292 nameDataMap: Map<string, Array<FrameSpacingStruct>>, 293 itemData: FrameSpacingStruct, 294 data: any 295) { 296 let unitIndex: number = 1; 297 let secondToNanosecond: number = 1000_000_000; 298 let spacingStructs = nameDataMap.get(itemData.nameId!); 299 if (spacingStructs) { 300 let lastIndexData = spacingStructs[spacingStructs.length - 1]; 301 let intervalTime = (itemData.currentTs - lastIndexData.currentTs) / secondToNanosecond; 302 let widthDifference = Number(itemData.currentFrameWidth!) - Number(lastIndexData.currentFrameWidth!); 303 let heightDifference = Number(itemData.currentFrameHeight!) - Number(lastIndexData.currentFrameHeight!); 304 let xDifference = Number(itemData.x!) - Number(lastIndexData.x!); 305 let yDifference = Number(itemData.y!) - Number(lastIndexData.y!); 306 let frameWidth = Math.abs(widthDifference / data.params.physicalWidth / intervalTime); 307 let frameHeight = Math.abs(heightDifference / data.params.physicalHeight / intervalTime); 308 let frameX = Math.abs(xDifference / data.params.physicalWidth / intervalTime); 309 let frameY = Math.abs(yDifference / data.params.physicalHeight / intervalTime); 310 let result = Math.max(frameWidth, frameHeight, frameX, frameY); 311 itemData.frameSpacingResult = Number(result.toFixed(unitIndex)); 312 itemData.preTs = lastIndexData.currentTs; 313 itemData.preFrameWidth = Number(lastIndexData.currentFrameWidth); 314 itemData.preFrameHeight = Number(lastIndexData.currentFrameHeight); 315 itemData.preX = Number(lastIndexData.x); 316 itemData.preY = Number(lastIndexData.y); 317 spacingStructs.push(itemData); 318 } 319} 320function setNameDataMap(nameDataMap: Map<string, Array<FrameSpacingStruct>>, itemData: FrameSpacingStruct) { 321 itemData.frameSpacingResult = 0; 322 itemData.preTs = 0; 323 itemData.preFrameWidth = 0; 324 itemData.preFrameHeight = 0; 325 itemData.preX = 0; 326 itemData.preY = 0; 327 nameDataMap.set(itemData.nameId!, [itemData]); 328} 329class FrameSpacing { 330 id: Uint16Array; 331 x: Float32Array; 332 y: Float32Array; 333 currentFrameWidth: Float32Array; 334 currentFrameHeight: Float32Array; 335 currentTs: Float64Array; 336 frameSpacingResult: Float32Array; 337 preTs: Float64Array; 338 preFrameWidth: Float32Array; 339 preFrameHeight: Float32Array; 340 preX: Float32Array; 341 preY: Float32Array; 342 343 constructor(data: any, len: any[], transfer: boolean) { 344 this.id = new Uint16Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 345 this.x = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 346 this.y = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 347 this.currentFrameWidth = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 348 this.currentFrameHeight = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 349 this.currentTs = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 350 this.frameSpacingResult = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 351 this.preTs = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 352 this.preFrameWidth = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 353 this.preFrameHeight = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 354 this.preX = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 355 this.preY = new Float32Array(transfer ? len : data.params.sharedArrayBuffers.animationId); 356 } 357} 358