python-aidot-cameras 0.15.3__tar.gz → 0.15.4__tar.gz

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 (174) hide show
  1. {python_aidot_cameras-0.15.3/python_aidot_cameras.egg-info → python_aidot_cameras-0.15.4}/PKG-INFO +1 -1
  2. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/sdes.py +7 -1
  3. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/sdes_open.py +16 -7
  4. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/pyproject.toml +1 -1
  5. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
  6. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_ffmpeg_stderr_log.py +16 -2
  7. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_serve_stderr_drain.py +29 -0
  8. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_teardown_exit_log.py +21 -0
  9. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/LICENSE +0 -0
  10. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/MANIFEST.in +0 -0
  11. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/README.md +0 -0
  12. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/__init__.py +0 -0
  13. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/__main__.py +0 -0
  14. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_upstream.py +0 -0
  15. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/__init__.py +0 -0
  16. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/__init__.py +0 -0
  17. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/clock.py +0 -0
  18. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/codecs/__init__.py +0 -0
  19. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/codecs/base.py +0 -0
  20. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/codecs/g711.py +0 -0
  21. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/codecs/g722.py +0 -0
  22. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/codecs/h264.py +0 -0
  23. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/codecs/opus.py +0 -0
  24. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/codecs/vpx.py +0 -0
  25. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/contrib/__init__.py +0 -0
  26. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/contrib/media.py +0 -0
  27. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/contrib/signaling.py +0 -0
  28. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/events.py +0 -0
  29. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/exceptions.py +0 -0
  30. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/jitterbuffer.py +0 -0
  31. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/mediastreams.py +0 -0
  32. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rate.py +0 -0
  33. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcconfiguration.py +0 -0
  34. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcdatachannel.py +0 -0
  35. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcdtlstransport.py +0 -0
  36. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcicetransport.py +0 -0
  37. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcpeerconnection.py +0 -0
  38. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcrtpparameters.py +0 -0
  39. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcrtpreceiver.py +0 -0
  40. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcrtpsender.py +0 -0
  41. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcrtptransceiver.py +0 -0
  42. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcsctptransport.py +0 -0
  43. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtcsessiondescription.py +0 -0
  44. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/rtp.py +0 -0
  45. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/sdp.py +0 -0
  46. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/stats.py +0 -0
  47. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/_vendor/aiortc/utils.py +0 -0
  48. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/ble_gateway.py +0 -0
  49. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/__init__.py +0 -0
  50. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/client.py +0 -0
  51. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/constants.py +0 -0
  52. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/controls.py +0 -0
  53. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/go2rtc.py +0 -0
  54. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/hwaccel.py +0 -0
  55. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/lan_control.py +0 -0
  56. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/models.py +0 -0
  57. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/playback.py +0 -0
  58. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/protocol.py +0 -0
  59. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/tutk.py +0 -0
  60. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/webrtc.py +0 -0
  61. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/camera/webrtc_open.py +0 -0
  62. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/client.py +0 -0
  63. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/const.py +0 -0
  64. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/credentials.py +0 -0
  65. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/crypto.py +0 -0
  66. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/device_client.py +0 -0
  67. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/discover.py +0 -0
  68. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/exceptions.py +0 -0
  69. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/g711.py +0 -0
  70. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/aidot_cameras/py.typed +0 -0
  71. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/python_aidot_cameras.egg-info/SOURCES.txt +0 -0
  72. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
  73. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/python_aidot_cameras.egg-info/entry_points.txt +0 -0
  74. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/python_aidot_cameras.egg-info/requires.txt +0 -0
  75. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/python_aidot_cameras.egg-info/top_level.txt +0 -0
  76. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/setup.cfg +0 -0
  77. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_aioice_compat.py +0 -0
  78. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_alarm_event.py +0 -0
  79. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_answer_sdp_video_pt.py +0 -0
  80. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_audio_mux_offline.py +0 -0
  81. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_backoff.py +0 -0
  82. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_battery_detection.py +0 -0
  83. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_battery_evidence_corroboration.py +0 -0
  84. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_battery_skip_turn.py +0 -0
  85. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_ble_gateway.py +0 -0
  86. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_constants_imports_resolve.py +0 -0
  87. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_deferred_hardening.py +0 -0
  88. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_device_login_guard.py +0 -0
  89. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_device_user_info_cache.py +0 -0
  90. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_dormant_camera_cleanup.py +0 -0
  91. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_dtls_mux_terminal_write.py +0 -0
  92. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_dtls_not_ready_burst.py +0 -0
  93. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_dtls_pinning.py +0 -0
  94. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_dtls_serve_decode_skip.py +0 -0
  95. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_dtls_serve_open_timeout.py +0 -0
  96. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_dtls_skip_signaling_wait.py +0 -0
  97. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_dtls_slow_probe.py +0 -0
  98. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_egress_guard.py +0 -0
  99. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_env_seams.py +0 -0
  100. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_go2rtc.py +0 -0
  101. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_go2rtc_cli.py +0 -0
  102. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_h264_decode_rate_limit.py +0 -0
  103. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_highport_nomination.py +0 -0
  104. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_hwaccel_probe.py +0 -0
  105. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_ice_config_cache.py +0 -0
  106. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_ice_peer_reflexive.py +0 -0
  107. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_idle_release_both_loops.py +0 -0
  108. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_keepalive_renew.py +0 -0
  109. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_key_restart_sdp.py +0 -0
  110. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_keyframe_prompter.py +0 -0
  111. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_lan_control.py +0 -0
  112. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_light_active_color_mode.py +0 -0
  113. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_live_stream_param.py +0 -0
  114. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_live_validate_policy.py +0 -0
  115. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_logging_caps.py +0 -0
  116. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_media_wait_floor.py +0 -0
  117. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_motion_poll.py +0 -0
  118. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_mqtt_credential_refetch.py +0 -0
  119. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_mqtt_credential_self_heal.py +0 -0
  120. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_mqtt_password_not_persisted.py +0 -0
  121. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_mqtt_session_reconnect.py +0 -0
  122. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_narrow_pc_ice.py +0 -0
  123. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_no_self_referential_go2rtc.py +0 -0
  124. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_no_undefined_names.py +0 -0
  125. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_offline_keepalive_pause.py +0 -0
  126. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_open_fail_logger.py +0 -0
  127. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_open_gate_delay.py +0 -0
  128. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_peerid_reuse.py +0 -0
  129. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_persistent_mqtt.py +0 -0
  130. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_persistent_mqtt_robustness.py +0 -0
  131. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_playback_tls.py +0 -0
  132. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_post_merge_hardening.py +0 -0
  133. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_resolution_persists.py +0 -0
  134. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_restart_cycle.py +0 -0
  135. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_retry_policy.py +0 -0
  136. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_scripts_importable.py +0 -0
  137. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_adaptive.py +0 -0
  138. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_bridge_break_gate.py +0 -0
  139. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_echo_wait_timeout.py +0 -0
  140. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_fast_liveplay.py +0 -0
  141. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_idle_release.py +0 -0
  142. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_open_cleanup.py +0 -0
  143. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_serve_audio.py +0 -0
  144. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_serve_cmd.py +0 -0
  145. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_sprop.py +0 -0
  146. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_talk.py +0 -0
  147. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_terminal_ack.py +0 -0
  148. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_terminal_ack_latency.py +0 -0
  149. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdes_watchdog.py +0 -0
  150. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdp_narrowing_properties.py +0 -0
  151. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sdp_payload_type_narrowing.py +0 -0
  152. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_security_hardening.py +0 -0
  153. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_serializable_login_info.py +0 -0
  154. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_serve_relay.py +0 -0
  155. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_session_stats.py +0 -0
  156. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_shared_house_seam.py +0 -0
  157. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_speak.py +0 -0
  158. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_sprop_staleness.py +0 -0
  159. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_stream_cap.py +0 -0
  160. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_stream_drain_ownership.py +0 -0
  161. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_stream_idle.py +0 -0
  162. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_stream_slot_cap.py +0 -0
  163. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_stream_teardown.py +0 -0
  164. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_talk.py +0 -0
  165. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_terminal_ack.py +0 -0
  166. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_token_file_robustness.py +0 -0
  167. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_token_refresh.py +0 -0
  168. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_turn_create_permission.py +0 -0
  169. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_upstream_compat.py +0 -0
  170. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_viewer_check_throttle.py +0 -0
  171. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_viewer_presence.py +0 -0
  172. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_viewer_present_push_mode.py +0 -0
  173. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_wait_or_event.py +0 -0
  174. {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.4}/tests/test_wake_readiness_retry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 0.15.3
3
+ Version: 0.15.4
4
4
  Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
5
5
  Author-email: cbrightly <chris.brightly@gmail.com>
6
6
  License-Expression: MIT
@@ -38,7 +38,12 @@ class SdesSession:
38
38
  teardown_requested=None,
39
39
  first_video_pt=None,
40
40
  first_audio_pt=None,
41
+ device_id=None,
41
42
  ) -> None:
43
+ # Which camera this session belongs to, for logging only. Optional so
44
+ # an existing caller that does not pass it still works; the logs then
45
+ # read "?" exactly as they did before.
46
+ self._device_id = device_id or "?"
42
47
  self._proc = proc
43
48
  self._sdp_path = sdp_path
44
49
  self._outgoing_q = outgoing_q
@@ -215,7 +220,8 @@ class SdesSession:
215
220
  or "Could not find codec parameters" in text
216
221
  )
217
222
  (_LOGGER.debug if expected_no_media else _LOGGER.warning)(
218
- "ffmpeg SDES stderr:\n%s", text
223
+ "camera %s: ffmpeg SDES stderr:\n%s",
224
+ getattr(self, "_device_id", "?"), text
219
225
  )
220
226
 
221
227
  @staticmethod
@@ -2825,23 +2825,31 @@ class _SdesOpenMixin:
2825
2825
  _br_level = _classify_ffmpeg_exit(
2826
2826
  _br_rc, _br_teardown_requested
2827
2827
  )
2828
+ # Name the camera. These lines used to carry no
2829
+ # device id at all, and this account runs several
2830
+ # SDES cameras at once, so a burst of exits could
2831
+ # not be attributed to one of them without extra
2832
+ # tooling - which sent a live investigation down
2833
+ # the wrong path once already.
2834
+ _br_dev = getattr(self, "device_id", "?")
2828
2835
  _br_msg = (
2829
- "SDES bridge: ffmpeg exited with code %d"
2830
- " - stopped by teardown"
2836
+ "camera %s: SDES bridge: ffmpeg exited with"
2837
+ " code %d - stopped by teardown"
2831
2838
  if _br_level < _log_br.WARNING else
2832
- "SDES bridge: ffmpeg exited with code %d"
2833
- " - stream ended"
2839
+ "camera %s: SDES bridge: ffmpeg exited with"
2840
+ " code %d - stream ended"
2834
2841
  )
2835
2842
  _log_br.getLogger(__name__).log(
2836
- _br_level, _br_msg, _br_rc
2843
+ _br_level, _br_msg, _br_dev, _br_rc
2837
2844
  )
2838
2845
  if _br_level >= _log_br.WARNING:
2839
2846
  _serr_tail = getattr(
2840
2847
  _br_proc, "_aidot_stderr_tail", None)
2841
2848
  if _serr_tail:
2842
2849
  _log_br.getLogger(__name__).warning(
2843
- "SDES serve ffmpeg stderr (last %d"
2844
- " lines):\n%s", len(_serr_tail),
2850
+ "camera %s: SDES serve ffmpeg stderr"
2851
+ " (last %d lines):\n%s", _br_dev,
2852
+ len(_serr_tail),
2845
2853
  "\n".join(_serr_tail),
2846
2854
  )
2847
2855
  if _bridge_should_break(
@@ -4909,4 +4917,5 @@ class _SdesOpenMixin:
4909
4917
  teardown_requested=_teardown_holder,
4910
4918
  first_video_pt=_first_video_pt,
4911
4919
  first_audio_pt=_first_audio_pt,
4920
+ device_id=getattr(self, "device_id", None),
4912
4921
  )
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-aidot-cameras"
7
- version = "0.15.3"
7
+ version = "0.15.4"
8
8
  description = "Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 0.15.3
3
+ Version: 0.15.4
4
4
  Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
5
5
  Author-email: cbrightly <chris.brightly@gmail.com>
6
6
  License-Expression: MIT
@@ -12,8 +12,10 @@ import types
12
12
  from aidot_cameras.camera.sdes import SdesSession
13
13
 
14
14
 
15
- def _log_fn(last_media):
16
- obj = types.SimpleNamespace(last_media_monotonic=last_media)
15
+ def _log_fn(last_media, device_id="dev-abc"):
16
+ obj = types.SimpleNamespace(
17
+ last_media_monotonic=last_media, _device_id=device_id
18
+ )
17
19
  return SdesSession._log_ffmpeg_stderr.__get__(obj)
18
20
 
19
21
 
@@ -31,6 +33,18 @@ def test_no_media_expected_shape_logs_debug(caplog):
31
33
  assert recs and recs[0].levelno == logging.DEBUG, msg
32
34
 
33
35
 
36
+ def test_the_log_names_the_camera(caplog):
37
+ """Several SDES cameras stream at once; an unattributed line is near-useless.
38
+
39
+ A burst of these lines with no device id could not be pinned to a camera
40
+ during a live investigation, which cost real time and one wrong conclusion.
41
+ """
42
+ with caplog.at_level(logging.DEBUG, logger="aidot_cameras.camera.sdes"):
43
+ _log_fn(1.0, device_id="12b144cb12da")(b"Error writing trailer")
44
+ recs = _stderr_records(caplog)
45
+ assert recs and "12b144cb12da" in recs[0].getMessage()
46
+
47
+
34
48
  def test_no_media_unexpected_error_still_warns(caplog):
35
49
  # No media, but NOT the expected empty-output shape -> a real ffmpeg failure.
36
50
  with caplog.at_level(logging.DEBUG, logger="aidot_cameras.camera.sdes"):
@@ -59,6 +59,35 @@ def test_stderr_none_is_safe() -> None:
59
59
  assert _tail(proc) == []
60
60
 
61
61
 
62
+ def test_every_piped_spawn_installs_the_drain() -> None:
63
+ """A serve spawned with an un-drained ``stderr=PIPE`` is the outage itself.
64
+
65
+ There are two serve-spawn sites (cold open and key-restart), and the bug
66
+ shipped because a pipe was opened at one of them with nothing reading it.
67
+ A third site, or a drain call deleted from an existing one, reintroduces it
68
+ exactly - and no behavioural test can see the difference until ffmpeg has
69
+ written ~64KB, which is far past where a unit test looks. Pin the source.
70
+ """
71
+ import inspect
72
+
73
+ from aidot_cameras.camera import sdes_open
74
+
75
+ src = inspect.getsource(sdes_open).splitlines()
76
+ spawns = [i for i, line in enumerate(src) if "stderr=subprocess.PIPE" in line]
77
+ assert spawns, (
78
+ "no piped spawn found in sdes_open - if the serve stopped using a pipe "
79
+ "this guard is obsolete, but do not delete it without checking why"
80
+ )
81
+ for line_no in spawns:
82
+ window = "\n".join(src[line_no:line_no + 12])
83
+ assert "_start_serve_stderr_drain(" in window, (
84
+ f"{sdes_open.__name__}:{line_no + 1} spawns with stderr=PIPE and "
85
+ "nothing drains it within the next few lines. An un-drained pipe "
86
+ "fills at ~64KB and blocks ffmpeg on its next write, which kills "
87
+ "the RTSP publisher and 404s every viewer"
88
+ )
89
+
90
+
62
91
  class _TornDownProc:
63
92
  """A serve proc whose stderr pipe the drainer already emptied.
64
93
 
@@ -61,6 +61,27 @@ def test_reap_sets_teardown_flag_before_kill():
61
61
  )
62
62
 
63
63
 
64
+ def test_the_bridge_exit_log_names_the_camera():
65
+ """The exit line is emitted from a closure the tests cannot call directly.
66
+
67
+ It is still worth pinning: this account streams several SDES cameras at
68
+ once, and while these lines carried no device id a burst of exits could not
69
+ be attributed to a camera at all. Assert the format string takes one, and
70
+ that the session is handed the id it needs for its own stderr log.
71
+ """
72
+ src = inspect.getsource(sdes_open)
73
+ assert "camera %s: SDES bridge: ffmpeg exited" in src, (
74
+ "the bridge exit log lost its device id - a burst of these is "
75
+ "unattributable without it"
76
+ )
77
+ assert "camera %s: SDES serve ffmpeg stderr" in src
78
+ start = src.index("return SdesSession(")
79
+ assert "device_id=" in src[start:start + 800], (
80
+ "SdesSession is constructed without a device_id, so its own stderr "
81
+ "log cannot name the camera"
82
+ )
83
+
84
+
64
85
  class _FakeProc:
65
86
  def __init__(self):
66
87
  self._alive = True