kasunk99-livestream-core 0.2.1 → 0.2.3

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,CA6iBrF"}
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,CAsjBrF"}
@@ -101,15 +101,16 @@ export function useHostSocket(options = {}) {
101
101
  }
102
102
  catch { /* ignore */ }
103
103
  resetHostState();
104
- // Step 3 — stop camera/mic tracks deferred: Camera2 stopCapture() is fast but
105
- // we still give the executor a moment to finish the PC close first.
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?.getTracks()
109
- ?.forEach((t) => { try {
110
- t.stop?.();
111
- }
112
- catch { /* ignore */ } });
112
+ screenStreamToStop
113
+ ?.release?.();
113
114
  }
114
115
  catch { /* ignore */ }
115
116
  try {
@@ -278,12 +279,13 @@ export function useHostSocket(options = {}) {
278
279
  return; // fullCleanup already ran, bail
279
280
  const screenStreamToStop = hostSession.screenStream;
280
281
  hostSession.screenStream = null;
282
+ // release() → track.release() → mediaStreamTrackRelease → TrackPrivate.dispose()
283
+ // → stopCapture() (returns true) + dispose() → videoCapturer.dispose()
284
+ // → ScreenCapturerAndroid.dispose() → mediaProjection.stop(). This is the only
285
+ // path that properly stops the MediaProjection; t.stop() only calls stopCapture()
286
+ // which is now a no-op to avoid blocking the executor.
281
287
  try {
282
- screenStreamToStop.getTracks()
283
- .forEach((t) => { try {
284
- t.stop?.();
285
- }
286
- catch { /* ignore */ } });
288
+ screenStreamToStop.release?.();
287
289
  }
288
290
  catch { /* ignore */ }
289
291
  try {
@@ -500,17 +502,16 @@ export function useHostSocket(options = {}) {
500
502
  patchHostState({ status: 'Stopping screen share...' });
501
503
  const screenStream = hostSession.screenStream;
502
504
  hostSession.screenStream = null; // guard: stopScreenShare() bails on re-entry
503
- // t.stop() setEnabled(false) → executor: mediaStreamTrackSetEnabled(-1, id, false)
504
- // → getUserMediaImpl.mediaStreamTrackSetEnabled ScreenCaptureController.stopCapture()
505
- // Our override is non-blocking: spawns "ScreenCaptureStop" thread that calls
506
- // capturer.stopCapture() (blocks there, not on executor) and then calls
507
- // MediaProjectionService.abort(ctx) in its finally block so the notification
508
- // disappears after the MediaProjection fully drains.
509
- screenStream.getTracks()
510
- .forEach((t) => { try {
511
- t.stop?.();
505
+ // release() calls TrackPrivate.dispose() → ScreenCaptureController.dispose()
506
+ // → MediaProjectionService.abort() + videoCapturer.dispose() which unblocks
507
+ // captureStopped.await() immediately. t.stop() alone does not call dispose(),
508
+ // so the background thread in stopCapture() blocks the latch for up to 60 s
509
+ // when peerConnectionDispose() already freed SurfaceTextureHelper (e.g. after
510
+ // the user navigates away and comes back to a fresh component mount).
511
+ try {
512
+ screenStream.release?.();
512
513
  }
513
- catch { /* ignore */ } });
514
+ catch { /* ignore */ }
514
515
  }
515
516
  fullCleanup();
516
517
  patchHostState({ status: 'Stream stopped' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kasunk99-livestream-core",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Reusable livestream viewer/host module for React Native (Expo) — mediasoup + Socket.IO",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",