kasunk99-livestream-core 0.2.0 → 0.2.2
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHostSocket.d.ts","sourceRoot":"","sources":["../../src/hooks/useHostSocket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAoB3B,MAAM,MAAM,oBAAoB,GAAG;IACjC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG;IAC5C,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC,CAAC;AAMF,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,
|
|
1
|
+
{"version":3,"file":"useHostSocket.d.ts","sourceRoot":"","sources":["../../src/hooks/useHostSocket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAoB3B,MAAM,MAAM,oBAAoB,GAAG;IACjC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG;IAC5C,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC,CAAC;AAMF,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CAkjBrF"}
|
|
@@ -101,15 +101,16 @@ export function useHostSocket(options = {}) {
|
|
|
101
101
|
}
|
|
102
102
|
catch { /* ignore */ }
|
|
103
103
|
resetHostState();
|
|
104
|
-
// Step 3 — stop
|
|
105
|
-
//
|
|
104
|
+
// Step 3 — stop tracks deferred: give the executor a moment to finish pc.close().
|
|
105
|
+
// Screen stream: use release() not t.stop(). release() calls TrackPrivate.dispose()
|
|
106
|
+
// → ScreenCaptureController.dispose() → MediaProjectionService.abort() +
|
|
107
|
+
// videoCapturer.dispose() → decrements captureStopped latch immediately.
|
|
108
|
+
// t.stop() alone only calls stopCapture() which blocks the latch for up to 60 s
|
|
109
|
+
// when peerConnectionDispose() already freed the SurfaceTextureHelper.
|
|
106
110
|
setTimeout(() => {
|
|
107
111
|
try {
|
|
108
|
-
screenStreamToStop
|
|
109
|
-
?.
|
|
110
|
-
t.stop?.();
|
|
111
|
-
}
|
|
112
|
-
catch { /* ignore */ } });
|
|
112
|
+
screenStreamToStop
|
|
113
|
+
?.release?.();
|
|
113
114
|
}
|
|
114
115
|
catch { /* ignore */ }
|
|
115
116
|
try {
|
|
@@ -497,51 +498,19 @@ export function useHostSocket(options = {}) {
|
|
|
497
498
|
const stopLive = useCallback(async () => {
|
|
498
499
|
const { captureMode } = getHostState();
|
|
499
500
|
if (captureMode === 'screen' && hostSession.screenStream) {
|
|
500
|
-
// ── Sequential screen-share teardown ───────────────────────────────
|
|
501
|
-
// react-native-webrtc uses a single-threaded executor for ALL WebRTC ops.
|
|
502
|
-
// ScreenCapturerAndroid.stopCapture() blocks that executor for up to 60 s
|
|
503
|
-
// while waiting for the render thread (captureStopped CountDownLatch).
|
|
504
|
-
// RTCPeerConnection.dispose() (triggered async after pc.close()) frees the
|
|
505
|
-
// SurfaceTextureHelper that the render thread writes into.
|
|
506
|
-
// If stop() runs AFTER dispose(), the render thread is stuck → 60 s freeze.
|
|
507
|
-
//
|
|
508
|
-
// Fix: stop the screen tracks HERE, wait for the MediaProjection 'ended'
|
|
509
|
-
// event (i.e. the native capture has fully drained), THEN call fullCleanup().
|
|
510
|
-
// By the time fullCleanup() runs, the screen capturer is already gone and
|
|
511
|
-
// peerConnectionDispose() has nothing to contend with.
|
|
512
|
-
const screenStream = hostSession.screenStream;
|
|
513
|
-
hostSession.screenStream = null; // guard: stopScreenShare bails on re-entry
|
|
514
501
|
patchHostState({ status: 'Stopping screen share...' });
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
528
|
-
catch { /* ignore */ } });
|
|
529
|
-
// Fallback: if 'ended' never fires (some devices), unblock after 800 ms
|
|
530
|
-
setTimeout(() => {
|
|
531
|
-
videoTrack.removeEventListener?.('ended', onEnded);
|
|
532
|
-
resolve();
|
|
533
|
-
}, 800);
|
|
534
|
-
}
|
|
535
|
-
else {
|
|
536
|
-
screenStream.getTracks()
|
|
537
|
-
.forEach((t) => { try {
|
|
538
|
-
t.stop?.();
|
|
539
|
-
}
|
|
540
|
-
catch { /* ignore */ } });
|
|
541
|
-
resolve();
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
// MediaProjection is fully stopped — executor is free. Safe to close transport.
|
|
502
|
+
const screenStream = hostSession.screenStream;
|
|
503
|
+
hostSession.screenStream = null; // guard: stopScreenShare() bails on re-entry
|
|
504
|
+
// release() calls TrackPrivate.dispose() → ScreenCaptureController.dispose()
|
|
505
|
+
// → MediaProjectionService.abort() + videoCapturer.dispose() which unblocks
|
|
506
|
+
// captureStopped.await() immediately. t.stop() alone does not call dispose(),
|
|
507
|
+
// so the background thread in stopCapture() blocks the latch for up to 60 s
|
|
508
|
+
// when peerConnectionDispose() already freed SurfaceTextureHelper (e.g. after
|
|
509
|
+
// the user navigates away and comes back to a fresh component mount).
|
|
510
|
+
try {
|
|
511
|
+
screenStream.release?.();
|
|
512
|
+
}
|
|
513
|
+
catch { /* ignore */ }
|
|
545
514
|
}
|
|
546
515
|
fullCleanup();
|
|
547
516
|
patchHostState({ status: 'Stream stopped' });
|
package/package.json
CHANGED