@nativescript/canvas-media 2.0.26 → 2.0.28
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/audio/common.d.ts +1 -0
- package/audio/common.js +20 -8
- package/audio/common.js.map +1 -1
- package/package.json +1 -1
- package/platforms/android/canvas_media.aar +0 -0
- package/platforms/android/java/org/nativescript/canvas/media/AudioContextTapProcessor.java +31 -21
- package/platforms/android/java/org/nativescript/canvas/media/AudioHelper.java +307 -104
- package/platforms/ios/src/NSCAudioHelper.m +11 -11
- package/platforms/ios/src/NSCAudioView.m +49 -34
- package/platforms/ios/src/NSCVideoHelper.m +56 -64
- package/video/common.d.ts +1 -0
- package/video/common.js +21 -6
- package/video/common.js.map +1 -1
package/audio/common.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export declare abstract class AudioBase extends MediaBase {
|
|
|
26
26
|
_listeners: Record<string, Function[]>;
|
|
27
27
|
addEventListener(type: string, listener: Function, useCapture?: boolean | any): void;
|
|
28
28
|
removeEventListener(type: string, listener: Function, useCapture?: boolean | any): void;
|
|
29
|
+
private _invokeListener;
|
|
29
30
|
_notifyListener(type: string): void;
|
|
30
31
|
_removeListener(type: string, listener: Function, listenersObj: any): void;
|
|
31
32
|
_listenerExist(type: string, listener: Function, listenersObj: any): boolean;
|
package/audio/common.js
CHANGED
|
@@ -6,6 +6,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { CSSType } from '@nativescript/core';
|
|
8
8
|
import { MediaBase } from '../common';
|
|
9
|
+
function warnAudioListener(label, _error) {
|
|
10
|
+
try {
|
|
11
|
+
console.warn(label);
|
|
12
|
+
}
|
|
13
|
+
catch { }
|
|
14
|
+
}
|
|
9
15
|
let AudioBase = class AudioBase extends MediaBase {
|
|
10
16
|
constructor() {
|
|
11
17
|
super(...arguments);
|
|
@@ -39,27 +45,33 @@ let AudioBase = class AudioBase extends MediaBase {
|
|
|
39
45
|
const target = isCapture ? this._capturedListeners : this._listeners;
|
|
40
46
|
this._removeListener(type, listener, target);
|
|
41
47
|
}
|
|
48
|
+
_invokeListener(type, listener, source) {
|
|
49
|
+
try {
|
|
50
|
+
listener.call(this);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
warnAudioListener(`Audio.${type} ${source} listener failed`, error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
42
56
|
_notifyListener(type) {
|
|
43
57
|
const captured = this._capturedListeners?.[type];
|
|
44
58
|
if (Array.isArray(captured)) {
|
|
45
59
|
for (let i = 0; i < captured.length; i++) {
|
|
46
60
|
const cb = captured[i];
|
|
47
61
|
if (typeof cb === 'function')
|
|
48
|
-
cb
|
|
62
|
+
this._invokeListener(type, cb, 'captured');
|
|
49
63
|
}
|
|
50
64
|
}
|
|
65
|
+
const handler = this[`on${type}`];
|
|
66
|
+
if (typeof handler === 'function') {
|
|
67
|
+
this._invokeListener(type, handler, 'property');
|
|
68
|
+
}
|
|
51
69
|
const events = this._listeners?.[type];
|
|
52
70
|
if (Array.isArray(events)) {
|
|
53
71
|
for (let i = 0; i < events.length; i++) {
|
|
54
72
|
const cb = events[i];
|
|
55
|
-
if (typeof this[type] === 'function') {
|
|
56
|
-
try {
|
|
57
|
-
this[type]();
|
|
58
|
-
}
|
|
59
|
-
catch (e) { }
|
|
60
|
-
}
|
|
61
73
|
if (typeof cb === 'function')
|
|
62
|
-
cb
|
|
74
|
+
this._invokeListener(type, cb, 'registered');
|
|
63
75
|
}
|
|
64
76
|
}
|
|
65
77
|
}
|
package/audio/common.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../../packages/canvas-media/audio/common.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../../packages/canvas-media/audio/common.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,SAAS,iBAAiB,CAAC,KAAa,EAAE,MAAgB;IACzD,IAAI,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACX,CAAC;AAGM,IAAe,SAAS,GAAxB,MAAe,SAAU,SAAQ,SAAS;IAA1C;;QA2BN,uBAAkB,GAAG,EAAgC,CAAC;QACtD,eAAU,GAAG,EAAgC,CAAC;IAuE/C,CAAC;IArEA,gBAAgB,CAAC,IAAY,EAAE,QAAkB,EAAE,UAA0B;QAC5E,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QAC3C,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,OAAO,UAAU,KAAK,SAAS;YAAE,SAAS,GAAG,UAAU,CAAC;aACvD,IAAI,OAAO,UAAU,KAAK,QAAQ;YAAE,SAAS,GAAG,UAAU,EAAE,OAAO,IAAI,KAAK,CAAC;QAElF,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QACrE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;YAClD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC3B,CAAC;QACF,CAAC;IACF,CAAC;IAED,mBAAmB,CAAC,IAAY,EAAE,QAAkB,EAAE,UAA0B;QAC/E,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,OAAO,UAAU,KAAK,SAAS;YAAE,SAAS,GAAG,UAAU,CAAC;aACvD,IAAI,OAAO,UAAU,KAAK,QAAQ;YAAE,SAAS,GAAG,UAAU,EAAE,OAAO,IAAI,KAAK,CAAC;QAClF,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QACrE,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAEO,eAAe,CAAC,IAAY,EAAE,QAAkB,EAAE,MAAc;QACvE,IAAI,CAAC;YACJ,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,iBAAiB,CAAC,SAAS,IAAI,IAAI,MAAM,kBAAkB,EAAE,KAAK,CAAC,CAAC;QACrE,CAAC;IACF,CAAC;IAED,eAAe,CAAC,IAAY;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC1C,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACvB,IAAI,OAAO,EAAE,KAAK,UAAU;oBAAE,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC;YAC1E,CAAC;QACF,CAAC;QAED,MAAM,OAAO,GAAI,IAAY,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QAC3C,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;gBACrB,IAAI,OAAO,EAAE,KAAK,UAAU;oBAAE,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC;YAC5E,CAAC;QACF,CAAC;IACF,CAAC;IAED,eAAe,CAAC,IAAY,EAAE,QAAkB,EAAE,YAAiB;QAClE,IAAI,CAAC,YAAY;YAAE,OAAO;QAC1B,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO;QAChC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,QAAe,CAAC,CAAC;QACzC,IAAI,GAAG,GAAG,CAAC,CAAC;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,cAAc,CAAC,IAAY,EAAE,QAAkB,EAAE,YAAiB;QACjE,IAAI,CAAC,YAAY;YAAE,OAAO,KAAK,CAAC;QAChC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACtC,OAAO,GAAG,CAAC,OAAO,CAAC,QAAe,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5C,CAAC;;AA7Fa,sBAAY,GAAG,SAAS,AAAZ,CAAa;AACzB,mBAAS,GAAG,MAAM,AAAT,CAAU;AACnB,oBAAU,GAAG,OAAO,AAAV,CAAW;AACrB,sBAAY,GAAG,SAAS,AAAZ,CAAa;AACzB,6BAAmB,GAAG,gBAAgB,AAAnB,CAAoB;AACvC,yBAAe,GAAG,YAAY,AAAf,CAAgB;AAC/B,6BAAmB,GAAG,gBAAgB,AAAnB,CAAoB;AACvC,6BAAmB,GAAG,gBAAgB,AAAnB,CAAoB;AACvC,yBAAe,GAAG,YAAY,AAAf,CAAgB;AAC/B,oBAAU,GAAG,OAAO,AAAV,CAAW;AACrB,oBAAU,GAAG,OAAO,AAAV,CAAW;AAEZ,sBAAY,GAAG,CAAC,AAAJ,CAAK;AACjB,uBAAa,GAAG,CAAC,AAAJ,CAAK;AAClB,2BAAiB,GAAG,CAAC,AAAJ,CAAK;AACtB,0BAAgB,GAAG,CAAC,AAAJ,CAAK;AACrB,0BAAgB,GAAG,CAAC,AAAJ,CAAK;AArBvB,SAAS;IAD9B,OAAO,CAAC,OAAO,CAAC;GACK,SAAS,CAmG9B"}
|
package/package.json
CHANGED
|
Binary file
|
|
@@ -7,6 +7,7 @@ import androidx.media3.common.util.UnstableApi;
|
|
|
7
7
|
import java.nio.ByteBuffer;
|
|
8
8
|
import java.nio.ByteOrder;
|
|
9
9
|
import java.nio.FloatBuffer;
|
|
10
|
+
import java.util.Arrays;
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
@UnstableApi
|
|
@@ -33,6 +34,9 @@ public class AudioContextTapProcessor extends BaseAudioProcessor {
|
|
|
33
34
|
|
|
34
35
|
@Override
|
|
35
36
|
public AudioFormat onConfigure(AudioFormat inputFormat) throws UnhandledAudioFormatException {
|
|
37
|
+
if (bytesPerSample(inputFormat.encoding) <= 0) {
|
|
38
|
+
throw new UnhandledAudioFormatException(inputFormat);
|
|
39
|
+
}
|
|
36
40
|
return inputFormat;
|
|
37
41
|
}
|
|
38
42
|
|
|
@@ -47,32 +51,38 @@ public class AudioContextTapProcessor extends BaseAudioProcessor {
|
|
|
47
51
|
int channels = fmt.channelCount;
|
|
48
52
|
int sampleRate = fmt.sampleRate;
|
|
49
53
|
int bytesPerSample = bytesPerSample(fmt.encoding);
|
|
54
|
+
int sampleCount = bytesPerSample > 0 ? remaining / bytesPerSample : 0;
|
|
55
|
+
int bytesToCopy = sampleCount * bytesPerSample;
|
|
56
|
+
int srcStart = inputBuffer.position();
|
|
57
|
+
|
|
58
|
+
if (sink != null && sink.isActive() && sampleCount > 0 && channels > 0 && sampleRate > 0) {
|
|
59
|
+
if (_floatScratch.length < sampleCount) {
|
|
60
|
+
_floatScratch = new float[Math.max(sampleCount, _floatScratch.length * 2)];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
ByteBuffer src = inputBuffer.duplicate();
|
|
64
|
+
src.order(byteOrderForEncoding(fmt.encoding));
|
|
65
|
+
src.position(srcStart);
|
|
66
|
+
src.limit(srcStart + bytesToCopy);
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
copyToFloat(src, _floatScratch, sampleCount, fmt.encoding);
|
|
70
|
+
sink.onPcmFrames(_floatScratch, sampleCount, sampleRate, channels);
|
|
71
|
+
} catch (Throwable t) {
|
|
72
|
+
android.util.Log.w("AudioContextTapProc", "sink threw", t);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
50
75
|
|
|
51
76
|
ByteBuffer out = replaceOutputBuffer(remaining);
|
|
52
|
-
int srcStart = inputBuffer.position();
|
|
53
77
|
out.put(inputBuffer);
|
|
54
78
|
out.flip();
|
|
79
|
+
}
|
|
55
80
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (_floatScratch.length < sampleCount) {
|
|
60
|
-
_floatScratch = new float[Math.max(sampleCount, _floatScratch.length * 2)];
|
|
61
|
-
}
|
|
62
|
-
ByteBuffer src = inputBuffer.duplicate();
|
|
63
|
-
src.order(ByteOrder.nativeOrder());
|
|
64
|
-
src.position(srcStart);
|
|
65
|
-
src.limit(srcStart + remaining);
|
|
66
|
-
copyToFloat(src, _floatScratch, sampleCount, fmt.encoding);
|
|
67
|
-
try {
|
|
68
|
-
sink.onPcmFrames(_floatScratch, sampleCount, sampleRate, channels);
|
|
69
|
-
} catch (Throwable t) {
|
|
70
|
-
android.util.Log.w("AudioContextTapProc", "sink threw", t);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
81
|
+
private static ByteOrder byteOrderForEncoding(int encoding) {
|
|
82
|
+
if (encoding == ENCODING_PCM_16BIT_BIG_ENDIAN) {
|
|
83
|
+
return ByteOrder.BIG_ENDIAN;
|
|
73
84
|
}
|
|
74
|
-
|
|
75
|
-
inputBuffer.position(srcStart + remaining);
|
|
85
|
+
return ByteOrder.LITTLE_ENDIAN;
|
|
76
86
|
}
|
|
77
87
|
|
|
78
88
|
private static int bytesPerSample(int encoding) {
|
|
@@ -132,7 +142,7 @@ public class AudioContextTapProcessor extends BaseAudioProcessor {
|
|
|
132
142
|
break;
|
|
133
143
|
}
|
|
134
144
|
default: {
|
|
135
|
-
|
|
145
|
+
Arrays.fill(dst, 0, sampleCount, 0f);
|
|
136
146
|
break;
|
|
137
147
|
}
|
|
138
148
|
}
|
|
@@ -12,14 +12,28 @@ import java.io.File;
|
|
|
12
12
|
import java.util.Collections;
|
|
13
13
|
import java.util.Timer;
|
|
14
14
|
import java.util.TimerTask;
|
|
15
|
+
import java.util.List;
|
|
15
16
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
16
|
-
|
|
17
|
+
import androidx.annotation.Nullable;
|
|
18
|
+
import androidx.media3.common.AudioAttributes;
|
|
19
|
+
import androidx.media3.common.DeviceInfo;
|
|
17
20
|
import androidx.media3.common.MediaItem;
|
|
21
|
+
import androidx.media3.common.MediaMetadata;
|
|
22
|
+
import androidx.media3.common.Metadata;
|
|
18
23
|
import androidx.media3.common.PlaybackException;
|
|
19
|
-
import androidx.media3.common.
|
|
24
|
+
import androidx.media3.common.PlaybackParameters;
|
|
20
25
|
import androidx.media3.common.Player;
|
|
26
|
+
import androidx.media3.common.Timeline;
|
|
27
|
+
import androidx.media3.common.TrackSelectionParameters;
|
|
28
|
+
import androidx.media3.common.Tracks;
|
|
29
|
+
import androidx.media3.common.VideoSize;
|
|
30
|
+
import androidx.media3.common.text.Cue;
|
|
31
|
+
import androidx.media3.common.text.CueGroup;
|
|
21
32
|
import androidx.media3.common.util.UnstableApi;
|
|
22
33
|
import androidx.media3.common.util.Util;
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
23
37
|
import androidx.media3.datasource.DefaultDataSource;
|
|
24
38
|
import androidx.media3.datasource.DefaultHttpDataSource;
|
|
25
39
|
import androidx.media3.datasource.cache.CacheDataSource;
|
|
@@ -63,35 +77,32 @@ public class AudioHelper implements Player.Listener {
|
|
|
63
77
|
private volatile int _tapNodeChannels;
|
|
64
78
|
private volatile Method _tapNodePushFrames;
|
|
65
79
|
private volatile Method _tapNodeEndStream;
|
|
80
|
+
private volatile Method _tapNodeConfigureFormat;
|
|
66
81
|
private volatile Method _ctxCreateExternalPcm;
|
|
82
|
+
private volatile boolean _tapSuppressesDirectOutput = false;
|
|
83
|
+
private volatile boolean _muted = false;
|
|
84
|
+
private static final int MAX_TAP_REFLECTION_FAILURES = 8;
|
|
85
|
+
private final Object _tapStateLock = new Object();
|
|
86
|
+
private volatile int _tapReflectionFailures = 0;
|
|
67
87
|
|
|
68
88
|
private final AudioContextTapProcessor.Sink _tapSink = new AudioContextTapProcessor.Sink() {
|
|
69
89
|
@Override
|
|
70
90
|
public void onPcmFrames(float[] interleaved, int sampleCount, int sampleRate, int channels) {
|
|
71
91
|
Object node = _tapSourceNode;
|
|
72
|
-
|
|
92
|
+
Method push = _tapNodePushFrames;
|
|
93
|
+
if (node == null || push == null || sampleCount == 0 || sampleRate <= 0 || channels <= 0) return;
|
|
73
94
|
|
|
74
95
|
if (_tapNodeSampleRate != sampleRate || _tapNodeChannels != channels) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Method end = _tapNodeEndStream;
|
|
78
|
-
if (ctx == null || create == null) return;
|
|
79
|
-
Object replacement;
|
|
96
|
+
Method configure = _tapNodeConfigureFormat;
|
|
97
|
+
if (configure == null) return;
|
|
80
98
|
try {
|
|
81
|
-
|
|
99
|
+
configure.invoke(node, sampleRate, channels);
|
|
100
|
+
_tapNodeSampleRate = sampleRate;
|
|
101
|
+
_tapNodeChannels = channels;
|
|
82
102
|
} catch (Throwable t) {
|
|
83
|
-
|
|
103
|
+
handleTapReflectionFailure("configureFormat reflection failed", t);
|
|
84
104
|
return;
|
|
85
105
|
}
|
|
86
|
-
if (replacement == null) return;
|
|
87
|
-
Object old = _tapSourceNode;
|
|
88
|
-
if (old != null && end != null) {
|
|
89
|
-
try { end.invoke(old); } catch (Throwable ignored) {}
|
|
90
|
-
}
|
|
91
|
-
_tapSourceNode = replacement;
|
|
92
|
-
_tapNodeSampleRate = sampleRate;
|
|
93
|
-
_tapNodeChannels = channels;
|
|
94
|
-
node = replacement;
|
|
95
106
|
}
|
|
96
107
|
|
|
97
108
|
float[] payload = interleaved;
|
|
@@ -100,9 +111,10 @@ public class AudioHelper implements Player.Listener {
|
|
|
100
111
|
System.arraycopy(interleaved, 0, payload, 0, sampleCount);
|
|
101
112
|
}
|
|
102
113
|
try {
|
|
103
|
-
|
|
114
|
+
push.invoke(node, (Object) payload);
|
|
115
|
+
_tapReflectionFailures = 0;
|
|
104
116
|
} catch (Throwable t) {
|
|
105
|
-
|
|
117
|
+
handleTapReflectionFailure("pushFrames reflection failed", t);
|
|
106
118
|
}
|
|
107
119
|
}
|
|
108
120
|
|
|
@@ -112,6 +124,15 @@ public class AudioHelper implements Player.Listener {
|
|
|
112
124
|
}
|
|
113
125
|
};
|
|
114
126
|
|
|
127
|
+
private void handleTapReflectionFailure(String label, Throwable t) {
|
|
128
|
+
int failures = ++_tapReflectionFailures;
|
|
129
|
+
android.util.Log.w("AudioHelper", label, t);
|
|
130
|
+
if (failures >= MAX_TAP_REFLECTION_FAILURES) {
|
|
131
|
+
android.util.Log.w("AudioHelper", "disabling audio context tap after repeated failures");
|
|
132
|
+
detachAudioContextTap();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
115
136
|
public interface Callback {
|
|
116
137
|
void onDurationChange(long duration);
|
|
117
138
|
void onPlaying();
|
|
@@ -128,6 +149,40 @@ public class AudioHelper implements Player.Listener {
|
|
|
128
149
|
|
|
129
150
|
Handler handler;
|
|
130
151
|
|
|
152
|
+
private void safeInvoke(String label, Runnable action) {
|
|
153
|
+
try {
|
|
154
|
+
action.run();
|
|
155
|
+
} catch (Throwable t) {
|
|
156
|
+
android.util.Log.w("AudioHelper", label + " failed", t);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private void dispatchOnHandler(String label, Runnable action) {
|
|
161
|
+
Handler currentHandler = handler;
|
|
162
|
+
if (currentHandler == null) {
|
|
163
|
+
safeInvoke(label, action);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
Looper targetLooper = currentHandler.getLooper();
|
|
168
|
+
if (targetLooper != null && targetLooper == Looper.myLooper()) {
|
|
169
|
+
safeInvoke(label, action);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
currentHandler.post(() -> safeInvoke(label, action));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private void updateEffectivePlayerVolume() {
|
|
177
|
+
try {
|
|
178
|
+
if (_player != null) {
|
|
179
|
+
_player.setVolume((_muted || _tapSuppressesDirectOutput) ? 0f : 1f);
|
|
180
|
+
}
|
|
181
|
+
} catch (Throwable t) {
|
|
182
|
+
android.util.Log.w("AudioHelper", "updateEffectivePlayerVolume failed", t);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
131
186
|
public AudioHelper(Context context, String cacheRoot) {
|
|
132
187
|
File cacheDir = new File(cacheRoot, "MEDIA_PLAYER_CACHE");
|
|
133
188
|
if (!cacheDir.exists()) { cacheDir.mkdirs(); }
|
|
@@ -179,6 +234,7 @@ public class AudioHelper implements Player.Listener {
|
|
|
179
234
|
_player = builder.build();
|
|
180
235
|
_player.addListener(this);
|
|
181
236
|
_player.setAudioAttributes(AudioAttributes.DEFAULT, true);
|
|
237
|
+
updateEffectivePlayerVolume();
|
|
182
238
|
|
|
183
239
|
_container = new LinearLayout(context);
|
|
184
240
|
_container.setOrientation(LinearLayout.VERTICAL);
|
|
@@ -200,95 +256,224 @@ public class AudioHelper implements Player.Listener {
|
|
|
200
256
|
@Override
|
|
201
257
|
public void onIsPlayingChanged(boolean isPlaying) {
|
|
202
258
|
long duration = this._player.getDuration();
|
|
203
|
-
|
|
204
|
-
this._callback.onDurationChange(duration);
|
|
205
|
-
}
|
|
206
|
-
this._playing = isPlaying;
|
|
207
|
-
if (isPlaying) {
|
|
259
|
+
dispatchOnHandler("onIsPlayingChanged", () -> {
|
|
208
260
|
if (this._callback != null) {
|
|
209
|
-
this._callback.
|
|
210
|
-
this._callback.onLoadedData();
|
|
211
|
-
}
|
|
212
|
-
if (this._audioView != null) {
|
|
213
|
-
this._audioView.setPlaying(true);
|
|
214
|
-
this._audioView.setDuration(duration);
|
|
261
|
+
safeInvoke("onDurationChange callback", () -> this._callback.onDurationChange(duration));
|
|
215
262
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
AudioHelper that = this;
|
|
222
|
-
_timer.schedule(new TimerTask() {
|
|
223
|
-
@Override
|
|
224
|
-
public void run() {
|
|
225
|
-
handler.post(() -> {
|
|
226
|
-
long current = _player.getCurrentPosition();
|
|
227
|
-
if (that._callback != null) {
|
|
228
|
-
that._callback.onCurrentTimeChanged(current);
|
|
229
|
-
}
|
|
230
|
-
if (that._audioView != null) {
|
|
231
|
-
that._audioView.setCurrentTime(current);
|
|
232
|
-
}
|
|
233
|
-
});
|
|
263
|
+
this._playing = isPlaying;
|
|
264
|
+
if (isPlaying) {
|
|
265
|
+
if (this._callback != null) {
|
|
266
|
+
safeInvoke("onPlaying callback", () -> this._callback.onPlaying());
|
|
267
|
+
safeInvoke("onLoadedData callback", () -> this._callback.onLoadedData());
|
|
234
268
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
_timer
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
269
|
+
if (this._audioView != null) {
|
|
270
|
+
this._audioView.setPlaying(true);
|
|
271
|
+
this._audioView.setDuration(duration);
|
|
272
|
+
}
|
|
273
|
+
if (_timer != null) {
|
|
274
|
+
_timer.cancel();
|
|
275
|
+
_timer = null;
|
|
276
|
+
}
|
|
277
|
+
_timer = new Timer();
|
|
278
|
+
AudioHelper that = this;
|
|
279
|
+
_timer.schedule(new TimerTask() {
|
|
280
|
+
@Override
|
|
281
|
+
public void run() {
|
|
282
|
+
dispatchOnHandler("onCurrentTimeChanged", () -> {
|
|
283
|
+
long current = _player.getCurrentPosition();
|
|
284
|
+
if (that._callback != null) {
|
|
285
|
+
safeInvoke("onCurrentTimeChanged callback", () -> that._callback.onCurrentTimeChanged(current));
|
|
286
|
+
}
|
|
287
|
+
if (that._audioView != null) {
|
|
288
|
+
that._audioView.setCurrentTime(current);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}, 0, 1000);
|
|
293
|
+
} else {
|
|
294
|
+
if (_timer != null) {
|
|
295
|
+
_timer.cancel();
|
|
296
|
+
_timer = null;
|
|
297
|
+
}
|
|
298
|
+
long currentTime = this._player.getCurrentPosition();
|
|
299
|
+
if (this._callback != null) {
|
|
300
|
+
safeInvoke("onCurrentTimeChanged callback", () -> this._callback.onCurrentTimeChanged(currentTime));
|
|
301
|
+
}
|
|
302
|
+
if (this._audioView != null) {
|
|
303
|
+
this._audioView.setPlaying(false);
|
|
304
|
+
this._audioView.setCurrentTime(currentTime);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
});
|
|
249
308
|
}
|
|
250
309
|
|
|
251
310
|
@Override
|
|
252
311
|
public void onPlayerError(PlaybackException error) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
312
|
+
final String message = error == null ? "Playback error" : error.getMessage();
|
|
313
|
+
dispatchOnHandler("onPlayerError", () -> {
|
|
314
|
+
if (this._callback != null) {
|
|
315
|
+
safeInvoke("onError callback", () -> this._callback.onError(message));
|
|
316
|
+
}
|
|
317
|
+
});
|
|
256
318
|
}
|
|
257
319
|
|
|
258
320
|
@Override
|
|
259
321
|
public void onEvents(Player player, Player.Events events) { }
|
|
260
322
|
|
|
323
|
+
@Override
|
|
324
|
+
public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {}
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
@Override
|
|
328
|
+
public void onMediaItemTransition(
|
|
329
|
+
@Nullable MediaItem mediaItem, @Player.MediaItemTransitionReason int reason) {}
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
@Override
|
|
333
|
+
public void onTracksChanged(Tracks tracks) {}
|
|
334
|
+
|
|
335
|
+
@Override
|
|
336
|
+
public void onMediaMetadataChanged(MediaMetadata mediaMetadata) {}
|
|
337
|
+
|
|
338
|
+
@Override
|
|
339
|
+
public void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {}
|
|
340
|
+
|
|
341
|
+
@Override
|
|
342
|
+
public void onIsLoadingChanged(boolean isLoading) {}
|
|
343
|
+
|
|
344
|
+
@Deprecated
|
|
345
|
+
@UnstableApi
|
|
346
|
+
@Override
|
|
347
|
+
public void onLoadingChanged(boolean isLoading) {}
|
|
348
|
+
|
|
349
|
+
@Override
|
|
350
|
+
public void onAvailableCommandsChanged(Player.Commands availableCommands) {}
|
|
351
|
+
|
|
352
|
+
@Override
|
|
353
|
+
public void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) {}
|
|
354
|
+
|
|
355
|
+
@Deprecated
|
|
356
|
+
@UnstableApi
|
|
357
|
+
@Override
|
|
358
|
+
public void onPlayerStateChanged(boolean playWhenReady, @Player.State int playbackState) {}
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
|
|
261
362
|
@Override
|
|
262
363
|
public void onPlaybackStateChanged(@Player.State int playbackState) {
|
|
263
364
|
if (playbackState == Player.STATE_READY) {
|
|
264
|
-
|
|
265
|
-
this._canPlayFired
|
|
266
|
-
|
|
267
|
-
this._callback
|
|
365
|
+
dispatchOnHandler("onPlaybackStateChanged", () -> {
|
|
366
|
+
if (!this._canPlayFired) {
|
|
367
|
+
this._canPlayFired = true;
|
|
368
|
+
if (this._callback != null) {
|
|
369
|
+
safeInvoke("onCanPlay callback", () -> this._callback.onCanPlay());
|
|
370
|
+
}
|
|
268
371
|
}
|
|
269
|
-
}
|
|
270
372
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
373
|
+
if (this._loadedDataFired.compareAndSet(false, true)) {
|
|
374
|
+
if (this._callback != null) {
|
|
375
|
+
safeInvoke("onLoadedData callback", () -> this._callback.onLoadedData());
|
|
376
|
+
}
|
|
274
377
|
}
|
|
275
|
-
}
|
|
276
378
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
if (duration > 0 && buffered >= duration - 1000 && !this._canPlayThroughFired) {
|
|
284
|
-
this._canPlayThroughFired = true;
|
|
285
|
-
if (this._callback != null) {
|
|
286
|
-
this._callback.onCanPlayThrough();
|
|
379
|
+
long duration = this._player.getDuration();
|
|
380
|
+
long buffered = this._player.getBufferedPosition();
|
|
381
|
+
if (this._audioView != null) {
|
|
382
|
+
this._audioView.setDuration(duration);
|
|
383
|
+
this._audioView.setCurrentTime(this._player.getCurrentPosition());
|
|
287
384
|
}
|
|
288
|
-
|
|
385
|
+
if (duration > 0 && buffered >= duration - 1000 && !this._canPlayThroughFired) {
|
|
386
|
+
this._canPlayThroughFired = true;
|
|
387
|
+
if (this._callback != null) {
|
|
388
|
+
safeInvoke("onCanPlayThrough callback", () -> this._callback.onCanPlayThrough());
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
});
|
|
289
392
|
}
|
|
290
393
|
}
|
|
291
394
|
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
@Override
|
|
398
|
+
public void onPlayWhenReadyChanged(
|
|
399
|
+
boolean playWhenReady, @Player.PlayWhenReadyChangeReason int reason) {}
|
|
400
|
+
|
|
401
|
+
@Override
|
|
402
|
+
public void onPlaybackSuppressionReasonChanged(
|
|
403
|
+
@Player.PlaybackSuppressionReason int playbackSuppressionReason) {}
|
|
404
|
+
|
|
405
|
+
@Override
|
|
406
|
+
public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {}
|
|
407
|
+
|
|
408
|
+
@Override
|
|
409
|
+
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {}
|
|
410
|
+
|
|
411
|
+
@Override
|
|
412
|
+
public void onPlayerErrorChanged(@Nullable PlaybackException error) {}
|
|
413
|
+
|
|
414
|
+
@Deprecated
|
|
415
|
+
@UnstableApi
|
|
416
|
+
@Override
|
|
417
|
+
public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {}
|
|
418
|
+
|
|
419
|
+
@Override
|
|
420
|
+
public void onPositionDiscontinuity(
|
|
421
|
+
Player.PositionInfo oldPosition, Player.PositionInfo newPosition, @Player.DiscontinuityReason int reason) {}
|
|
422
|
+
|
|
423
|
+
@Override
|
|
424
|
+
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {}
|
|
425
|
+
|
|
426
|
+
@Override
|
|
427
|
+
public void onSeekBackIncrementChanged(long seekBackIncrementMs) {}
|
|
428
|
+
|
|
429
|
+
@Override
|
|
430
|
+
public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {}
|
|
431
|
+
|
|
432
|
+
@Override
|
|
433
|
+
public void onMaxSeekToPreviousPositionChanged(long maxSeekToPreviousPositionMs) {}
|
|
434
|
+
|
|
435
|
+
@UnstableApi
|
|
436
|
+
@Override
|
|
437
|
+
public void onAudioSessionIdChanged(int audioSessionId) {}
|
|
438
|
+
|
|
439
|
+
@Override
|
|
440
|
+
public void onAudioAttributesChanged(AudioAttributes audioAttributes) {}
|
|
441
|
+
|
|
442
|
+
@Override
|
|
443
|
+
public void onVolumeChanged(float volume) {}
|
|
444
|
+
|
|
445
|
+
@Override
|
|
446
|
+
public void onSkipSilenceEnabledChanged(boolean skipSilenceEnabled) {}
|
|
447
|
+
|
|
448
|
+
@Override
|
|
449
|
+
public void onDeviceInfoChanged(DeviceInfo deviceInfo) {}
|
|
450
|
+
|
|
451
|
+
@Override
|
|
452
|
+
public void onDeviceVolumeChanged(int volume, boolean muted) {}
|
|
453
|
+
|
|
454
|
+
@Override
|
|
455
|
+
public void onSurfaceSizeChanged(int width, int height) {}
|
|
456
|
+
|
|
457
|
+
@Override
|
|
458
|
+
public void onRenderedFirstFrame() {}
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
@Deprecated
|
|
462
|
+
@UnstableApi
|
|
463
|
+
@Override
|
|
464
|
+
public void onCues(List<Cue> cues) {}
|
|
465
|
+
|
|
466
|
+
@Override
|
|
467
|
+
public void onCues(CueGroup cueGroup) {}
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
@UnstableApi
|
|
471
|
+
public void onMetadata(Metadata metadata) {}
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
|
|
292
477
|
public void play() {
|
|
293
478
|
try {
|
|
294
479
|
this._player.setPlayWhenReady(true);
|
|
@@ -306,14 +491,21 @@ public class AudioHelper implements Player.Listener {
|
|
|
306
491
|
|
|
307
492
|
Method push = node.getClass().getMethod("pushFrames", float[].class);
|
|
308
493
|
Method end = node.getClass().getMethod("endStream");
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
494
|
+
Method configure = node.getClass().getMethod("configureFormat", int.class, int.class);
|
|
495
|
+
|
|
496
|
+
synchronized (_tapStateLock) {
|
|
497
|
+
_attachedContext = contextNative;
|
|
498
|
+
_ctxCreateExternalPcm = create;
|
|
499
|
+
_tapNodePushFrames = push;
|
|
500
|
+
_tapNodeEndStream = end;
|
|
501
|
+
_tapNodeConfigureFormat = configure;
|
|
502
|
+
_tapNodeSampleRate = 48000;
|
|
503
|
+
_tapNodeChannels = 2;
|
|
504
|
+
_tapReflectionFailures = 0;
|
|
505
|
+
_tapSuppressesDirectOutput = true;
|
|
506
|
+
_tapSourceNode = node;
|
|
507
|
+
}
|
|
508
|
+
updateEffectivePlayerVolume();
|
|
317
509
|
return node;
|
|
318
510
|
} catch (NoSuchMethodException e) {
|
|
319
511
|
android.util.Log.w("AudioHelper", "attachAudioContextTap: contextNative missing expected surface", e);
|
|
@@ -325,13 +517,23 @@ public class AudioHelper implements Player.Listener {
|
|
|
325
517
|
}
|
|
326
518
|
|
|
327
519
|
public void detachAudioContextTap() {
|
|
328
|
-
Object node
|
|
329
|
-
Method end
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
520
|
+
Object node;
|
|
521
|
+
Method end;
|
|
522
|
+
synchronized (_tapStateLock) {
|
|
523
|
+
node = _tapSourceNode;
|
|
524
|
+
end = _tapNodeEndStream;
|
|
525
|
+
_tapSourceNode = null;
|
|
526
|
+
_attachedContext = null;
|
|
527
|
+
_ctxCreateExternalPcm = null;
|
|
528
|
+
_tapNodePushFrames = null;
|
|
529
|
+
_tapNodeEndStream = null;
|
|
530
|
+
_tapNodeConfigureFormat = null;
|
|
531
|
+
_tapNodeSampleRate = 0;
|
|
532
|
+
_tapNodeChannels = 0;
|
|
533
|
+
_tapReflectionFailures = 0;
|
|
534
|
+
_tapSuppressesDirectOutput = false;
|
|
535
|
+
}
|
|
536
|
+
updateEffectivePlayerVolume();
|
|
335
537
|
if (node != null && end != null) {
|
|
336
538
|
try { end.invoke(node); } catch (Throwable ignored) {}
|
|
337
539
|
}
|
|
@@ -351,11 +553,12 @@ public class AudioHelper implements Player.Listener {
|
|
|
351
553
|
}
|
|
352
554
|
|
|
353
555
|
public boolean getMuted() {
|
|
354
|
-
return this.
|
|
556
|
+
return this._muted;
|
|
355
557
|
}
|
|
356
558
|
|
|
357
559
|
public void setMuted(boolean value) {
|
|
358
|
-
this.
|
|
560
|
+
this._muted = value;
|
|
561
|
+
updateEffectivePlayerVolume();
|
|
359
562
|
}
|
|
360
563
|
|
|
361
564
|
public long getDuration() {
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
// CanvasMedia
|
|
4
4
|
//
|
|
5
5
|
#import "NSCAudioHelper.h"
|
|
6
|
-
#
|
|
6
|
+
#if __has_include(<UniformTypeIdentifiers/UniformTypeIdentifiers.h>)
|
|
7
|
+
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
|
|
8
|
+
#endif
|
|
7
9
|
#import "NSCAudioView.h"
|
|
8
10
|
|
|
9
11
|
@implementation NSCAudioHelper {
|
|
@@ -614,17 +616,15 @@
|
|
|
614
616
|
}
|
|
615
617
|
mime = [mime stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
616
618
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
return @"probably";
|
|
624
|
-
}
|
|
625
|
-
CFRelease(uti);
|
|
619
|
+
#if __has_include(<UniformTypeIdentifiers/UniformTypeIdentifiers.h>)
|
|
620
|
+
if (@available(iOS 14.0, *)) {
|
|
621
|
+
UTType *utType = [UTType typeWithMIMEType:mime];
|
|
622
|
+
if (utType && ([utType conformsToType:UTTypeAudio] || [utType conformsToType:UTTypeAudiovisualContent] || [utType conformsToType:UTTypeMovie])) {
|
|
623
|
+
if ([mime containsString:@"ogg"] || [mime containsString:@"webm"] || [mime containsString:@"opus"]) return @"maybe";
|
|
624
|
+
return @"probably";
|
|
626
625
|
}
|
|
627
|
-
}
|
|
626
|
+
}
|
|
627
|
+
#endif
|
|
628
628
|
|
|
629
629
|
if ([mime containsString:@"mp3"] || [mime containsString:@"mpeg"] || [mime containsString:@"wav"] || [mime containsString:@"aac"] || [mime containsString:@"m4a"] || [mime containsString:@"flac"]) return @"probably";
|
|
630
630
|
if ([mime containsString:@"ogg"] || [mime containsString:@"opus"] || [mime containsString:@"webm"]) return @"maybe";
|
|
@@ -127,14 +127,17 @@
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
- (void)setPlaying:(BOOL)playing {
|
|
130
|
+
__weak typeof(self) weakSelf = self;
|
|
130
131
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
132
|
+
__strong typeof(weakSelf) strongSelf = weakSelf;
|
|
133
|
+
if (!strongSelf) return;
|
|
131
134
|
UIImage *img = nil;
|
|
132
|
-
if (playing ? _customPauseImage : _customPlayImage) {
|
|
133
|
-
img = playing ? _customPauseImage : _customPlayImage;
|
|
135
|
+
if (playing ? strongSelf->_customPauseImage : strongSelf->_customPlayImage) {
|
|
136
|
+
img = playing ? strongSelf->_customPauseImage : strongSelf->_customPlayImage;
|
|
134
137
|
if (img) {
|
|
135
138
|
UIImage *templ = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
|
136
|
-
[_playButton setImage:templ forState:UIControlStateNormal];
|
|
137
|
-
if (_iconTintColor) _playButton.tintColor = _iconTintColor;
|
|
139
|
+
[strongSelf->_playButton setImage:templ forState:UIControlStateNormal];
|
|
140
|
+
if (strongSelf->_iconTintColor) strongSelf->_playButton.tintColor = strongSelf->_iconTintColor;
|
|
138
141
|
return;
|
|
139
142
|
}
|
|
140
143
|
}
|
|
@@ -143,62 +146,71 @@
|
|
|
143
146
|
img = [UIImage systemImageNamed:(playing ? @"pause.fill" : @"play.fill")];
|
|
144
147
|
if (img) {
|
|
145
148
|
UIImage *templ = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
|
146
|
-
[_playButton setImage:templ forState:UIControlStateNormal];
|
|
147
|
-
if (_iconTintColor) _playButton.tintColor = _iconTintColor;
|
|
149
|
+
[strongSelf->_playButton setImage:templ forState:UIControlStateNormal];
|
|
150
|
+
if (strongSelf->_iconTintColor) strongSelf->_playButton.tintColor = strongSelf->_iconTintColor;
|
|
148
151
|
return;
|
|
149
152
|
}
|
|
150
153
|
}
|
|
151
154
|
|
|
152
|
-
UIColor *c = _iconTintColor ?: [UIColor blackColor];
|
|
153
|
-
UIImage *fallback = playing ? [
|
|
155
|
+
UIColor *c = strongSelf->_iconTintColor ?: [UIColor blackColor];
|
|
156
|
+
UIImage *fallback = playing ? [strongSelf _pauseIconWithSize:CGSizeMake(40,40) color:c] : [strongSelf _playIconWithSize:CGSizeMake(40,40) color:c];
|
|
154
157
|
if (fallback) {
|
|
155
|
-
[_playButton setImage:[fallback imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
|
|
156
|
-
if (_iconTintColor) _playButton.tintColor = _iconTintColor;
|
|
158
|
+
[strongSelf->_playButton setImage:[fallback imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
|
|
159
|
+
if (strongSelf->_iconTintColor) strongSelf->_playButton.tintColor = strongSelf->_iconTintColor;
|
|
157
160
|
}
|
|
158
161
|
});
|
|
159
162
|
}
|
|
160
163
|
|
|
161
164
|
- (void)setPlayImage:(UIImage *)image {
|
|
162
165
|
_customPlayImage = image;
|
|
166
|
+
__weak typeof(self) weakSelf = self;
|
|
163
167
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
168
|
+
__strong typeof(weakSelf) strongSelf = weakSelf;
|
|
169
|
+
if (!strongSelf) return;
|
|
164
170
|
BOOL playing = NO;
|
|
165
|
-
if (_helper) {
|
|
166
|
-
playing = ([_helper state] == NSCPlayerStatePlaying);
|
|
171
|
+
if (strongSelf->_helper) {
|
|
172
|
+
playing = ([strongSelf->_helper state] == NSCPlayerStatePlaying);
|
|
167
173
|
}
|
|
168
|
-
if (!playing && _customPlayImage) {
|
|
169
|
-
UIImage *img = [_customPlayImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
|
170
|
-
[_playButton setImage:img forState:UIControlStateNormal];
|
|
171
|
-
if (_iconTintColor) _playButton.tintColor = _iconTintColor;
|
|
174
|
+
if (!playing && strongSelf->_customPlayImage) {
|
|
175
|
+
UIImage *img = [strongSelf->_customPlayImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
|
176
|
+
[strongSelf->_playButton setImage:img forState:UIControlStateNormal];
|
|
177
|
+
if (strongSelf->_iconTintColor) strongSelf->_playButton.tintColor = strongSelf->_iconTintColor;
|
|
172
178
|
}
|
|
173
179
|
});
|
|
174
180
|
}
|
|
175
181
|
|
|
176
182
|
- (void)setPauseImage:(UIImage *)image {
|
|
177
183
|
_customPauseImage = image;
|
|
184
|
+
__weak typeof(self) weakSelf = self;
|
|
178
185
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
186
|
+
__strong typeof(weakSelf) strongSelf = weakSelf;
|
|
187
|
+
if (!strongSelf) return;
|
|
179
188
|
BOOL playing = NO;
|
|
180
|
-
if (_helper) {
|
|
181
|
-
playing = ([_helper state] == NSCPlayerStatePlaying);
|
|
189
|
+
if (strongSelf->_helper) {
|
|
190
|
+
playing = ([strongSelf->_helper state] == NSCPlayerStatePlaying);
|
|
182
191
|
}
|
|
183
|
-
if (playing && _customPauseImage) {
|
|
184
|
-
UIImage *img = [_customPauseImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
|
185
|
-
[_playButton setImage:img forState:UIControlStateNormal];
|
|
186
|
-
if (_iconTintColor) _playButton.tintColor = _iconTintColor;
|
|
192
|
+
if (playing && strongSelf->_customPauseImage) {
|
|
193
|
+
UIImage *img = [strongSelf->_customPauseImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
|
194
|
+
[strongSelf->_playButton setImage:img forState:UIControlStateNormal];
|
|
195
|
+
if (strongSelf->_iconTintColor) strongSelf->_playButton.tintColor = strongSelf->_iconTintColor;
|
|
187
196
|
}
|
|
188
197
|
});
|
|
189
198
|
}
|
|
190
199
|
|
|
191
200
|
- (void)setIconTintColor:(UIColor *)color {
|
|
192
201
|
_iconTintColor = color;
|
|
202
|
+
__weak typeof(self) weakSelf = self;
|
|
193
203
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
194
|
-
|
|
195
|
-
|
|
204
|
+
__strong typeof(weakSelf) strongSelf = weakSelf;
|
|
205
|
+
if (!strongSelf) return;
|
|
206
|
+
if (strongSelf->_iconTintColor) {
|
|
207
|
+
strongSelf->_playButton.tintColor = strongSelf->_iconTintColor;
|
|
196
208
|
}
|
|
197
209
|
BOOL playing = NO;
|
|
198
|
-
if (_helper) {
|
|
199
|
-
playing = ([_helper state] == NSCPlayerStatePlaying);
|
|
210
|
+
if (strongSelf->_helper) {
|
|
211
|
+
playing = ([strongSelf->_helper state] == NSCPlayerStatePlaying);
|
|
200
212
|
}
|
|
201
|
-
[
|
|
213
|
+
[strongSelf setPlaying:playing];
|
|
202
214
|
});
|
|
203
215
|
}
|
|
204
216
|
|
|
@@ -243,17 +255,20 @@
|
|
|
243
255
|
}
|
|
244
256
|
|
|
245
257
|
- (void)setDuration:(double)seconds {
|
|
258
|
+
__weak typeof(self) weakSelf = self;
|
|
246
259
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
247
|
-
|
|
260
|
+
__strong typeof(weakSelf) strongSelf = weakSelf;
|
|
261
|
+
if (!strongSelf) return;
|
|
262
|
+
strongSelf->_slider.minimumValue = 0;
|
|
248
263
|
if (seconds > 0) {
|
|
249
|
-
_slider.maximumValue = (float)seconds;
|
|
264
|
+
strongSelf->_slider.maximumValue = (float)seconds;
|
|
250
265
|
} else {
|
|
251
|
-
_slider.maximumValue = 1.0f;
|
|
266
|
+
strongSelf->_slider.maximumValue = 1.0f;
|
|
252
267
|
}
|
|
253
|
-
_durationSeconds = seconds;
|
|
254
|
-
_slider.enabled = (!isnan(seconds) && seconds > 0);
|
|
255
|
-
if (_slider.value > _slider.maximumValue) _slider.value = _slider.maximumValue;
|
|
256
|
-
[
|
|
268
|
+
strongSelf->_durationSeconds = seconds;
|
|
269
|
+
strongSelf->_slider.enabled = (!isnan(seconds) && seconds > 0);
|
|
270
|
+
if (strongSelf->_slider.value > strongSelf->_slider.maximumValue) strongSelf->_slider.value = strongSelf->_slider.maximumValue;
|
|
271
|
+
[strongSelf updateTimeLabelWithCurrent:strongSelf->_slider.value duration:strongSelf->_durationSeconds];
|
|
257
272
|
});
|
|
258
273
|
}
|
|
259
274
|
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
// Created by Osei Fortune on 20/05/2025.
|
|
6
6
|
//
|
|
7
7
|
#import "NSCVideoHelper.h"
|
|
8
|
-
#
|
|
8
|
+
#if __has_include(<UniformTypeIdentifiers/UniformTypeIdentifiers.h>)
|
|
9
|
+
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
|
|
10
|
+
#endif
|
|
9
11
|
#import "NSCVideoHelper+Internal.h"
|
|
10
12
|
|
|
11
13
|
@implementation NSCVideoHelper {
|
|
@@ -79,21 +81,30 @@
|
|
|
79
81
|
__weak typeof(self) weakSelf = self;
|
|
80
82
|
[self.asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
|
|
81
83
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
AVAssetTrack *videoTrack = [[
|
|
86
|
-
|
|
84
|
+
__strong typeof(weakSelf) strongSelf = weakSelf;
|
|
85
|
+
if (!strongSelf) return;
|
|
86
|
+
|
|
87
|
+
AVAssetTrack *videoTrack = [[strongSelf.asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
|
|
88
|
+
strongSelf->_videoSize = videoTrack ? videoTrack.naturalSize : CGSizeZero;
|
|
87
89
|
|
|
88
|
-
float fps = videoTrack.nominalFrameRate
|
|
90
|
+
float fps = (videoTrack && videoTrack.nominalFrameRate > 0) ? videoTrack.nominalFrameRate : 30.0f;
|
|
89
91
|
CMTime interval = CMTimeMake(1, (int32_t)fps);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
|
|
93
|
+
if (strongSelf.playbackFramesObserver) {
|
|
94
|
+
[strongSelf.player removeTimeObserver:strongSelf.playbackFramesObserver];
|
|
95
|
+
strongSelf.playbackFramesObserver = nil;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
__weak typeof(strongSelf) weakFrameSelf = strongSelf;
|
|
99
|
+
strongSelf.playbackFramesObserver = [strongSelf.player addPeriodicTimeObserverForInterval:interval queue:nil usingBlock:^(CMTime time) {
|
|
100
|
+
__strong typeof(weakFrameSelf) frameSelf = weakFrameSelf;
|
|
101
|
+
if (!frameSelf) return;
|
|
102
|
+
if (frameSelf.state == NSCPlayerStatePlaying) {
|
|
103
|
+
[frameSelf.listener onVideoFrameCallback];
|
|
93
104
|
}
|
|
94
105
|
}];
|
|
95
106
|
|
|
96
|
-
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:
|
|
107
|
+
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:strongSelf.asset];
|
|
97
108
|
|
|
98
109
|
strongSelf->_currentItem = item;
|
|
99
110
|
|
|
@@ -112,10 +123,11 @@
|
|
|
112
123
|
[item addObserver:strongSelf forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
|
|
113
124
|
[item addObserver:strongSelf forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:nil];
|
|
114
125
|
|
|
126
|
+
__weak typeof(strongSelf) weakPlayEndSelf = strongSelf;
|
|
115
127
|
strongSelf->_playEndNotificationId = [[NSNotificationCenter defaultCenter]
|
|
116
128
|
addObserverForName:AVPlayerItemDidPlayToEndTimeNotification
|
|
117
129
|
object:item queue:nil usingBlock:^(NSNotification *note) {
|
|
118
|
-
__strong typeof(
|
|
130
|
+
__strong typeof(weakPlayEndSelf) innerSelf = weakPlayEndSelf;
|
|
119
131
|
if (!innerSelf) return;
|
|
120
132
|
if (innerSelf->_isLoop) {
|
|
121
133
|
[innerSelf->_player seekToTime:kCMTimeZero];
|
|
@@ -133,27 +145,6 @@
|
|
|
133
145
|
if (strongSelf.autoplay) {
|
|
134
146
|
[strongSelf play];
|
|
135
147
|
}
|
|
136
|
-
|
|
137
|
-
[item addObserver:strongSelf forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
|
|
138
|
-
[item addObserver:strongSelf forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:nil];
|
|
139
|
-
|
|
140
|
-
strongSelf->_playEndNotificationId = [[NSNotificationCenter defaultCenter]
|
|
141
|
-
addObserverForName:AVPlayerItemDidPlayToEndTimeNotification
|
|
142
|
-
object:item queue:nil usingBlock:^(NSNotification *note) {
|
|
143
|
-
if (weakSelf != NULL && weakSelf.isLoop) {
|
|
144
|
-
[weakSelf.player seekToTime:kCMTimeZero];
|
|
145
|
-
[weakSelf.player play];
|
|
146
|
-
weakSelf.state = NSCPlayerStatePlaying;
|
|
147
|
-
[weakSelf.listener onStateChange:NSCPlayerStatePlaying];
|
|
148
|
-
}
|
|
149
|
-
}];
|
|
150
|
-
|
|
151
|
-
[weakSelf.player replaceCurrentItemWithPlayerItem:item];
|
|
152
|
-
weakSelf.readyState = NSCPlayerReadyStateHaveMetadata;
|
|
153
|
-
[weakSelf performSelectorOnMainThread:@selector(_scheduleFirstFrameCheck) withObject:nil waitUntilDone:NO];
|
|
154
|
-
if (weakSelf.autoplay) {
|
|
155
|
-
[weakSelf play];
|
|
156
|
-
}
|
|
157
148
|
});
|
|
158
149
|
}];
|
|
159
150
|
}
|
|
@@ -219,17 +210,15 @@
|
|
|
219
210
|
}
|
|
220
211
|
mime = [mime stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
221
212
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return @"probably";
|
|
229
|
-
}
|
|
230
|
-
CFRelease(uti);
|
|
213
|
+
#if __has_include(<UniformTypeIdentifiers/UniformTypeIdentifiers.h>)
|
|
214
|
+
if (@available(iOS 14.0, *)) {
|
|
215
|
+
UTType *utType = [UTType typeWithMIMEType:mime];
|
|
216
|
+
if (utType && ([utType conformsToType:UTTypeVideo] || [utType conformsToType:UTTypeAudiovisualContent])) {
|
|
217
|
+
if ([mime containsString:@"webm"] || [mime containsString:@"vp8"] || [mime containsString:@"vp9"] || [mime containsString:@"ogg"]) return @"maybe";
|
|
218
|
+
return @"probably";
|
|
231
219
|
}
|
|
232
|
-
}
|
|
220
|
+
}
|
|
221
|
+
#endif
|
|
233
222
|
|
|
234
223
|
if ([mime containsString:@"mp4"] || [mime containsString:@"mpeg"] || [mime containsString:@"h264"] || [mime containsString:@"video/mp4"]) return @"probably";
|
|
235
224
|
if ([mime containsString:@"webm"] || [mime containsString:@"vp8"] || [mime containsString:@"vp9"] || [mime containsString:@"video/webm"]) return @"maybe";
|
|
@@ -320,46 +309,49 @@
|
|
|
320
309
|
}
|
|
321
310
|
|
|
322
311
|
- (void)load {
|
|
312
|
+
__weak typeof(self) weakSelf = self;
|
|
323
313
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
314
|
+
__strong typeof(weakSelf) strongSelf = weakSelf;
|
|
315
|
+
if (!strongSelf) return;
|
|
324
316
|
@try {
|
|
325
|
-
[
|
|
317
|
+
[strongSelf pause];
|
|
326
318
|
|
|
327
|
-
if (
|
|
328
|
-
[
|
|
329
|
-
|
|
319
|
+
if (strongSelf.playbackTimeObserver) {
|
|
320
|
+
[strongSelf.player removeTimeObserver:strongSelf.playbackTimeObserver];
|
|
321
|
+
strongSelf.playbackTimeObserver = nil;
|
|
330
322
|
}
|
|
331
323
|
|
|
332
|
-
if (
|
|
333
|
-
[
|
|
334
|
-
|
|
324
|
+
if (strongSelf.playbackFramesObserver) {
|
|
325
|
+
[strongSelf.player removeTimeObserver:strongSelf.playbackFramesObserver];
|
|
326
|
+
strongSelf.playbackFramesObserver = nil;
|
|
335
327
|
}
|
|
336
328
|
|
|
337
|
-
if (_playEndNotificationId) {
|
|
338
|
-
[[NSNotificationCenter defaultCenter] removeObserver:_playEndNotificationId];
|
|
339
|
-
_playEndNotificationId = nil;
|
|
329
|
+
if (strongSelf->_playEndNotificationId) {
|
|
330
|
+
[[NSNotificationCenter defaultCenter] removeObserver:strongSelf->_playEndNotificationId];
|
|
331
|
+
strongSelf->_playEndNotificationId = nil;
|
|
340
332
|
}
|
|
341
333
|
|
|
342
|
-
if (
|
|
334
|
+
if (strongSelf.currentItem) {
|
|
343
335
|
@try {
|
|
344
|
-
[
|
|
336
|
+
[strongSelf.currentItem removeObserver:strongSelf forKeyPath:@"status"];
|
|
345
337
|
} @catch (NSException *exception) {}
|
|
346
338
|
@try {
|
|
347
|
-
[
|
|
339
|
+
[strongSelf.currentItem removeObserver:strongSelf forKeyPath:@"loadedTimeRanges"];
|
|
348
340
|
} @catch (NSException *exception) {}
|
|
349
341
|
}
|
|
350
342
|
|
|
351
|
-
if (
|
|
352
|
-
[
|
|
343
|
+
if (strongSelf.assetOutput) {
|
|
344
|
+
[strongSelf.assetOutput setDelegate:nil queue:NULL];
|
|
353
345
|
}
|
|
354
346
|
|
|
355
|
-
[
|
|
347
|
+
[strongSelf.player replaceCurrentItemWithPlayerItem:nil];
|
|
356
348
|
|
|
357
|
-
|
|
349
|
+
strongSelf.loadedDataFired = NO;
|
|
358
350
|
|
|
359
|
-
if (
|
|
360
|
-
NSString *src = [
|
|
361
|
-
|
|
362
|
-
[
|
|
351
|
+
if (strongSelf.currentSrc && strongSelf.currentSrc.length > 0) {
|
|
352
|
+
NSString *src = [strongSelf.currentSrc copy];
|
|
353
|
+
strongSelf.currentSrc = nil;
|
|
354
|
+
[strongSelf setSrc:src];
|
|
363
355
|
}
|
|
364
356
|
} @catch (NSException *ex) {
|
|
365
357
|
NSLog(@"NSCVideoHelper load() error: %@", ex);
|
package/video/common.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export declare abstract class VideoBase extends MediaBase {
|
|
|
34
34
|
_capturedListeners: {};
|
|
35
35
|
_listeners: {};
|
|
36
36
|
_notifyListener(type: any): void;
|
|
37
|
+
_invokeListener(type: string, listener: Function, source: string): void;
|
|
37
38
|
_removeListener(type: string, listener: Function, listeners: any): void;
|
|
38
39
|
_listenerExist(type: string, listener: Function, listeners: any): boolean;
|
|
39
40
|
addEventListener(type: string, listener: Function, useCapture: boolean | any): void;
|
package/video/common.js
CHANGED
|
@@ -6,6 +6,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { Screen, Application, Utils, CSSType, PercentLength } from '@nativescript/core';
|
|
8
8
|
import { MediaBase } from '../common';
|
|
9
|
+
function warnVideoListener(label, _error) {
|
|
10
|
+
try {
|
|
11
|
+
console.warn(label);
|
|
12
|
+
}
|
|
13
|
+
catch { }
|
|
14
|
+
}
|
|
9
15
|
let VideoBase = class VideoBase extends MediaBase {
|
|
10
16
|
constructor() {
|
|
11
17
|
super(...arguments);
|
|
@@ -60,24 +66,33 @@ let VideoBase = class VideoBase extends MediaBase {
|
|
|
60
66
|
for (let i = 0; i < size; i++) {
|
|
61
67
|
const item = capturedEvents[i];
|
|
62
68
|
if (typeof item === 'function') {
|
|
63
|
-
item
|
|
69
|
+
this._invokeListener(type, item, 'captured');
|
|
64
70
|
}
|
|
65
71
|
}
|
|
66
72
|
}
|
|
73
|
+
const handler = this[`on${type}`];
|
|
74
|
+
if (typeof handler === 'function') {
|
|
75
|
+
this._invokeListener(type, handler, 'property');
|
|
76
|
+
}
|
|
67
77
|
const events = this._listeners[type];
|
|
68
78
|
if (Array.isArray(events)) {
|
|
69
79
|
const size = events.length;
|
|
70
80
|
for (let i = 0; i < size; i++) {
|
|
71
81
|
const item = events[i];
|
|
72
|
-
if (typeof this[type] === 'function') {
|
|
73
|
-
this[type]();
|
|
74
|
-
}
|
|
75
82
|
if (typeof item === 'function') {
|
|
76
|
-
item
|
|
83
|
+
this._invokeListener(type, item, 'registered');
|
|
77
84
|
}
|
|
78
85
|
}
|
|
79
86
|
}
|
|
80
87
|
}
|
|
88
|
+
_invokeListener(type, listener, source) {
|
|
89
|
+
try {
|
|
90
|
+
listener.call(this);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
warnVideoListener(`Video.${type} ${source} listener failed`, error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
81
96
|
_removeListener(type, listener, listeners) {
|
|
82
97
|
if (!this._listeners) {
|
|
83
98
|
this._listeners = {};
|
|
@@ -178,7 +193,7 @@ let VideoBase = class VideoBase extends MediaBase {
|
|
|
178
193
|
if (this._videoFrameCallbacks.length !== 0) {
|
|
179
194
|
const toRemove = this._videoFrameCallbacks.length;
|
|
180
195
|
this._videoFrameCallbacks.forEach((cb) => {
|
|
181
|
-
cb
|
|
196
|
+
this._invokeListener('videoframe', cb, 'registered');
|
|
182
197
|
});
|
|
183
198
|
this._videoFrameCallbacks.splice(0, toRemove);
|
|
184
199
|
}
|
package/video/common.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../../packages/canvas-media/video/common.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../../packages/canvas-media/video/common.ts"],"names":[],"mappings":"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"}
|