expo-realtime-ivs-broadcast 0.1.10 → 0.2.1

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.
Files changed (265) hide show
  1. package/README.md +261 -4
  2. package/android/build/.transforms/10a4d332fad050fdaf4ee2d7badc1ee4/transformed/classes/classes_dex/classes.dex +0 -0
  3. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoIVSRemoteStreamView.dex +0 -0
  4. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoIVSStagePreviewView$attachStreamWithRetry$4.dex +0 -0
  5. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoIVSStagePreviewView.dex +0 -0
  6. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$1$16$1.dex +0 -0
  7. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$1$10$2.dex → ExpoRealtimeIvsBroadcastModule$definition$1$16$2.dex} +0 -0
  8. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$1$11$1.dex → ExpoRealtimeIvsBroadcastModule$definition$1$17$1.dex} +0 -0
  9. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$2.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$1.dex} +0 -0
  10. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$10.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$10.dex} +0 -0
  11. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$14.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$11.dex} +0 -0
  12. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$12.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$12.dex} +0 -0
  13. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$13.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$13.dex} +0 -0
  14. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$11.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$14.dex} +0 -0
  15. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$15.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$15.dex} +0 -0
  16. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$16.dex +0 -0
  17. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$17.dex +0 -0
  18. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$18.dex +0 -0
  19. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$4.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$2.dex} +0 -0
  20. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$3.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$3.dex} +0 -0
  21. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$5.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$4.dex} +0 -0
  22. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$1.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$5.dex} +0 -0
  23. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$6.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$6.dex} +0 -0
  24. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$7.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$7.dex} +0 -0
  25. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$8.dex +0 -0
  26. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$9.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$9.dex} +0 -0
  27. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunctionWithoutArgs$1.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$1.dex} +0 -0
  28. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunctionWithoutArgs$2.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$2.dex} +0 -0
  29. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunctionWithoutArgs$3.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$3.dex} +0 -0
  30. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$4.dex +0 -0
  31. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$5.dex +0 -0
  32. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$6.dex +0 -0
  33. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$7.dex +0 -0
  34. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$8.dex +0 -0
  35. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$OnCreate$1.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$OnCreate$1.dex} +0 -0
  36. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$View$1.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$View$1.dex} +0 -0
  37. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$View$2.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$View$2.dex} +0 -0
  38. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$lambda$22$$inlined$Prop$1.dex +0 -0
  39. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$lambda$10$$inlined$Prop$1.dex → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$lambda$22$$inlined$Prop$2.dex} +0 -0
  40. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$lambda$23$$inlined$Prop$1.dex +0 -0
  41. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule.dex +0 -0
  42. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/IVSStageManager.dex +0 -0
  43. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/PiPOptions$PiPSourceView.dex +0 -0
  44. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/PiPOptions.dex +0 -0
  45. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/PiPStateListener.dex +0 -0
  46. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/PictureInPictureDelegate.dex +0 -0
  47. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/PictureInPictureManager$Companion.dex +0 -0
  48. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/PictureInPictureManager.dex +0 -0
  49. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +5 -0
  50. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  51. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +12 -1
  52. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +5 -0
  53. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoIVSRemoteStreamView.class +0 -0
  54. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoIVSStagePreviewView$attachStreamWithRetry$4.class +0 -0
  55. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoIVSStagePreviewView.class +0 -0
  56. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$1$10$1.class → ExpoRealtimeIvsBroadcastModule$definition$1$16$1.class} +0 -0
  57. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$1$10$2.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$1$16$2.class} +0 -0
  58. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$1$11$1.class → ExpoRealtimeIvsBroadcastModule$definition$1$17$1.class} +0 -0
  59. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$4.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$1.class} +0 -0
  60. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$10.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$10.class} +0 -0
  61. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$14.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$11.class} +0 -0
  62. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$12.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$12.class} +0 -0
  63. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$13.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$13.class} +0 -0
  64. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$11.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$14.class} +0 -0
  65. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$15.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$15.class} +0 -0
  66. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$16.class +0 -0
  67. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$17.class +0 -0
  68. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$18.class +0 -0
  69. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$5.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$2.class} +0 -0
  70. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$3.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$3.class} +0 -0
  71. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$2.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$4.class} +0 -0
  72. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$1.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$5.class} +0 -0
  73. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$6.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$6.class} +0 -0
  74. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$7.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$7.class} +0 -0
  75. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$8.class +0 -0
  76. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$9.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$9.class} +0 -0
  77. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunctionWithoutArgs$1.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$1.class} +0 -0
  78. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunctionWithoutArgs$2.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$2.class} +0 -0
  79. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunctionWithoutArgs$3.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$3.class} +0 -0
  80. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$4.class +0 -0
  81. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$5.class +0 -0
  82. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$6.class +0 -0
  83. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$7.class +0 -0
  84. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$8.class +0 -0
  85. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$OnCreate$1.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$OnCreate$1.class} +0 -0
  86. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$View$1.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$View$1.class} +0 -0
  87. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$View$2.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$View$2.class} +0 -0
  88. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$lambda$22$$inlined$Prop$1.class +0 -0
  89. package/android/build/{tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$lambda$10$$inlined$Prop$1.class → intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$lambda$22$$inlined$Prop$2.class} +0 -0
  90. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$lambda$10$$inlined$Prop$1.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$lambda$23$$inlined$Prop$1.class} +0 -0
  91. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule.class +0 -0
  92. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/IVSStageManager.class +0 -0
  93. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/PiPOptions$PiPSourceView.class +0 -0
  94. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/PiPOptions.class +0 -0
  95. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/PiPStateListener.class +0 -0
  96. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/PictureInPictureDelegate.class +0 -0
  97. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/PictureInPictureManager$Companion.class +0 -0
  98. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/PictureInPictureManager.class +0 -0
  99. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  100. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  101. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
  102. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
  103. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
  104. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values +0 -0
  105. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  106. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.s +1 -0
  107. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
  108. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  109. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  110. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  111. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  112. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  113. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  114. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  115. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  116. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  117. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  118. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  119. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  120. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  121. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  122. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  123. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  124. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  125. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  126. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  127. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  128. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  129. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  130. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values +0 -0
  131. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  132. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.s +1 -0
  133. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  134. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  135. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
  136. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
  137. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
  138. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  139. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
  140. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  141. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
  142. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
  143. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
  144. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  145. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
  146. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  147. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
  148. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
  149. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
  150. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  151. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
  152. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +1 -1
  153. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  154. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
  155. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
  156. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
  157. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  158. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
  159. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  160. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  161. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  162. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  163. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  164. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  165. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  166. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  167. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  168. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  169. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values +0 -0
  170. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  171. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.s +1 -0
  172. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  173. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  174. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  175. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  176. package/android/build/outputs/logs/manifest-merger-debug-report.txt +14 -2
  177. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoIVSRemoteStreamView.class +0 -0
  178. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoIVSStagePreviewView$attachStreamWithRetry$4.class +0 -0
  179. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoIVSStagePreviewView.class +0 -0
  180. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$1$10$1.class → ExpoRealtimeIvsBroadcastModule$definition$1$16$1.class} +0 -0
  181. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$1$10$2.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$1$16$2.class} +0 -0
  182. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$1$11$1.class → ExpoRealtimeIvsBroadcastModule$definition$1$17$1.class} +0 -0
  183. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$1.class +0 -0
  184. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$10.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$10.class} +0 -0
  185. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$14.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$11.class} +0 -0
  186. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$12.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$12.class} +0 -0
  187. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$13.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$13.class} +0 -0
  188. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$11.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$14.class} +0 -0
  189. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$15.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$15.class} +0 -0
  190. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$16.class +0 -0
  191. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$17.class +0 -0
  192. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$18.class +0 -0
  193. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$2.class +0 -0
  194. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$3.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$3.class} +0 -0
  195. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$4.class +0 -0
  196. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$5.class +0 -0
  197. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$6.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$6.class} +0 -0
  198. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$7.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$7.class} +0 -0
  199. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$8.class +0 -0
  200. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$9.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunction$9.class} +0 -0
  201. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunctionWithoutArgs$1.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$1.class} +0 -0
  202. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunctionWithoutArgs$2.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$2.class} +0 -0
  203. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunctionWithoutArgs$3.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$3.class} +0 -0
  204. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$4.class +0 -0
  205. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$5.class +0 -0
  206. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$6.class +0 -0
  207. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$7.class +0 -0
  208. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$AsyncFunctionWithoutArgs$8.class +0 -0
  209. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$OnCreate$1.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$OnCreate$1.class} +0 -0
  210. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$View$1.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$View$1.class} +0 -0
  211. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$View$2.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$$inlined$View$2.class} +0 -0
  212. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$lambda$22$$inlined$Prop$1.class +0 -0
  213. package/android/build/{intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$lambda$9$$inlined$Prop$2.class → tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$24$lambda$22$$inlined$Prop$2.class} +0 -0
  214. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/{ExpoRealtimeIvsBroadcastModule$definition$lambda$11$lambda$9$$inlined$Prop$2.class → ExpoRealtimeIvsBroadcastModule$definition$lambda$24$lambda$23$$inlined$Prop$1.class} +0 -0
  215. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule.class +0 -0
  216. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/IVSStageManager.class +0 -0
  217. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/PiPOptions$PiPSourceView.class +0 -0
  218. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/PiPOptions.class +0 -0
  219. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/PiPStateListener.class +0 -0
  220. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/PictureInPictureDelegate.class +0 -0
  221. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/PictureInPictureManager$Companion.class +0 -0
  222. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/PictureInPictureManager.class +0 -0
  223. package/android/src/main/AndroidManifest.xml +5 -0
  224. package/android/src/main/java/expo/modules/realtimeivsbroadcast/ExpoIVSRemoteStreamView.kt +172 -23
  225. package/android/src/main/java/expo/modules/realtimeivsbroadcast/ExpoIVSStagePreviewView.kt +33 -0
  226. package/android/src/main/java/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule.kt +92 -2
  227. package/android/src/main/java/expo/modules/realtimeivsbroadcast/IVSStageManager.kt +5 -2
  228. package/android/src/main/java/expo/modules/realtimeivsbroadcast/PictureInPictureManager.kt +431 -0
  229. package/build/ExpoRealtimeIvsBroadcast.types.d.ts +45 -0
  230. package/build/ExpoRealtimeIvsBroadcast.types.d.ts.map +1 -1
  231. package/build/ExpoRealtimeIvsBroadcast.types.js.map +1 -1
  232. package/build/ExpoRealtimeIvsBroadcastModule.d.ts +7 -1
  233. package/build/ExpoRealtimeIvsBroadcastModule.d.ts.map +1 -1
  234. package/build/ExpoRealtimeIvsBroadcastModule.js.map +1 -1
  235. package/build/ExpoRealtimeIvsBroadcastModule.web.d.ts +7 -1
  236. package/build/ExpoRealtimeIvsBroadcastModule.web.d.ts.map +1 -1
  237. package/build/ExpoRealtimeIvsBroadcastModule.web.js +20 -0
  238. package/build/ExpoRealtimeIvsBroadcastModule.web.js.map +1 -1
  239. package/build/index.d.ts +60 -1
  240. package/build/index.d.ts.map +1 -1
  241. package/build/index.js +77 -0
  242. package/build/index.js.map +1 -1
  243. package/ios/ExpoIVSRemoteStreamView.swift +17 -0
  244. package/ios/ExpoIVSStagePreviewView.swift +39 -5
  245. package/ios/ExpoRealtimeIvsBroadcast.podspec +2 -1
  246. package/ios/ExpoRealtimeIvsBroadcastModule.swift +46 -1
  247. package/ios/IVSPictureInPictureController.swift +1196 -0
  248. package/ios/IVSStageManager.swift +419 -1
  249. package/package.json +1 -1
  250. package/src/ExpoRealtimeIvsBroadcast.types.ts +53 -0
  251. package/src/ExpoRealtimeIvsBroadcastModule.ts +9 -1
  252. package/src/ExpoRealtimeIvsBroadcastModule.web.ts +26 -8
  253. package/src/index.ts +94 -0
  254. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$1$10$1.dex +0 -0
  255. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$8.dex +0 -0
  256. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$lambda$9$$inlined$Prop$1.dex +0 -0
  257. package/android/build/.transforms/9f2f591934de19590757f5a4b0b59398/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$lambda$9$$inlined$Prop$2.dex +0 -0
  258. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$8.class +0 -0
  259. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$lambda$9$$inlined$Prop$1.class +0 -0
  260. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$1.class +0 -0
  261. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$2.class +0 -0
  262. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$4.class +0 -0
  263. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$5.class +0 -0
  264. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$$inlined$AsyncFunction$8.class +0 -0
  265. package/android/build/tmp/kotlin-classes/debug/expo/modules/realtimeivsbroadcast/ExpoRealtimeIvsBroadcastModule$definition$lambda$11$lambda$9$$inlined$Prop$1.class +0 -0
@@ -0,0 +1,1196 @@
1
+ // IVSPictureInPictureController.swift
2
+ // Picture-in-Picture support for IVS Stages
3
+
4
+ import AVKit
5
+ import AVFoundation
6
+ import UIKit
7
+ import AmazonIVSBroadcast
8
+
9
+ // MARK: - PiP Types (Available to all iOS versions for type compatibility)
10
+
11
+ /// Options for configuring PiP behavior
12
+ public struct PiPOptions {
13
+ public var autoEnterOnBackground: Bool = true
14
+ public var sourceView: PiPSourceView = .remote
15
+ public var preferredAspectRatio: CGSize = CGSize(width: 9, height: 16)
16
+
17
+ public enum PiPSourceView: String {
18
+ case local
19
+ case remote
20
+ }
21
+
22
+ public init() {}
23
+ }
24
+
25
+ /// Delegate protocol for PiP state changes
26
+ public protocol IVSPictureInPictureControllerDelegate: AnyObject {
27
+ func pictureInPictureDidStart()
28
+ func pictureInPictureDidStop()
29
+ func pictureInPictureWillRestore()
30
+ func pictureInPictureDidFail(with error: String)
31
+ }
32
+
33
+ // MARK: - View Frame Capture
34
+ /// Captures frames from any UIView using CADisplayLink for PiP
35
+ /// This is the workaround for IVS SDK not exposing frame callbacks
36
+ /// ALL operations happen on the main thread to avoid threading issues
37
+
38
+ public class ViewFrameCapture {
39
+ private var displayLink: CADisplayLink?
40
+ private weak var targetView: UIView?
41
+ private var frameCallback: ((CVPixelBuffer) -> Void)?
42
+
43
+ // Throttle frame capture to 30fps
44
+ private var lastCaptureTime: CFTimeInterval = 0
45
+ private let targetFrameInterval: CFTimeInterval = 1.0 / 30.0
46
+
47
+ // Fixed output size to prevent jittering - 9:16 portrait
48
+ private let fixedOutputWidth: Int = 540
49
+ private let fixedOutputHeight: Int = 960
50
+
51
+ // Reusable pixel buffer pool for efficiency
52
+ private var pixelBufferPool: CVPixelBufferPool?
53
+ private var lastWidth: Int = 0
54
+ private var lastHeight: Int = 0
55
+
56
+ private var isCapturing: Bool = false
57
+
58
+ public init() {}
59
+
60
+ deinit {
61
+ stop()
62
+ }
63
+
64
+ /// Start capturing frames from the target view
65
+ public func start(view: UIView, callback: @escaping (CVPixelBuffer) -> Void) {
66
+ // Ensure we're on main thread
67
+ guard Thread.isMainThread else {
68
+ DispatchQueue.main.async { [weak self] in
69
+ self?.start(view: view, callback: callback)
70
+ }
71
+ return
72
+ }
73
+
74
+ stop() // Clean up any existing capture
75
+
76
+ self.targetView = view
77
+ self.frameCallback = callback
78
+ self.isCapturing = true
79
+
80
+ let displayLink = CADisplayLink(target: self, selector: #selector(self.captureFrame))
81
+ displayLink.preferredFrameRateRange = CAFrameRateRange(minimum: 24, maximum: 30, preferred: 30)
82
+ displayLink.add(to: .main, forMode: .common)
83
+ self.displayLink = displayLink
84
+
85
+ print("🖼️ [ViewCapture] Started capturing frames from view")
86
+ }
87
+
88
+ /// Stop capturing frames
89
+ public func stop() {
90
+ // Ensure we're on main thread
91
+ guard Thread.isMainThread else {
92
+ DispatchQueue.main.async { [weak self] in
93
+ self?.stop()
94
+ }
95
+ return
96
+ }
97
+
98
+ isCapturing = false
99
+ displayLink?.invalidate()
100
+ displayLink = nil
101
+ targetView = nil
102
+ frameCallback = nil
103
+ pixelBufferPool = nil
104
+ lastWidth = 0
105
+ lastHeight = 0
106
+ frameCount = 0
107
+ print("🖼️ [ViewCapture] Stopped capturing frames")
108
+ }
109
+
110
+ @objc private func captureFrame(_ displayLink: CADisplayLink) {
111
+ // All of this runs on main thread (CADisplayLink callback)
112
+ guard isCapturing else { return }
113
+
114
+ // Throttle to target frame rate
115
+ let currentTime = displayLink.timestamp
116
+ guard currentTime - lastCaptureTime >= targetFrameInterval else { return }
117
+ lastCaptureTime = currentTime
118
+
119
+ guard let view = targetView, let callback = frameCallback else { return }
120
+
121
+ let bounds = view.bounds
122
+ guard bounds.width > 0 && bounds.height > 0 else { return }
123
+
124
+ // Check if view has a window - if not, try to get superview bounds
125
+ // IVS preview might not have window when app is in background
126
+ let captureView: UIView
127
+ let captureBounds: CGRect
128
+
129
+ if view.window != nil {
130
+ captureView = view
131
+ captureBounds = bounds
132
+ } else if let superview = view.superview, superview.window != nil {
133
+ // Try capturing from superview instead
134
+ captureView = superview
135
+ captureBounds = superview.bounds
136
+ } else {
137
+ // Last resort: capture the view anyway with afterScreenUpdates
138
+ captureView = view
139
+ captureBounds = bounds
140
+ }
141
+
142
+ // Use UIGraphicsImageRenderer with drawHierarchy for Metal/OpenGL views
143
+ // This is the only reliable way to capture IVS preview views
144
+ // NOTE: afterScreenUpdates must be true when view is not in visible window (e.g., during PiP)
145
+ let renderer = UIGraphicsImageRenderer(size: captureBounds.size)
146
+ let image = renderer.image { rendererContext in
147
+ // drawHierarchy captures Metal/OpenGL content unlike layer.render
148
+ // afterScreenUpdates: true is required when view may not be visible
149
+ captureView.drawHierarchy(in: captureBounds, afterScreenUpdates: true)
150
+ }
151
+
152
+ guard let cgImage = image.cgImage else { return }
153
+
154
+ // Use FIXED output size to prevent jittering
155
+ let width = fixedOutputWidth
156
+ let height = fixedOutputHeight
157
+
158
+ // Get pixel buffer from pool with fixed size
159
+ guard let pixelBuffer = getPixelBuffer(width: width, height: height) else {
160
+ return
161
+ }
162
+
163
+ CVPixelBufferLockBaseAddress(pixelBuffer, [])
164
+ defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, []) }
165
+
166
+ guard let context = CGContext(
167
+ data: CVPixelBufferGetBaseAddress(pixelBuffer),
168
+ width: width,
169
+ height: height,
170
+ bitsPerComponent: 8,
171
+ bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer),
172
+ space: CGColorSpaceCreateDeviceRGB(),
173
+ bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
174
+ ) else {
175
+ return
176
+ }
177
+
178
+ // Calculate scaling to fit the captured image into fixed output size
179
+ // while maintaining aspect ratio (aspect fill)
180
+ let sourceWidth = CGFloat(cgImage.width)
181
+ let sourceHeight = CGFloat(cgImage.height)
182
+ let targetWidth = CGFloat(width)
183
+ let targetHeight = CGFloat(height)
184
+
185
+ let sourceAspect = sourceWidth / sourceHeight
186
+ let targetAspect = targetWidth / targetHeight
187
+
188
+ var drawRect: CGRect
189
+ if sourceAspect > targetAspect {
190
+ // Source is wider - fit to height, crop sides
191
+ let scaledWidth = targetHeight * sourceAspect
192
+ let xOffset = (scaledWidth - targetWidth) / 2
193
+ drawRect = CGRect(x: -xOffset, y: 0, width: scaledWidth, height: targetHeight)
194
+ } else {
195
+ // Source is taller - fit to width, crop top/bottom
196
+ let scaledHeight = targetWidth / sourceAspect
197
+ let yOffset = (scaledHeight - targetHeight) / 2
198
+ drawRect = CGRect(x: 0, y: -yOffset, width: targetWidth, height: scaledHeight)
199
+ }
200
+
201
+ // CGContext has origin at bottom-left, so we need to flip
202
+ context.translateBy(x: 0, y: CGFloat(height))
203
+ context.scaleBy(x: 1, y: -1)
204
+
205
+ // Draw the image scaled to fit the fixed output size (aspect fill)
206
+ context.draw(cgImage, in: drawRect)
207
+
208
+ // Log first frame capture for debugging
209
+ if frameCount == 0 {
210
+ print("🖼️ [ViewCapture] First frame captured: \(width)x\(height)")
211
+ }
212
+ frameCount += 1
213
+
214
+ // Call the callback with the captured frame
215
+ callback(pixelBuffer)
216
+ }
217
+
218
+ private var frameCount: Int = 0
219
+
220
+ private func getPixelBuffer(width: Int, height: Int) -> CVPixelBuffer? {
221
+ // Create new pool if size changed
222
+ if width != lastWidth || height != lastHeight || pixelBufferPool == nil {
223
+ lastWidth = width
224
+ lastHeight = height
225
+
226
+ let attributes: [String: Any] = [
227
+ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
228
+ kCVPixelBufferWidthKey as String: width,
229
+ kCVPixelBufferHeightKey as String: height,
230
+ kCVPixelBufferIOSurfacePropertiesKey as String: [:],
231
+ kCVPixelBufferCGImageCompatibilityKey as String: true,
232
+ kCVPixelBufferCGBitmapContextCompatibilityKey as String: true
233
+ ]
234
+
235
+ var pool: CVPixelBufferPool?
236
+ CVPixelBufferPoolCreate(kCFAllocatorDefault, nil, attributes as CFDictionary, &pool)
237
+ pixelBufferPool = pool
238
+ }
239
+
240
+ guard let pool = pixelBufferPool else { return nil }
241
+
242
+ var pixelBuffer: CVPixelBuffer?
243
+ CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pixelBuffer)
244
+ return pixelBuffer
245
+ }
246
+ }
247
+
248
+ // MARK: - SampleBufferVideoCallView
249
+ /// A UIView that uses AVSampleBufferDisplayLayer as its layer class
250
+ /// This is required for Video Call PiP
251
+
252
+ @available(iOS 15.0, *)
253
+ class SampleBufferVideoCallView: UIView {
254
+ override class var layerClass: AnyClass {
255
+ return AVSampleBufferDisplayLayer.self
256
+ }
257
+
258
+ var sampleBufferDisplayLayer: AVSampleBufferDisplayLayer {
259
+ return layer as! AVSampleBufferDisplayLayer
260
+ }
261
+ }
262
+
263
+ // MARK: - IVSPictureInPictureController
264
+
265
+ /// Controller for managing Picture-in-Picture functionality with IVS streams
266
+ /// Uses the Video Call PiP API for real-time video
267
+ @available(iOS 15.0, *)
268
+ public class IVSPictureInPictureController: NSObject {
269
+
270
+ // MARK: - Properties
271
+
272
+ private var pipController: AVPictureInPictureController?
273
+ private var sampleBufferDisplayLayer: AVSampleBufferDisplayLayer?
274
+ private var pipContentSource: AVPictureInPictureController.ContentSource?
275
+
276
+ // Video Call PiP components
277
+ private var pipVideoCallViewController: AVPictureInPictureVideoCallViewController?
278
+ private var sampleBufferVideoCallView: SampleBufferVideoCallView?
279
+
280
+ // Container/source view for PiP - this should be the ACTUAL visible view showing video
281
+ private var pipContainerView: UIView?
282
+ private weak var activeSourceView: UIView?
283
+
284
+ // Configuration
285
+ private var options: PiPOptions = PiPOptions()
286
+
287
+ // State
288
+ public private(set) var isActive: Bool = false
289
+ public private(set) var isEnabled: Bool = false
290
+
291
+ // Delegate
292
+ public weak var delegate: IVSPictureInPictureControllerDelegate?
293
+
294
+ // Frame timing for sample buffer creation
295
+ private var frameCount: Int64 = 0
296
+ private let timeScale: Int32 = 600
297
+
298
+ // Queue for sample buffer operations
299
+ private let sampleBufferQueue = DispatchQueue(label: "com.ivs.pip.sampleBuffer")
300
+
301
+ // View frame capture for remote streams
302
+ private var viewFrameCapture: ViewFrameCapture?
303
+ private weak var captureTargetView: UIView?
304
+
305
+ // Pending source view (when setup is deferred because view is not in window)
306
+ private weak var pendingSourceView: UIView?
307
+
308
+ // Placeholder frame generator for broadcaster PiP (when camera is unavailable in background)
309
+ private var placeholderTimer: Timer?
310
+ private var placeholderPixelBuffer: CVPixelBuffer?
311
+ private var isUsingPlaceholder: Bool = false
312
+ private var lastRealFrameTime: CFAbsoluteTime = 0
313
+ private let placeholderTimeout: CFTimeInterval = 0.5 // Switch to placeholder after 0.5s without frames
314
+
315
+ // MARK: - Initialization
316
+
317
+ public override init() {
318
+ super.init()
319
+ setupNotifications()
320
+ createPlaceholderPixelBuffer()
321
+ }
322
+
323
+ deinit {
324
+ NotificationCenter.default.removeObserver(self)
325
+ cleanup()
326
+ }
327
+
328
+ // MARK: - Setup
329
+
330
+ private func setupNotifications() {
331
+ NotificationCenter.default.addObserver(
332
+ self,
333
+ selector: #selector(applicationWillResignActive),
334
+ name: UIApplication.willResignActiveNotification,
335
+ object: nil
336
+ )
337
+
338
+ NotificationCenter.default.addObserver(
339
+ self,
340
+ selector: #selector(applicationDidBecomeActive),
341
+ name: UIApplication.didBecomeActiveNotification,
342
+ object: nil
343
+ )
344
+ }
345
+
346
+ /// Enable PiP with the given options
347
+ /// Uses the Video Call PiP API which is designed for real-time video
348
+ public func enable(options: PiPOptions) -> Bool {
349
+ guard AVPictureInPictureController.isPictureInPictureSupported() else {
350
+ print("🖼️ [PiP] Picture-in-Picture is not supported on this device (simulator?)")
351
+ delegate?.pictureInPictureDidFail(with: "PiP not supported on this device")
352
+ return false
353
+ }
354
+
355
+ // Ensure we're on the main thread for all UI operations
356
+ guard Thread.isMainThread else {
357
+ var result = false
358
+ DispatchQueue.main.sync {
359
+ result = self.enable(options: options)
360
+ }
361
+ return result
362
+ }
363
+
364
+ // If already enabled, clean up first to allow re-enabling
365
+ if isEnabled {
366
+ print("🖼️ [PiP] Already enabled, resetting state for re-enable")
367
+ cleanupForReEnable()
368
+ }
369
+
370
+ self.options = options
371
+
372
+ // Use fixed frame size matching our capture output (9:16 portrait)
373
+ let frameWidth: CGFloat = 540
374
+ let frameHeight: CGFloat = 960
375
+
376
+ // Create SampleBufferVideoCallView - a UIView with AVSampleBufferDisplayLayer as its layer
377
+ let sampleBufferView = SampleBufferVideoCallView(frame: CGRect(x: 0, y: 0, width: frameWidth, height: frameHeight))
378
+ sampleBufferView.sampleBufferDisplayLayer.videoGravity = .resizeAspectFill
379
+ self.sampleBufferDisplayLayer = sampleBufferView.sampleBufferDisplayLayer
380
+ self.sampleBufferVideoCallView = sampleBufferView
381
+
382
+ // Create the PiP Video Call View Controller
383
+ let pipVideoCallVC = AVPictureInPictureVideoCallViewController()
384
+ pipVideoCallVC.preferredContentSize = CGSize(width: frameWidth, height: frameHeight)
385
+ pipVideoCallVC.view.addSubview(sampleBufferView)
386
+ self.pipVideoCallViewController = pipVideoCallVC
387
+
388
+ // Set up constraints for the sample buffer view
389
+ sampleBufferView.translatesAutoresizingMaskIntoConstraints = false
390
+ NSLayoutConstraint.activate([
391
+ sampleBufferView.leadingAnchor.constraint(equalTo: pipVideoCallVC.view.leadingAnchor),
392
+ sampleBufferView.trailingAnchor.constraint(equalTo: pipVideoCallVC.view.trailingAnchor),
393
+ sampleBufferView.topAnchor.constraint(equalTo: pipVideoCallVC.view.topAnchor),
394
+ sampleBufferView.bottomAnchor.constraint(equalTo: pipVideoCallVC.view.bottomAnchor)
395
+ ])
396
+
397
+ // NOTE: We'll set the activeSourceView later when setupWithSourceView is called
398
+ // The activeVideoCallSourceView MUST be the actual visible view showing video
399
+ self.isEnabled = true
400
+
401
+ print("🖼️ [PiP] Enabled with Video Call API: autoEnter=\(options.autoEnterOnBackground), source=\(options.sourceView.rawValue)")
402
+ print("🖼️ [PiP] Call setupWithSourceView() with the actual video view to complete setup")
403
+
404
+ return true
405
+ }
406
+
407
+ /// Clean up state for re-enabling (without fully disabling)
408
+ private func cleanupForReEnable() {
409
+ // Stop any active PiP
410
+ pipController?.stopPictureInPicture()
411
+ pipController = nil
412
+ pipContentSource = nil
413
+
414
+ // Clean up Video Call components
415
+ sampleBufferVideoCallView?.removeFromSuperview()
416
+ sampleBufferVideoCallView = nil
417
+ pipVideoCallViewController = nil
418
+
419
+ sampleBufferDisplayLayer?.flush()
420
+ sampleBufferDisplayLayer = nil
421
+
422
+ // Reset state but keep isEnabled true (will be set again)
423
+ frameCount = 0
424
+ enqueuedFrameCount = 0
425
+ startTime = nil
426
+ isActive = false
427
+
428
+ // Don't nil out activeSourceView - it might still be valid
429
+ print("🖼️ [PiP] Cleaned up for re-enable")
430
+ }
431
+
432
+ /// Complete PiP setup with the actual source view
433
+ /// This MUST be called with the visible view showing video content
434
+ public func setupWithSourceView(_ sourceView: UIView) {
435
+ guard Thread.isMainThread else {
436
+ DispatchQueue.main.async { [weak self] in
437
+ self?.setupWithSourceView(sourceView)
438
+ }
439
+ return
440
+ }
441
+
442
+ guard let pipVideoCallVC = pipVideoCallViewController else {
443
+ print("🖼️ [PiP] Error: Must call enable() before setupWithSourceView()")
444
+ return
445
+ }
446
+
447
+ // IMPORTANT: Check if the source view is in a window hierarchy
448
+ // If not, defer setup until it is
449
+ if sourceView.window == nil {
450
+ print("🖼️ [PiP] Warning: Source view not in window hierarchy yet. Deferring setup...")
451
+ self.pendingSourceView = sourceView
452
+
453
+ // Observe when the view gets added to window
454
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self, weak sourceView] in
455
+ guard let self = self, let view = sourceView else { return }
456
+ if view.window != nil {
457
+ print("🖼️ [PiP] Source view now in window, completing setup")
458
+ self.pendingSourceView = nil
459
+ self.completeSetupWithSourceView(view, pipVideoCallVC: pipVideoCallVC)
460
+ } else {
461
+ // Retry with increasing delays
462
+ self.retrySetupWithSourceView(view, pipVideoCallVC: pipVideoCallVC, attempt: 1)
463
+ }
464
+ }
465
+ return
466
+ }
467
+
468
+ completeSetupWithSourceView(sourceView, pipVideoCallVC: pipVideoCallVC)
469
+ }
470
+
471
+ /// Retry setup with exponential backoff
472
+ private func retrySetupWithSourceView(_ sourceView: UIView, pipVideoCallVC: AVPictureInPictureVideoCallViewController, attempt: Int) {
473
+ let maxAttempts = 10
474
+ let delay = min(0.1 * pow(1.5, Double(attempt)), 2.0) // Max 2 second delay
475
+
476
+ guard attempt < maxAttempts else {
477
+ print("🖼️ [PiP] Warning: Source view still not in window after \(maxAttempts) attempts. Setting up anyway...")
478
+ completeSetupWithSourceView(sourceView, pipVideoCallVC: pipVideoCallVC)
479
+ return
480
+ }
481
+
482
+ DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self, weak sourceView] in
483
+ guard let self = self, let view = sourceView else { return }
484
+
485
+ if view.window != nil {
486
+ print("🖼️ [PiP] Source view now in window (attempt \(attempt + 1)), completing setup")
487
+ self.pendingSourceView = nil
488
+ self.completeSetupWithSourceView(view, pipVideoCallVC: pipVideoCallVC)
489
+ } else {
490
+ print("🖼️ [PiP] Source view still not in window (attempt \(attempt + 1)), retrying...")
491
+ self.retrySetupWithSourceView(view, pipVideoCallVC: pipVideoCallVC, attempt: attempt + 1)
492
+ }
493
+ }
494
+ }
495
+
496
+ /// Actually complete the PiP setup once we have a valid source view
497
+ private func completeSetupWithSourceView(_ sourceView: UIView, pipVideoCallVC: AVPictureInPictureVideoCallViewController) {
498
+ self.activeSourceView = sourceView
499
+ self.pipContainerView = sourceView
500
+
501
+ // Create PiP content source using Video Call API
502
+ // The activeVideoCallSourceView is the ACTUAL view showing video in the app
503
+ let contentSource = AVPictureInPictureController.ContentSource(
504
+ activeVideoCallSourceView: sourceView,
505
+ contentViewController: pipVideoCallVC
506
+ )
507
+ self.pipContentSource = contentSource
508
+
509
+ // Create PiP controller
510
+ let controller = AVPictureInPictureController(contentSource: contentSource)
511
+ controller.delegate = self
512
+ controller.canStartPictureInPictureAutomaticallyFromInline = options.autoEnterOnBackground
513
+
514
+ self.pipController = controller
515
+
516
+ // Pre-warm with more placeholder frames and longer delay to ensure PiP is possible
517
+ print("🖼️ [PiP] Pre-warming display layer with placeholder frames...")
518
+ aggressivePreWarm { [weak self, weak controller] in
519
+ guard let self = self, let controller = controller else { return }
520
+ print("🖼️ [PiP] Setup complete with source view: \(sourceView)")
521
+ print("🖼️ [PiP] Source view in window: \(sourceView.window != nil)")
522
+ print("🖼️ [PiP] isPictureInPicturePossible: \(controller.isPictureInPicturePossible)")
523
+ }
524
+ }
525
+
526
+ /// Aggressive pre-warming to ensure display layer is ready
527
+ private func aggressivePreWarm(completion: @escaping () -> Void) {
528
+ // Enqueue initial batch of frames immediately
529
+ for _ in 0..<5 {
530
+ enqueuePlaceholderFrame()
531
+ }
532
+
533
+ // Then enqueue more frames over time to ensure the layer is warm
534
+ var framesEnqueued = 5
535
+ let timer = Timer.scheduledTimer(withTimeInterval: 0.033, repeats: true) { [weak self] timer in
536
+ guard let self = self else {
537
+ timer.invalidate()
538
+ return
539
+ }
540
+
541
+ self.enqueuePlaceholderFrame()
542
+ framesEnqueued += 1
543
+
544
+ // After 15 frames (~0.5s), check if PiP is possible
545
+ if framesEnqueued >= 15 {
546
+ timer.invalidate()
547
+ DispatchQueue.main.async {
548
+ completion()
549
+ }
550
+ }
551
+ }
552
+ RunLoop.main.add(timer, forMode: .common)
553
+ }
554
+
555
+ /// Disable PiP
556
+ public func disable() {
557
+ // Ensure we're on the main thread
558
+ guard Thread.isMainThread else {
559
+ DispatchQueue.main.async { [weak self] in
560
+ self?.disable()
561
+ }
562
+ return
563
+ }
564
+
565
+ if isActive {
566
+ stop()
567
+ }
568
+
569
+ stopViewCapture()
570
+ cleanup()
571
+ isEnabled = false
572
+
573
+ print("🖼️ [PiP] Disabled")
574
+ }
575
+
576
+ /// Start PiP manually
577
+ public func start() {
578
+ // Ensure we're on the main thread
579
+ guard Thread.isMainThread else {
580
+ DispatchQueue.main.async { [weak self] in
581
+ self?.start()
582
+ }
583
+ return
584
+ }
585
+
586
+ guard isEnabled else {
587
+ print("🖼️ [PiP] Cannot start - PiP is not enabled")
588
+ delegate?.pictureInPictureDidFail(with: "PiP is not enabled")
589
+ return
590
+ }
591
+
592
+ guard let controller = pipController else {
593
+ print("🖼️ [PiP] Cannot start - no PiP controller")
594
+ delegate?.pictureInPictureDidFail(with: "PiP controller not initialized")
595
+ return
596
+ }
597
+
598
+ // If PiP is not possible, try pre-warming with placeholder frames
599
+ if !controller.isPictureInPicturePossible {
600
+ print("🖼️ [PiP] PiP not possible, pre-warming with placeholder frames...")
601
+ preWarmWithPlaceholder { [weak self, weak controller] success in
602
+ guard let self = self, let controller = controller else { return }
603
+
604
+ if success && controller.isPictureInPicturePossible {
605
+ controller.startPictureInPicture()
606
+ print("🖼️ [PiP] Start requested after pre-warming")
607
+ } else {
608
+ print("🖼️ [PiP] Cannot start - PiP still not possible after pre-warming")
609
+ self.delegate?.pictureInPictureDidFail(with: "PiP is not possible at this time. Make sure video frames are being fed.")
610
+ }
611
+ }
612
+ return
613
+ }
614
+
615
+ controller.startPictureInPicture()
616
+ print("🖼️ [PiP] Start requested")
617
+ }
618
+
619
+ /// Pre-warm the display layer with placeholder frames to make PiP possible
620
+ /// Uses aggressive pre-warming with retry logic
621
+ private func preWarmWithPlaceholder(completion: @escaping (Bool) -> Void) {
622
+ guard placeholderPixelBuffer != nil else {
623
+ print("🖼️ [PiP] No placeholder buffer available")
624
+ completion(false)
625
+ return
626
+ }
627
+
628
+ // Check if source view is in window - if not, that's likely the issue
629
+ if let sourceView = activeSourceView {
630
+ print("🖼️ [PiP] Pre-warm: Source view in window: \(sourceView.window != nil)")
631
+ if sourceView.window == nil {
632
+ print("🖼️ [PiP] Warning: Source view not in window during pre-warm!")
633
+ }
634
+ }
635
+
636
+ // Use aggressive pre-warming with polling
637
+ var attemptCount = 0
638
+ let maxAttempts = 5
639
+
640
+ func tryPreWarm() {
641
+ attemptCount += 1
642
+
643
+ // Enqueue a batch of frames
644
+ for _ in 0..<10 {
645
+ enqueuePlaceholderFrame()
646
+ }
647
+
648
+ // Use increasing delays for each attempt
649
+ let delay = 0.15 * Double(attemptCount)
650
+
651
+ DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
652
+ guard let self = self else {
653
+ completion(false)
654
+ return
655
+ }
656
+
657
+ let isPossible = self.pipController?.isPictureInPicturePossible ?? false
658
+ print("🖼️ [PiP] Pre-warm attempt \(attemptCount)/\(maxAttempts), isPictureInPicturePossible: \(isPossible)")
659
+
660
+ if isPossible {
661
+ completion(true)
662
+ } else if attemptCount < maxAttempts {
663
+ // Try again with more frames
664
+ tryPreWarm()
665
+ } else {
666
+ // Final attempt - log diagnostic info
667
+ print("🖼️ [PiP] Pre-warm failed after \(maxAttempts) attempts")
668
+ if let sourceView = self.activeSourceView {
669
+ print("🖼️ [PiP] - Source view in window: \(sourceView.window != nil)")
670
+ print("🖼️ [PiP] - Source view frame: \(sourceView.frame)")
671
+ print("🖼️ [PiP] - Source view hidden: \(sourceView.isHidden)")
672
+ }
673
+ print("🖼️ [PiP] - Display layer status: \(self.sampleBufferDisplayLayer?.status.rawValue ?? -1)")
674
+ print("🖼️ [PiP] - Frames enqueued: \(self.enqueuedFrameCount)")
675
+ completion(false)
676
+ }
677
+ }
678
+ }
679
+
680
+ tryPreWarm()
681
+ }
682
+
683
+ /// Stop PiP manually
684
+ public func stop() {
685
+ // Ensure we're on the main thread
686
+ guard Thread.isMainThread else {
687
+ DispatchQueue.main.async { [weak self] in
688
+ self?.stop()
689
+ }
690
+ return
691
+ }
692
+
693
+ guard let controller = pipController, isActive else {
694
+ print("🖼️ [PiP] Cannot stop - PiP is not active")
695
+ return
696
+ }
697
+
698
+ controller.stopPictureInPicture()
699
+ print("🖼️ [PiP] Stop requested")
700
+ }
701
+
702
+ // MARK: - View Capture for Remote Streams (Fallback Method)
703
+
704
+ /// Start capturing frames from a UIView (fallback method when IVSImageDevice is not available)
705
+ /// This also sets up the Video Call API with the source view
706
+ /// NOTE: For IVSImageDevice frame capture, the IVSStageManager handles the callback setup
707
+ /// and calls enqueueFrame() directly. This method is kept as a fallback.
708
+ public func startViewCapture(from view: UIView) {
709
+ // Ensure we're on the main thread
710
+ guard Thread.isMainThread else {
711
+ DispatchQueue.main.async { [weak self] in
712
+ self?.startViewCapture(from: view)
713
+ }
714
+ return
715
+ }
716
+
717
+ stopViewCapture()
718
+
719
+ // IMPORTANT: Set up the Video Call API with this view as the source
720
+ // This must be the actual visible view showing video content
721
+ if let parentView = view.superview {
722
+ // Use the parent container view (ExpoIVSRemoteStreamView) as the source
723
+ setupWithSourceView(parentView)
724
+ } else {
725
+ // Use the view directly
726
+ setupWithSourceView(view)
727
+ }
728
+
729
+ captureTargetView = view
730
+ viewFrameCapture = ViewFrameCapture()
731
+ viewFrameCapture?.start(view: view) { [weak self] pixelBuffer in
732
+ self?.enqueueFrame(pixelBuffer)
733
+ }
734
+
735
+ print("🖼️ [PiP] Started view capture for remote stream (fallback method)")
736
+ }
737
+
738
+ /// Stop capturing frames from view
739
+ public func stopViewCapture() {
740
+ // Ensure we're on the main thread
741
+ guard Thread.isMainThread else {
742
+ DispatchQueue.main.async { [weak self] in
743
+ self?.stopViewCapture()
744
+ }
745
+ return
746
+ }
747
+
748
+ viewFrameCapture?.stop()
749
+ viewFrameCapture = nil
750
+ captureTargetView = nil
751
+ }
752
+
753
+ // MARK: - Frame Handling
754
+
755
+ /// Feed a video frame (CVPixelBuffer) to the PiP display
756
+ public func enqueueFrame(_ pixelBuffer: CVPixelBuffer) {
757
+ guard isEnabled, let displayLayer = sampleBufferDisplayLayer else {
758
+ return
759
+ }
760
+
761
+ // Track that we received a real frame
762
+ lastRealFrameTime = CFAbsoluteTimeGetCurrent()
763
+
764
+ // If we were using placeholder, switch back to real frames
765
+ if isUsingPlaceholder {
766
+ print("🖼️ [PiP] Real frames resumed, stopping placeholder")
767
+ stopPlaceholderFrameGeneration()
768
+ }
769
+
770
+ // Log first few frames and periodically for debugging
771
+ let shouldLog = enqueuedFrameCount < 3 || (enqueuedFrameCount % 300 == 0) // Log every 10 seconds at 30fps
772
+ if shouldLog {
773
+ let width = CVPixelBufferGetWidth(pixelBuffer)
774
+ let height = CVPixelBufferGetHeight(pixelBuffer)
775
+ print("🖼️ [PiP] Frame #\(enqueuedFrameCount): \(width)x\(height), layer status: \(displayLayer.status.rawValue), isActive: \(isActive)")
776
+ }
777
+
778
+ // Create CMSampleBuffer from CVPixelBuffer - do this synchronously
779
+ // to ensure the pixel buffer is not released before we use it
780
+ guard let sampleBuffer = self.createSampleBuffer(from: pixelBuffer) else {
781
+ if enqueuedFrameCount < 3 {
782
+ print("🖼️ [PiP] Failed to create sample buffer")
783
+ }
784
+ return
785
+ }
786
+
787
+ enqueuedFrameCount += 1
788
+
789
+ // Enqueue on background queue for performance
790
+ sampleBufferQueue.async { [weak displayLayer, weak self] in
791
+ guard let displayLayer = displayLayer else { return }
792
+
793
+ // Handle failed display layer
794
+ if displayLayer.status == .failed {
795
+ print("🖼️ [PiP] Display layer failed, flushing...")
796
+ displayLayer.flush()
797
+ // Reset start time for fresh timing after flush
798
+ self?.startTime = nil
799
+ }
800
+
801
+ displayLayer.enqueue(sampleBuffer)
802
+ }
803
+
804
+ // Log first successful enqueue
805
+ if enqueuedFrameCount == 1 {
806
+ print("🖼️ [PiP] First frame enqueued successfully")
807
+ }
808
+ }
809
+
810
+ private var enqueuedFrameCount: Int = 0
811
+
812
+ /// Feed a CMSampleBuffer directly to the PiP display
813
+ /// This extracts the pixel buffer and re-creates with proper timing for AVSampleBufferDisplayLayer
814
+ public func enqueueSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
815
+ guard isEnabled, let displayLayer = sampleBufferDisplayLayer else {
816
+ return
817
+ }
818
+
819
+ // Extract pixel buffer from sample buffer and use our timing
820
+ guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
821
+ return
822
+ }
823
+
824
+ // Use enqueueFrame which has proper timing handling
825
+ enqueueFrame(pixelBuffer)
826
+ }
827
+
828
+ // MARK: - Private Helpers
829
+
830
+ private var startTime: CMTime?
831
+
832
+ private func createSampleBuffer(from pixelBuffer: CVPixelBuffer) -> CMSampleBuffer? {
833
+ var formatDescription: CMVideoFormatDescription?
834
+ let status = CMVideoFormatDescriptionCreateForImageBuffer(
835
+ allocator: kCFAllocatorDefault,
836
+ imageBuffer: pixelBuffer,
837
+ formatDescriptionOut: &formatDescription
838
+ )
839
+
840
+ guard status == noErr, let format = formatDescription else {
841
+ print("🖼️ [PiP] Failed to create format description")
842
+ return nil
843
+ }
844
+
845
+ // Use host time for live streaming - this ensures proper synchronization
846
+ let currentTime = CMClockGetTime(CMClockGetHostTimeClock())
847
+
848
+ // Initialize start time on first frame
849
+ if startTime == nil {
850
+ startTime = currentTime
851
+ }
852
+
853
+ // Calculate presentation time relative to start
854
+ let presentationTime = CMTimeSubtract(currentTime, startTime!)
855
+
856
+ var timingInfo = CMSampleTimingInfo(
857
+ duration: CMTime(value: 1, timescale: 30), // 1/30th second duration
858
+ presentationTimeStamp: presentationTime,
859
+ decodeTimeStamp: .invalid
860
+ )
861
+
862
+ var sampleBuffer: CMSampleBuffer?
863
+ let createStatus = CMSampleBufferCreateForImageBuffer(
864
+ allocator: kCFAllocatorDefault,
865
+ imageBuffer: pixelBuffer,
866
+ dataReady: true,
867
+ makeDataReadyCallback: nil,
868
+ refcon: nil,
869
+ formatDescription: format,
870
+ sampleTiming: &timingInfo,
871
+ sampleBufferOut: &sampleBuffer
872
+ )
873
+
874
+ guard createStatus == noErr else {
875
+ print("🖼️ [PiP] Failed to create sample buffer: \(createStatus)")
876
+ return nil
877
+ }
878
+
879
+ // Increment frame count
880
+ frameCount += 1
881
+
882
+ return sampleBuffer
883
+ }
884
+
885
+ // MARK: - Placeholder Frame Generation
886
+
887
+ /// Create a placeholder pixel buffer with "Broadcasting" text
888
+ private func createPlaceholderPixelBuffer() {
889
+ let width = 540
890
+ let height = 960
891
+
892
+ let attributes: [String: Any] = [
893
+ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
894
+ kCVPixelBufferWidthKey as String: width,
895
+ kCVPixelBufferHeightKey as String: height,
896
+ kCVPixelBufferIOSurfacePropertiesKey as String: [:],
897
+ kCVPixelBufferCGImageCompatibilityKey as String: true,
898
+ kCVPixelBufferCGBitmapContextCompatibilityKey as String: true
899
+ ]
900
+
901
+ var pixelBuffer: CVPixelBuffer?
902
+ CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, attributes as CFDictionary, &pixelBuffer)
903
+
904
+ guard let buffer = pixelBuffer else {
905
+ print("🖼️ [PiP] Failed to create placeholder pixel buffer")
906
+ return
907
+ }
908
+
909
+ CVPixelBufferLockBaseAddress(buffer, [])
910
+ defer { CVPixelBufferUnlockBaseAddress(buffer, []) }
911
+
912
+ guard let context = CGContext(
913
+ data: CVPixelBufferGetBaseAddress(buffer),
914
+ width: width,
915
+ height: height,
916
+ bitsPerComponent: 8,
917
+ bytesPerRow: CVPixelBufferGetBytesPerRow(buffer),
918
+ space: CGColorSpaceCreateDeviceRGB(),
919
+ bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
920
+ ) else {
921
+ return
922
+ }
923
+
924
+ // Fill with dark background
925
+ context.setFillColor(UIColor(red: 0.1, green: 0.1, blue: 0.15, alpha: 1.0).cgColor)
926
+ context.fill(CGRect(x: 0, y: 0, width: width, height: height))
927
+
928
+ // Draw "Broadcasting" text
929
+ UIGraphicsPushContext(context)
930
+
931
+ // Flip context for proper text rendering
932
+ context.translateBy(x: 0, y: CGFloat(height))
933
+ context.scaleBy(x: 1, y: -1)
934
+
935
+ let paragraphStyle = NSMutableParagraphStyle()
936
+ paragraphStyle.alignment = .center
937
+
938
+ // Draw large red recording dot
939
+ let circleSize: CGFloat = 50
940
+ let circleRect = CGRect(x: (CGFloat(width) - circleSize) / 2, y: CGFloat(height) / 2 - 120, width: circleSize, height: circleSize)
941
+ context.setFillColor(UIColor.red.cgColor)
942
+ context.fillEllipse(in: circleRect)
943
+
944
+ // Draw "LIVE" text - large and bold
945
+ let liveText = "LIVE"
946
+ let liveAttributes: [NSAttributedString.Key: Any] = [
947
+ .font: UIFont.boldSystemFont(ofSize: 72),
948
+ .foregroundColor: UIColor.white,
949
+ .paragraphStyle: paragraphStyle
950
+ ]
951
+ let liveRect = CGRect(x: 0, y: CGFloat(height) / 2 - 40, width: CGFloat(width), height: 90)
952
+ liveText.draw(in: liveRect, withAttributes: liveAttributes)
953
+
954
+ // Draw "Broadcasting in progress" text
955
+ let subText = "Broadcasting in progress"
956
+ let subAttributes: [NSAttributedString.Key: Any] = [
957
+ .font: UIFont.systemFont(ofSize: 28),
958
+ .foregroundColor: UIColor.lightGray,
959
+ .paragraphStyle: paragraphStyle
960
+ ]
961
+ let subRect = CGRect(x: 0, y: CGFloat(height) / 2 + 60, width: CGFloat(width), height: 40)
962
+ subText.draw(in: subRect, withAttributes: subAttributes)
963
+
964
+ UIGraphicsPopContext()
965
+
966
+ self.placeholderPixelBuffer = buffer
967
+ print("🖼️ [PiP] Placeholder pixel buffer created")
968
+ }
969
+
970
+ /// Start generating placeholder frames to keep PiP alive
971
+ private func startPlaceholderFrameGeneration() {
972
+ guard placeholderTimer == nil else { return }
973
+
974
+ isUsingPlaceholder = true
975
+ print("🖼️ [PiP] Starting placeholder frame generation")
976
+
977
+ // Generate placeholder frames at 10fps to keep PiP alive
978
+ placeholderTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
979
+ self?.enqueuePlaceholderFrame()
980
+ }
981
+ RunLoop.main.add(placeholderTimer!, forMode: .common)
982
+ }
983
+
984
+ /// Stop generating placeholder frames
985
+ private func stopPlaceholderFrameGeneration() {
986
+ placeholderTimer?.invalidate()
987
+ placeholderTimer = nil
988
+ isUsingPlaceholder = false
989
+ print("🖼️ [PiP] Stopped placeholder frame generation")
990
+ }
991
+
992
+ /// Enqueue a placeholder frame
993
+ private func enqueuePlaceholderFrame() {
994
+ guard isEnabled, let pixelBuffer = placeholderPixelBuffer, let displayLayer = sampleBufferDisplayLayer else {
995
+ return
996
+ }
997
+
998
+ guard let sampleBuffer = createSampleBuffer(from: pixelBuffer) else {
999
+ return
1000
+ }
1001
+
1002
+ sampleBufferQueue.async { [weak displayLayer] in
1003
+ guard let displayLayer = displayLayer else { return }
1004
+
1005
+ if displayLayer.status == .failed {
1006
+ displayLayer.flush()
1007
+ }
1008
+
1009
+ displayLayer.enqueue(sampleBuffer)
1010
+ }
1011
+ }
1012
+
1013
+ /// Check if we should switch to placeholder (called when real frames stop coming)
1014
+ private func checkForPlaceholderSwitch() {
1015
+ let timeSinceLastFrame = CFAbsoluteTimeGetCurrent() - lastRealFrameTime
1016
+
1017
+ if timeSinceLastFrame > placeholderTimeout && !isUsingPlaceholder && isActive {
1018
+ print("🖼️ [PiP] No real frames for \(timeSinceLastFrame)s, switching to placeholder")
1019
+ startPlaceholderFrameGeneration()
1020
+ }
1021
+ }
1022
+
1023
+ private func cleanup() {
1024
+ // Ensure we're on the main thread for UI operations
1025
+ guard Thread.isMainThread else {
1026
+ DispatchQueue.main.sync { [weak self] in
1027
+ self?.cleanup()
1028
+ }
1029
+ return
1030
+ }
1031
+
1032
+ // Stop placeholder frame generation
1033
+ stopPlaceholderFrameGeneration()
1034
+
1035
+ pipController?.stopPictureInPicture()
1036
+ pipController = nil
1037
+ pipContentSource = nil
1038
+
1039
+ // Clean up Video Call components
1040
+ sampleBufferVideoCallView?.removeFromSuperview()
1041
+ sampleBufferVideoCallView = nil
1042
+ pipVideoCallViewController = nil
1043
+
1044
+ sampleBufferDisplayLayer?.flush()
1045
+ sampleBufferDisplayLayer = nil
1046
+
1047
+ // Don't remove pipContainerView if it's the actual source view (not owned by us)
1048
+ if pipContainerView != activeSourceView {
1049
+ pipContainerView?.removeFromSuperview()
1050
+ }
1051
+ pipContainerView = nil
1052
+ activeSourceView = nil
1053
+
1054
+ frameCount = 0
1055
+ enqueuedFrameCount = 0
1056
+ startTime = nil
1057
+ isActive = false
1058
+ }
1059
+
1060
+ // MARK: - App Lifecycle
1061
+
1062
+ @objc private func applicationWillResignActive() {
1063
+ // NOTE: We no longer manually trigger PiP here because
1064
+ // AVPictureInPictureController.canStartPictureInPictureAutomaticallyFromInline = true
1065
+ // handles auto-entering PiP automatically when the app goes to background.
1066
+ // Manual triggering was causing "Failed to start" errors due to race conditions
1067
+ // with the system's built-in auto-enter mechanism.
1068
+ print("🖼️ [PiP] App going to background (system handles auto-enter)")
1069
+ }
1070
+
1071
+ @objc private func applicationDidBecomeActive() {
1072
+ // Could be used for cleanup or state updates when app returns
1073
+ print("🖼️ [PiP] App became active")
1074
+ }
1075
+
1076
+ // MARK: - Public Getters
1077
+
1078
+ public var isPictureInPicturePossible: Bool {
1079
+ return pipController?.isPictureInPicturePossible ?? false
1080
+ }
1081
+
1082
+ public var currentSourceView: PiPOptions.PiPSourceView {
1083
+ return options.sourceView
1084
+ }
1085
+ }
1086
+
1087
+ // MARK: - AVPictureInPictureControllerDelegate
1088
+
1089
+ @available(iOS 15.0, *)
1090
+ extension IVSPictureInPictureController: AVPictureInPictureControllerDelegate {
1091
+
1092
+ public func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
1093
+ print("🖼️ [PiP] Will start")
1094
+ }
1095
+
1096
+ public func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
1097
+ isActive = true
1098
+ lastRealFrameTime = CFAbsoluteTimeGetCurrent() // Reset timer
1099
+
1100
+ // Start monitoring for frame timeout to switch to placeholder
1101
+ startFrameMonitoring()
1102
+
1103
+ print("🖼️ [PiP] Did start")
1104
+ delegate?.pictureInPictureDidStart()
1105
+ }
1106
+
1107
+ /// Start monitoring for frame timeout
1108
+ private func startFrameMonitoring() {
1109
+ // Check every 0.5 seconds if we should switch to placeholder
1110
+ Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] timer in
1111
+ guard let self = self else {
1112
+ timer.invalidate()
1113
+ return
1114
+ }
1115
+
1116
+ // Stop monitoring if PiP is no longer active
1117
+ if !self.isActive {
1118
+ timer.invalidate()
1119
+ return
1120
+ }
1121
+
1122
+ self.checkForPlaceholderSwitch()
1123
+ }
1124
+ }
1125
+
1126
+ public func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
1127
+ print("🖼️ [PiP] Will stop")
1128
+ }
1129
+
1130
+ public func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
1131
+ isActive = false
1132
+
1133
+ // Stop placeholder frame generation
1134
+ stopPlaceholderFrameGeneration()
1135
+
1136
+ // Reset timing for next PiP session - this is crucial for re-enabling PiP
1137
+ startTime = nil
1138
+ frameCount = 0
1139
+ enqueuedFrameCount = 0
1140
+
1141
+ // Flush the display layer to prepare for fresh frames
1142
+ sampleBufferDisplayLayer?.flush()
1143
+
1144
+ // Pre-warm with a few placeholder frames so PiP can start again immediately
1145
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
1146
+ self?.enqueuePlaceholderFrame()
1147
+ self?.enqueuePlaceholderFrame()
1148
+ self?.enqueuePlaceholderFrame()
1149
+ }
1150
+
1151
+ print("🖼️ [PiP] Did stop - state reset for next session")
1152
+ delegate?.pictureInPictureDidStop()
1153
+ }
1154
+
1155
+ public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
1156
+ isActive = false
1157
+ print("🖼️ [PiP] Failed to start: \(error.localizedDescription)")
1158
+ delegate?.pictureInPictureDidFail(with: error.localizedDescription)
1159
+ }
1160
+
1161
+ public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
1162
+ print("🖼️ [PiP] Restore user interface requested")
1163
+ delegate?.pictureInPictureWillRestore()
1164
+ completionHandler(true)
1165
+ }
1166
+ }
1167
+
1168
+ // MARK: - AVPictureInPictureSampleBufferPlaybackDelegate
1169
+
1170
+ @available(iOS 15.0, *)
1171
+ extension IVSPictureInPictureController: AVPictureInPictureSampleBufferPlaybackDelegate {
1172
+
1173
+ public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, setPlaying playing: Bool) {
1174
+ // For live streaming, we ignore play/pause requests - always playing
1175
+ print("🖼️ [PiP] setPlaying: \(playing) (ignored - live stream)")
1176
+ }
1177
+
1178
+ public func pictureInPictureControllerTimeRangeForPlayback(_ pictureInPictureController: AVPictureInPictureController) -> CMTimeRange {
1179
+ // Return .invalid to indicate live streaming (no seek bar, no time display)
1180
+ // This tells the system there's no seekable content
1181
+ return .invalid
1182
+ }
1183
+
1184
+ public func pictureInPictureControllerIsPlaybackPaused(_ pictureInPictureController: AVPictureInPictureController) -> Bool {
1185
+ // Live streaming is never paused - always return false
1186
+ return false
1187
+ }
1188
+
1189
+ public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, didTransitionToRenderSize newRenderSize: CMVideoDimensions) {
1190
+ print("🖼️ [PiP] Transitioned to render size: \(newRenderSize.width)x\(newRenderSize.height)")
1191
+ }
1192
+
1193
+ public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, skipByInterval skipInterval: CMTime) async {
1194
+ // No seeking in live streams - this is a no-op for live content
1195
+ }
1196
+ }