@meframe/core 0.0.31 → 0.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Meframe.d.ts +2 -2
- package/dist/Meframe.d.ts.map +1 -1
- package/dist/Meframe.js +3 -2
- package/dist/Meframe.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +12 -17
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +18 -280
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/l1/AudioL1Cache.d.ts +36 -19
- package/dist/cache/l1/AudioL1Cache.d.ts.map +1 -1
- package/dist/cache/l1/AudioL1Cache.js +182 -282
- package/dist/cache/l1/AudioL1Cache.js.map +1 -1
- package/dist/controllers/PlaybackController.d.ts +4 -2
- package/dist/controllers/PlaybackController.d.ts.map +1 -1
- package/dist/controllers/PlaybackController.js +43 -13
- package/dist/controllers/PlaybackController.js.map +1 -1
- package/dist/model/types.d.ts +0 -4
- package/dist/model/types.d.ts.map +1 -1
- package/dist/model/types.js.map +1 -1
- package/dist/orchestrator/ExportScheduler.d.ts +6 -0
- package/dist/orchestrator/ExportScheduler.d.ts.map +1 -1
- package/dist/orchestrator/ExportScheduler.js +45 -66
- package/dist/orchestrator/ExportScheduler.js.map +1 -1
- package/dist/orchestrator/GlobalAudioSession.d.ts +35 -28
- package/dist/orchestrator/GlobalAudioSession.d.ts.map +1 -1
- package/dist/orchestrator/GlobalAudioSession.js +212 -421
- package/dist/orchestrator/GlobalAudioSession.js.map +1 -1
- package/dist/orchestrator/OnDemandVideoSession.d.ts +3 -3
- package/dist/orchestrator/OnDemandVideoSession.d.ts.map +1 -1
- package/dist/orchestrator/OnDemandVideoSession.js +4 -4
- package/dist/orchestrator/OnDemandVideoSession.js.map +1 -1
- package/dist/orchestrator/Orchestrator.d.ts +1 -2
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.js +34 -48
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/orchestrator/VideoClipSession.d.ts +0 -2
- package/dist/orchestrator/VideoClipSession.d.ts.map +1 -1
- package/dist/orchestrator/VideoClipSession.js +0 -49
- package/dist/orchestrator/VideoClipSession.js.map +1 -1
- package/dist/stages/compose/OfflineAudioMixer.d.ts.map +1 -1
- package/dist/stages/compose/OfflineAudioMixer.js +13 -18
- package/dist/stages/compose/OfflineAudioMixer.js.map +1 -1
- package/dist/stages/decode/AudioChunkDecoder.js +169 -0
- package/dist/stages/decode/AudioChunkDecoder.js.map +1 -0
- package/dist/stages/demux/MP3FrameParser.js +186 -0
- package/dist/stages/demux/MP3FrameParser.js.map +1 -0
- package/dist/stages/load/ResourceLoader.d.ts +20 -9
- package/dist/stages/load/ResourceLoader.d.ts.map +1 -1
- package/dist/stages/load/ResourceLoader.js +92 -135
- package/dist/stages/load/ResourceLoader.js.map +1 -1
- package/dist/stages/load/types.d.ts +1 -0
- package/dist/stages/load/types.d.ts.map +1 -1
- package/dist/utils/audio-data.d.ts +16 -0
- package/dist/utils/audio-data.d.ts.map +1 -0
- package/dist/utils/audio-data.js +111 -0
- package/dist/utils/audio-data.js.map +1 -0
- package/package.json +1 -1
- package/dist/cache/resource/ImageBitmapCache.d.ts +0 -65
- package/dist/cache/resource/ImageBitmapCache.d.ts.map +0 -1
- package/dist/cache/resource/ImageBitmapCache.js +0 -101
- package/dist/cache/resource/ImageBitmapCache.js.map +0 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
function extractPlanesFromAudioData(audioData, numberOfChannels, numberOfFrames) {
|
|
2
|
+
const planes = Array.from(
|
|
3
|
+
{ length: numberOfChannels },
|
|
4
|
+
() => new Float32Array(numberOfFrames)
|
|
5
|
+
);
|
|
6
|
+
const toFloat = (value) => Math.max(-1, Math.min(1, value / 32768));
|
|
7
|
+
const fillInterleaved = (format) => {
|
|
8
|
+
const samples = format === "f32" ? new Float32Array(numberOfFrames * numberOfChannels) : new Int16Array(numberOfFrames * numberOfChannels);
|
|
9
|
+
try {
|
|
10
|
+
audioData.copyTo(samples, { format, planeIndex: 0 });
|
|
11
|
+
} catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
for (let frame = 0; frame < numberOfFrames; frame += 1) {
|
|
15
|
+
const offset = frame * numberOfChannels;
|
|
16
|
+
for (let channel = 0; channel < numberOfChannels; channel += 1) {
|
|
17
|
+
const plane = planes[channel];
|
|
18
|
+
if (!plane) continue;
|
|
19
|
+
if (format === "f32") {
|
|
20
|
+
plane[frame] = samples[offset + channel] ?? 0;
|
|
21
|
+
} else {
|
|
22
|
+
plane[frame] = toFloat(samples[offset + channel] ?? 0);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
};
|
|
28
|
+
const fillPlanar = (format) => {
|
|
29
|
+
try {
|
|
30
|
+
if (format === "f32-planar") {
|
|
31
|
+
for (let channel = 0; channel < numberOfChannels; channel += 1) {
|
|
32
|
+
const plane = planes[channel];
|
|
33
|
+
if (!plane) continue;
|
|
34
|
+
audioData.copyTo(plane, { planeIndex: channel, format: "f32-planar" });
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
const tmp = new Int16Array(numberOfFrames);
|
|
39
|
+
for (let channel = 0; channel < numberOfChannels; channel += 1) {
|
|
40
|
+
const plane = planes[channel];
|
|
41
|
+
if (!plane) continue;
|
|
42
|
+
audioData.copyTo(tmp, { planeIndex: channel, format: "s16-planar" });
|
|
43
|
+
for (let i = 0; i < numberOfFrames; i += 1) {
|
|
44
|
+
plane[i] = toFloat(tmp[i] ?? 0);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
} catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const fillFallback = () => {
|
|
53
|
+
try {
|
|
54
|
+
for (let channel = 0; channel < numberOfChannels; channel += 1) {
|
|
55
|
+
const plane = planes[channel];
|
|
56
|
+
if (!plane) continue;
|
|
57
|
+
audioData.copyTo(plane, { planeIndex: channel });
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
} catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const reportedFormat = audioData.format;
|
|
65
|
+
const attempts = [];
|
|
66
|
+
const scheduled = /* @__PURE__ */ new Set();
|
|
67
|
+
const scheduleAttempt = (token, attempt) => {
|
|
68
|
+
if (!scheduled.has(token)) {
|
|
69
|
+
scheduled.add(token);
|
|
70
|
+
attempts.push(attempt);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
if (reportedFormat) {
|
|
74
|
+
switch (reportedFormat) {
|
|
75
|
+
case "f32":
|
|
76
|
+
scheduleAttempt("f32", () => fillInterleaved("f32"));
|
|
77
|
+
break;
|
|
78
|
+
case "s16":
|
|
79
|
+
scheduleAttempt("s16", () => fillInterleaved("s16"));
|
|
80
|
+
break;
|
|
81
|
+
case "f32-planar":
|
|
82
|
+
scheduleAttempt("f32-planar", () => fillPlanar("f32-planar"));
|
|
83
|
+
break;
|
|
84
|
+
case "s16-planar":
|
|
85
|
+
scheduleAttempt("s16-planar", () => fillPlanar("s16-planar"));
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
scheduleAttempt("f32-planar", () => fillPlanar("f32-planar"));
|
|
90
|
+
scheduleAttempt("f32", () => fillInterleaved("f32"));
|
|
91
|
+
scheduleAttempt("s16-planar", () => fillPlanar("s16-planar"));
|
|
92
|
+
scheduleAttempt("s16", () => fillInterleaved("s16"));
|
|
93
|
+
let filled = false;
|
|
94
|
+
for (const attempt of attempts) {
|
|
95
|
+
if (attempt()) {
|
|
96
|
+
filled = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!filled) {
|
|
101
|
+
filled = fillFallback();
|
|
102
|
+
}
|
|
103
|
+
if (!filled) {
|
|
104
|
+
throw new Error("AudioL1Cache: unsupported AudioData format");
|
|
105
|
+
}
|
|
106
|
+
return planes;
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
extractPlanesFromAudioData
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=audio-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-data.js","sources":["../../src/utils/audio-data.ts"],"sourcesContent":["/**\n * Utility functions for processing AudioData and PCM buffers\n */\n\nexport interface AudioMetadata {\n sampleRate: number;\n numberOfChannels: number;\n}\n\n/**\n * Extract PCM data from AudioData object into Float32Array planes\n */\nexport function extractPlanesFromAudioData(\n audioData: AudioData,\n numberOfChannels: number,\n numberOfFrames: number\n): Float32Array[] {\n const planes: Float32Array[] = Array.from(\n { length: numberOfChannels },\n () => new Float32Array(numberOfFrames)\n );\n\n // Improved s16 to f32 conversion with range limiting\n const toFloat = (value: number): number => Math.max(-1, Math.min(1, value / 32768.0));\n\n const fillInterleaved = (format: 'f32' | 's16'): boolean => {\n const samples =\n format === 'f32'\n ? new Float32Array(numberOfFrames * numberOfChannels)\n : new Int16Array(numberOfFrames * numberOfChannels);\n\n try {\n audioData.copyTo(samples, { format, planeIndex: 0 });\n } catch {\n return false;\n }\n\n for (let frame = 0; frame < numberOfFrames; frame += 1) {\n const offset = frame * numberOfChannels;\n for (let channel = 0; channel < numberOfChannels; channel += 1) {\n const plane = planes[channel];\n if (!plane) continue;\n if (format === 'f32') {\n plane[frame] = (samples as Float32Array)[offset + channel] ?? 0;\n } else {\n plane[frame] = toFloat((samples as Int16Array)[offset + channel] ?? 0);\n }\n }\n }\n\n return true;\n };\n\n const fillPlanar = (format: 'f32-planar' | 's16-planar'): boolean => {\n try {\n if (format === 'f32-planar') {\n for (let channel = 0; channel < numberOfChannels; channel += 1) {\n const plane = planes[channel];\n if (!plane) continue;\n audioData.copyTo(plane, { planeIndex: channel, format: 'f32-planar' });\n }\n return true;\n }\n\n const tmp = new Int16Array(numberOfFrames);\n for (let channel = 0; channel < numberOfChannels; channel += 1) {\n const plane = planes[channel];\n if (!plane) continue;\n audioData.copyTo(tmp, { planeIndex: channel, format: 's16-planar' as any });\n for (let i = 0; i < numberOfFrames; i += 1) {\n plane[i] = toFloat(tmp[i] ?? 0);\n }\n }\n return true;\n } catch {\n return false;\n }\n };\n\n const fillFallback = (): boolean => {\n try {\n for (let channel = 0; channel < numberOfChannels; channel += 1) {\n const plane = planes[channel];\n if (!plane) continue;\n audioData.copyTo(plane, { planeIndex: channel });\n }\n return true;\n } catch {\n return false;\n }\n };\n\n const reportedFormat = (audioData as any).format as string | undefined;\n const attempts: Array<() => boolean> = [];\n const scheduled = new Set<string>();\n\n const scheduleAttempt = (token: string, attempt: () => boolean): void => {\n if (!scheduled.has(token)) {\n scheduled.add(token);\n attempts.push(attempt);\n }\n };\n\n if (reportedFormat) {\n switch (reportedFormat) {\n case 'f32':\n scheduleAttempt('f32', () => fillInterleaved('f32'));\n break;\n case 's16':\n scheduleAttempt('s16', () => fillInterleaved('s16'));\n break;\n case 'f32-planar':\n scheduleAttempt('f32-planar', () => fillPlanar('f32-planar'));\n break;\n case 's16-planar':\n scheduleAttempt('s16-planar', () => fillPlanar('s16-planar'));\n break;\n default:\n break;\n }\n }\n\n // Prioritize f32-planar to avoid unnecessary conversions\n scheduleAttempt('f32-planar', () => fillPlanar('f32-planar'));\n scheduleAttempt('f32', () => fillInterleaved('f32'));\n scheduleAttempt('s16-planar', () => fillPlanar('s16-planar'));\n scheduleAttempt('s16', () => fillInterleaved('s16'));\n\n let filled = false;\n for (const attempt of attempts) {\n if (attempt()) {\n filled = true;\n break;\n }\n }\n\n if (!filled) {\n filled = fillFallback();\n }\n\n if (!filled) {\n throw new Error('AudioL1Cache: unsupported AudioData format');\n }\n\n return planes;\n}\n\n/**\n * Apply volume/gain to PCM data\n */\nexport function applyGain(planes: Float32Array[], volume: number, muted: boolean): Float32Array[] {\n if (muted || volume === 0) {\n return planes.map((plane) => new Float32Array(plane.length));\n }\n\n if (volume === 1) {\n return planes.map((plane) => plane.slice());\n }\n\n return planes.map((plane) => {\n const scaled = new Float32Array(plane.length);\n for (let i = 0; i < plane.length; i += 1) {\n scaled[i] = (plane[i] ?? 0) * volume;\n }\n return scaled;\n });\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
export interface ImageBitmapRecord {
|
|
2
|
-
resourceId: string;
|
|
3
|
-
bitmap: ImageBitmap;
|
|
4
|
-
width: number;
|
|
5
|
-
height: number;
|
|
6
|
-
sizeBytes: number;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* ImageBitmapCache - Resource-level image bitmap cache
|
|
10
|
-
*
|
|
11
|
-
* Caches decoded ImageBitmap for image resources in main thread
|
|
12
|
-
* Used by OnDemandComposeSession for image clip composition
|
|
13
|
-
*
|
|
14
|
-
* Strategy:
|
|
15
|
-
* - Store ImageBitmap after ResourceLoader downloads image
|
|
16
|
-
* - Keep in main thread memory for direct access
|
|
17
|
-
* - Close and evict when memory pressure is high
|
|
18
|
-
*
|
|
19
|
-
* Memory usage:
|
|
20
|
-
* - Typical image (1080p): width * height * 4 bytes = ~8MB
|
|
21
|
-
* - Cache ~10 images max to stay under ~100MB
|
|
22
|
-
*/
|
|
23
|
-
export declare class ImageBitmapCache {
|
|
24
|
-
private cache;
|
|
25
|
-
private maxCacheSizeMB;
|
|
26
|
-
private currentSizeBytes;
|
|
27
|
-
constructor(maxCacheSizeMB?: number);
|
|
28
|
-
/**
|
|
29
|
-
* Set image bitmap for a resource
|
|
30
|
-
*/
|
|
31
|
-
set(resourceId: string, bitmap: ImageBitmap): void;
|
|
32
|
-
/**
|
|
33
|
-
* Get image bitmap for a resource
|
|
34
|
-
*/
|
|
35
|
-
get(resourceId: string): ImageBitmap | null;
|
|
36
|
-
/**
|
|
37
|
-
* Get full record with metadata
|
|
38
|
-
*/
|
|
39
|
-
getRecord(resourceId: string): ImageBitmapRecord | null;
|
|
40
|
-
/**
|
|
41
|
-
* Check if resource has bitmap cached
|
|
42
|
-
*/
|
|
43
|
-
has(resourceId: string): boolean;
|
|
44
|
-
/**
|
|
45
|
-
* Delete bitmap for a resource
|
|
46
|
-
*/
|
|
47
|
-
delete(resourceId: string): void;
|
|
48
|
-
/**
|
|
49
|
-
* Clear all cached bitmaps
|
|
50
|
-
*/
|
|
51
|
-
clear(): void;
|
|
52
|
-
/**
|
|
53
|
-
* Get total memory usage in bytes
|
|
54
|
-
*/
|
|
55
|
-
getTotalBytes(): number;
|
|
56
|
-
/**
|
|
57
|
-
* Get total memory usage in MB
|
|
58
|
-
*/
|
|
59
|
-
getTotalMB(): number;
|
|
60
|
-
/**
|
|
61
|
-
* Evict oldest entries if over size limit
|
|
62
|
-
*/
|
|
63
|
-
private evictIfNeeded;
|
|
64
|
-
}
|
|
65
|
-
//# sourceMappingURL=ImageBitmapCache.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ImageBitmapCache.d.ts","sourceRoot":"","sources":["../../../src/cache/resource/ImageBitmapCache.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAwC;IACrD,OAAO,CAAC,cAAc,CAAO;IAC7B,OAAO,CAAC,gBAAgB,CAAK;gBAEjB,cAAc,SAAM;IAIhC;;OAEG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI;IA0BlD;;OAEG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAK3C;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IAIvD;;OAEG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIhC;;OAEG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAShC;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,UAAU,IAAI,MAAM;IAIpB;;OAEG;IACH,OAAO,CAAC,aAAa;CAetB"}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
class ImageBitmapCache {
|
|
2
|
-
cache = /* @__PURE__ */ new Map();
|
|
3
|
-
maxCacheSizeMB = 100;
|
|
4
|
-
// Default 100MB
|
|
5
|
-
currentSizeBytes = 0;
|
|
6
|
-
constructor(maxCacheSizeMB = 100) {
|
|
7
|
-
this.maxCacheSizeMB = maxCacheSizeMB;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Set image bitmap for a resource
|
|
11
|
-
*/
|
|
12
|
-
set(resourceId, bitmap) {
|
|
13
|
-
const existing = this.cache.get(resourceId);
|
|
14
|
-
if (existing) {
|
|
15
|
-
existing.bitmap.close();
|
|
16
|
-
this.currentSizeBytes -= existing.sizeBytes;
|
|
17
|
-
}
|
|
18
|
-
const sizeBytes = bitmap.width * bitmap.height * 4;
|
|
19
|
-
const record = {
|
|
20
|
-
resourceId,
|
|
21
|
-
bitmap,
|
|
22
|
-
width: bitmap.width,
|
|
23
|
-
height: bitmap.height,
|
|
24
|
-
sizeBytes
|
|
25
|
-
};
|
|
26
|
-
this.cache.set(resourceId, record);
|
|
27
|
-
this.currentSizeBytes += sizeBytes;
|
|
28
|
-
this.evictIfNeeded();
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Get image bitmap for a resource
|
|
32
|
-
*/
|
|
33
|
-
get(resourceId) {
|
|
34
|
-
const record = this.cache.get(resourceId);
|
|
35
|
-
return record ? record.bitmap : null;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Get full record with metadata
|
|
39
|
-
*/
|
|
40
|
-
getRecord(resourceId) {
|
|
41
|
-
return this.cache.get(resourceId) || null;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Check if resource has bitmap cached
|
|
45
|
-
*/
|
|
46
|
-
has(resourceId) {
|
|
47
|
-
return this.cache.has(resourceId);
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Delete bitmap for a resource
|
|
51
|
-
*/
|
|
52
|
-
delete(resourceId) {
|
|
53
|
-
const record = this.cache.get(resourceId);
|
|
54
|
-
if (record) {
|
|
55
|
-
record.bitmap.close();
|
|
56
|
-
this.currentSizeBytes -= record.sizeBytes;
|
|
57
|
-
this.cache.delete(resourceId);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Clear all cached bitmaps
|
|
62
|
-
*/
|
|
63
|
-
clear() {
|
|
64
|
-
for (const record of this.cache.values()) {
|
|
65
|
-
record.bitmap.close();
|
|
66
|
-
}
|
|
67
|
-
this.cache.clear();
|
|
68
|
-
this.currentSizeBytes = 0;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Get total memory usage in bytes
|
|
72
|
-
*/
|
|
73
|
-
getTotalBytes() {
|
|
74
|
-
return this.currentSizeBytes;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Get total memory usage in MB
|
|
78
|
-
*/
|
|
79
|
-
getTotalMB() {
|
|
80
|
-
return this.currentSizeBytes / (1024 * 1024);
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Evict oldest entries if over size limit
|
|
84
|
-
*/
|
|
85
|
-
evictIfNeeded() {
|
|
86
|
-
const maxBytes = this.maxCacheSizeMB * 1024 * 1024;
|
|
87
|
-
if (this.currentSizeBytes > maxBytes) {
|
|
88
|
-
const entries = Array.from(this.cache.entries());
|
|
89
|
-
let evictIndex = 0;
|
|
90
|
-
while (this.currentSizeBytes > maxBytes && evictIndex < entries.length) {
|
|
91
|
-
const [resourceId] = entries[evictIndex];
|
|
92
|
-
this.delete(resourceId);
|
|
93
|
-
evictIndex++;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
export {
|
|
99
|
-
ImageBitmapCache
|
|
100
|
-
};
|
|
101
|
-
//# sourceMappingURL=ImageBitmapCache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ImageBitmapCache.js","sources":["../../../src/cache/resource/ImageBitmapCache.ts"],"sourcesContent":["export interface ImageBitmapRecord {\n resourceId: string;\n bitmap: ImageBitmap;\n width: number;\n height: number;\n sizeBytes: number; // Estimated memory usage\n}\n\n/**\n * ImageBitmapCache - Resource-level image bitmap cache\n *\n * Caches decoded ImageBitmap for image resources in main thread\n * Used by OnDemandComposeSession for image clip composition\n *\n * Strategy:\n * - Store ImageBitmap after ResourceLoader downloads image\n * - Keep in main thread memory for direct access\n * - Close and evict when memory pressure is high\n *\n * Memory usage:\n * - Typical image (1080p): width * height * 4 bytes = ~8MB\n * - Cache ~10 images max to stay under ~100MB\n */\nexport class ImageBitmapCache {\n private cache = new Map<string, ImageBitmapRecord>();\n private maxCacheSizeMB = 100; // Default 100MB\n private currentSizeBytes = 0;\n\n constructor(maxCacheSizeMB = 100) {\n this.maxCacheSizeMB = maxCacheSizeMB;\n }\n\n /**\n * Set image bitmap for a resource\n */\n set(resourceId: string, bitmap: ImageBitmap): void {\n // Close existing bitmap if present\n const existing = this.cache.get(resourceId);\n if (existing) {\n existing.bitmap.close();\n this.currentSizeBytes -= existing.sizeBytes;\n }\n\n // Estimate memory usage (RGBA format)\n const sizeBytes = bitmap.width * bitmap.height * 4;\n\n const record: ImageBitmapRecord = {\n resourceId,\n bitmap,\n width: bitmap.width,\n height: bitmap.height,\n sizeBytes,\n };\n\n this.cache.set(resourceId, record);\n this.currentSizeBytes += sizeBytes;\n\n // Evict if over limit (simple FIFO for now)\n this.evictIfNeeded();\n }\n\n /**\n * Get image bitmap for a resource\n */\n get(resourceId: string): ImageBitmap | null {\n const record = this.cache.get(resourceId);\n return record ? record.bitmap : null;\n }\n\n /**\n * Get full record with metadata\n */\n getRecord(resourceId: string): ImageBitmapRecord | null {\n return this.cache.get(resourceId) || null;\n }\n\n /**\n * Check if resource has bitmap cached\n */\n has(resourceId: string): boolean {\n return this.cache.has(resourceId);\n }\n\n /**\n * Delete bitmap for a resource\n */\n delete(resourceId: string): void {\n const record = this.cache.get(resourceId);\n if (record) {\n record.bitmap.close();\n this.currentSizeBytes -= record.sizeBytes;\n this.cache.delete(resourceId);\n }\n }\n\n /**\n * Clear all cached bitmaps\n */\n clear(): void {\n for (const record of this.cache.values()) {\n record.bitmap.close();\n }\n this.cache.clear();\n this.currentSizeBytes = 0;\n }\n\n /**\n * Get total memory usage in bytes\n */\n getTotalBytes(): number {\n return this.currentSizeBytes;\n }\n\n /**\n * Get total memory usage in MB\n */\n getTotalMB(): number {\n return this.currentSizeBytes / (1024 * 1024);\n }\n\n /**\n * Evict oldest entries if over size limit\n */\n private evictIfNeeded(): void {\n const maxBytes = this.maxCacheSizeMB * 1024 * 1024;\n\n // Simple FIFO eviction: remove oldest entries until under limit\n if (this.currentSizeBytes > maxBytes) {\n const entries = Array.from(this.cache.entries());\n let evictIndex = 0;\n\n while (this.currentSizeBytes > maxBytes && evictIndex < entries.length) {\n const [resourceId] = entries[evictIndex]!;\n this.delete(resourceId);\n evictIndex++;\n }\n }\n }\n}\n"],"names":[],"mappings":"AAuBO,MAAM,iBAAiB;AAAA,EACpB,4BAAY,IAAA;AAAA,EACZ,iBAAiB;AAAA;AAAA,EACjB,mBAAmB;AAAA,EAE3B,YAAY,iBAAiB,KAAK;AAChC,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAAoB,QAA2B;AAEjD,UAAM,WAAW,KAAK,MAAM,IAAI,UAAU;AAC1C,QAAI,UAAU;AACZ,eAAS,OAAO,MAAA;AAChB,WAAK,oBAAoB,SAAS;AAAA,IACpC;AAGA,UAAM,YAAY,OAAO,QAAQ,OAAO,SAAS;AAEjD,UAAM,SAA4B;AAAA,MAChC;AAAA,MACA;AAAA,MACA,OAAO,OAAO;AAAA,MACd,QAAQ,OAAO;AAAA,MACf;AAAA,IAAA;AAGF,SAAK,MAAM,IAAI,YAAY,MAAM;AACjC,SAAK,oBAAoB;AAGzB,SAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAAwC;AAC1C,UAAM,SAAS,KAAK,MAAM,IAAI,UAAU;AACxC,WAAO,SAAS,OAAO,SAAS;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,YAA8C;AACtD,WAAO,KAAK,MAAM,IAAI,UAAU,KAAK;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAA6B;AAC/B,WAAO,KAAK,MAAM,IAAI,UAAU;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,YAA0B;AAC/B,UAAM,SAAS,KAAK,MAAM,IAAI,UAAU;AACxC,QAAI,QAAQ;AACV,aAAO,OAAO,MAAA;AACd,WAAK,oBAAoB,OAAO;AAChC,WAAK,MAAM,OAAO,UAAU;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,eAAW,UAAU,KAAK,MAAM,OAAA,GAAU;AACxC,aAAO,OAAO,MAAA;AAAA,IAChB;AACA,SAAK,MAAM,MAAA;AACX,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,aAAqB;AACnB,WAAO,KAAK,oBAAoB,OAAO;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAsB;AAC5B,UAAM,WAAW,KAAK,iBAAiB,OAAO;AAG9C,QAAI,KAAK,mBAAmB,UAAU;AACpC,YAAM,UAAU,MAAM,KAAK,KAAK,MAAM,SAAS;AAC/C,UAAI,aAAa;AAEjB,aAAO,KAAK,mBAAmB,YAAY,aAAa,QAAQ,QAAQ;AACtE,cAAM,CAAC,UAAU,IAAI,QAAQ,UAAU;AACvC,aAAK,OAAO,UAAU;AACtB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;"}
|