python-aidot-cameras 0.15.3__tar.gz → 0.15.5__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.
- {python_aidot_cameras-0.15.3/python_aidot_cameras.egg-info → python_aidot_cameras-0.15.5}/PKG-INFO +1 -1
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/__main__.py +29 -5
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/client.py +27 -7
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/sdes.py +7 -1
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/sdes_open.py +16 -7
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/pyproject.toml +1 -1
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/python_aidot_cameras.egg-info/SOURCES.txt +1 -0
- python_aidot_cameras-0.15.5/tests/test_dtls_stdout_producer.py +77 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_ffmpeg_stderr_log.py +16 -2
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_serve_stderr_drain.py +29 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_teardown_exit_log.py +21 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/LICENSE +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/MANIFEST.in +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/README.md +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/__init__.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_upstream.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/__init__.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/__init__.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/clock.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/codecs/__init__.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/codecs/base.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/codecs/g711.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/codecs/g722.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/codecs/h264.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/codecs/opus.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/codecs/vpx.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/contrib/__init__.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/contrib/media.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/contrib/signaling.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/events.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/exceptions.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/jitterbuffer.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/mediastreams.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rate.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcconfiguration.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcdatachannel.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcdtlstransport.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcicetransport.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcpeerconnection.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcrtpparameters.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcrtpreceiver.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcrtpsender.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcrtptransceiver.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcsctptransport.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtcsessiondescription.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtp.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/sdp.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/stats.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/utils.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/ble_gateway.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/__init__.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/constants.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/controls.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/go2rtc.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/hwaccel.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/lan_control.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/models.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/playback.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/protocol.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/tutk.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/webrtc.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/webrtc_open.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/client.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/const.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/credentials.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/crypto.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/device_client.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/discover.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/exceptions.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/g711.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/py.typed +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/python_aidot_cameras.egg-info/entry_points.txt +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/python_aidot_cameras.egg-info/requires.txt +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/python_aidot_cameras.egg-info/top_level.txt +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/setup.cfg +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_aioice_compat.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_alarm_event.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_answer_sdp_video_pt.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_audio_mux_offline.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_backoff.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_battery_detection.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_battery_evidence_corroboration.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_battery_skip_turn.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_ble_gateway.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_constants_imports_resolve.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_deferred_hardening.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_device_login_guard.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_device_user_info_cache.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dormant_camera_cleanup.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_mux_terminal_write.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_not_ready_burst.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_pinning.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_serve_decode_skip.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_serve_open_timeout.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_skip_signaling_wait.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_slow_probe.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_egress_guard.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_env_seams.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_go2rtc.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_go2rtc_cli.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_h264_decode_rate_limit.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_highport_nomination.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_hwaccel_probe.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_ice_config_cache.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_ice_peer_reflexive.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_idle_release_both_loops.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_keepalive_renew.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_key_restart_sdp.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_keyframe_prompter.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_lan_control.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_light_active_color_mode.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_live_stream_param.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_live_validate_policy.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_logging_caps.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_media_wait_floor.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_motion_poll.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_mqtt_credential_refetch.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_mqtt_credential_self_heal.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_mqtt_password_not_persisted.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_mqtt_session_reconnect.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_narrow_pc_ice.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_no_self_referential_go2rtc.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_no_undefined_names.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_offline_keepalive_pause.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_open_fail_logger.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_open_gate_delay.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_peerid_reuse.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_persistent_mqtt.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_persistent_mqtt_robustness.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_playback_tls.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_post_merge_hardening.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_resolution_persists.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_restart_cycle.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_retry_policy.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_scripts_importable.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_adaptive.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_bridge_break_gate.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_echo_wait_timeout.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_fast_liveplay.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_idle_release.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_open_cleanup.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_serve_audio.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_serve_cmd.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_sprop.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_talk.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_terminal_ack.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_terminal_ack_latency.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_watchdog.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdp_narrowing_properties.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdp_payload_type_narrowing.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_security_hardening.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_serializable_login_info.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_serve_relay.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_session_stats.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_shared_house_seam.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_speak.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sprop_staleness.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_stream_cap.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_stream_drain_ownership.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_stream_idle.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_stream_slot_cap.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_stream_teardown.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_talk.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_terminal_ack.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_token_file_robustness.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_token_refresh.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_turn_create_permission.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_upstream_compat.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_viewer_check_throttle.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_viewer_presence.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_viewer_present_push_mode.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_wait_or_event.py +0 -0
- {python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_wake_readiness_retry.py +0 -0
{python_aidot_cameras-0.15.3/python_aidot_cameras.egg-info → python_aidot_cameras-0.15.5}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-aidot-cameras
|
|
3
|
-
Version: 0.15.
|
|
3
|
+
Version: 0.15.5
|
|
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
|
|
@@ -45,9 +45,18 @@ go2rtc.yaml example (SDES camera - native RTSP push, video + audio):
|
|
|
45
45
|
streams:
|
|
46
46
|
frontdoor: exec:aidot-go2rtc 8d2521ea... {output}
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
A DTLS camera (A000088) has no RTSP-push path, but a stdout producer works the
|
|
49
|
+
same lazy way. Pass ``-`` as the output and this process writes MPEG-TS (video
|
|
50
|
+
plus AAC audio) to stdout, which go2rtc's exec: source reads directly:
|
|
51
|
+
|
|
52
|
+
streams:
|
|
53
|
+
driveway: exec:aidot-go2rtc 7c89a5c1... -
|
|
54
|
+
|
|
55
|
+
go2rtc then owns the lifecycle - spawn on the first viewer, kill when idle -
|
|
56
|
+
exactly as it does with ``{output}`` for an SDES camera. An
|
|
57
|
+
``http://host:port/name.ts`` output still works too: the older HTTP-listen
|
|
58
|
+
serve, useful for a persistent consumer that is not go2rtc, but that process
|
|
59
|
+
must stay running to keep the serve bound.
|
|
51
60
|
"""
|
|
52
61
|
|
|
53
62
|
from __future__ import annotations
|
|
@@ -225,7 +234,21 @@ async def cmd_stream(dev_id: str, output_url: str) -> int:
|
|
|
225
234
|
|
|
226
235
|
dc = client.get_device_client(device)
|
|
227
236
|
|
|
228
|
-
if
|
|
237
|
+
if output_url == "-":
|
|
238
|
+
# Stdout producer: MPEG-TS on this process's stdout, for a go2rtc
|
|
239
|
+
# exec: source. SDES cameras already have {output} (RTSP push) and
|
|
240
|
+
# do not take this path, so say which one to use rather than
|
|
241
|
+
# producing an empty stream.
|
|
242
|
+
if dc.is_sdes_camera:
|
|
243
|
+
sys.exit(
|
|
244
|
+
f"{dev_id} is an SDES camera - '-' (stdout) is the DTLS "
|
|
245
|
+
"producer path. Use {output} (RTSP push) instead."
|
|
246
|
+
)
|
|
247
|
+
_LOGGER.info(
|
|
248
|
+
"DTLS stdout mode: writing MPEG-TS (video + AAC audio) to "
|
|
249
|
+
"stdout for a go2rtc exec: consumer."
|
|
250
|
+
)
|
|
251
|
+
elif not output_url.startswith("rtsp") and dc.is_sdes_camera:
|
|
229
252
|
_LOGGER.warning(
|
|
230
253
|
"SDES camera but output %r is not rtsp:// - the library will "
|
|
231
254
|
"HTTP-serve (video only by default) instead of pushing audio+video. "
|
|
@@ -235,7 +258,8 @@ async def cmd_stream(dev_id: str, output_url: str) -> int:
|
|
|
235
258
|
if output_url.startswith("rtsp") and not dc.is_sdes_camera:
|
|
236
259
|
sys.exit(
|
|
237
260
|
f"{dev_id} is a DTLS camera - the library has no RTSP-push path "
|
|
238
|
-
"for it. Use
|
|
261
|
+
"for it. Use '-' (stdout, for a go2rtc exec: source) or an "
|
|
262
|
+
"http://host:port/name.ts serve URL instead."
|
|
239
263
|
)
|
|
240
264
|
|
|
241
265
|
await dc.async_login()
|
|
@@ -4552,16 +4552,36 @@ class CameraMixin(_CameraControlsMixin, _WebRTCOpenMixin, _SdesOpenMixin):
|
|
|
4552
4552
|
# AIDOT_DTLS_RETRY_GATE_S and added dead latency after healthy drops.)
|
|
4553
4553
|
|
|
4554
4554
|
async def _spawn_dtls_serve_ffmpeg(self, serve_url: Optional[str], stdin_fd: int):
|
|
4555
|
-
"""Launch ffmpeg to serve the mux thread's MPEG-TS (read from ``stdin_fd``)
|
|
4556
|
-
|
|
4557
|
-
timestamped + AAC-muxed (with the
|
|
4558
|
-
ffmpeg just copies and serves -
|
|
4559
|
-
(mpegts PMT-timing on the
|
|
4555
|
+
"""Launch ffmpeg to serve the mux thread's MPEG-TS (read from ``stdin_fd``).
|
|
4556
|
+
|
|
4557
|
+
The stream is already cleanly timestamped + AAC-muxed (with the
|
|
4558
|
+
gain/limiter applied) by PyAV, so ffmpeg just copies and serves -
|
|
4559
|
+
re-encoding here dropped the live audio (mpegts PMT-timing on the
|
|
4560
|
+
real-time pipe). Returns the process, or None.
|
|
4561
|
+
|
|
4562
|
+
Two destinations:
|
|
4563
|
+
|
|
4564
|
+
- ``serve_url == "-"`` -> STDOUT model: write MPEG-TS to this process's
|
|
4565
|
+
own stdout (``pipe:1``), so a parent that spawned us - go2rtc's
|
|
4566
|
+
``exec:`` source - consumes the camera directly and owns the process
|
|
4567
|
+
lifecycle (spawn on first viewer, kill on idle). No listen port and
|
|
4568
|
+
no cold-start relay, which is the DTLS analogue of the SDES
|
|
4569
|
+
``{output}`` RTSP push. Logging already goes to stderr, so stdout
|
|
4570
|
+
carries nothing but media.
|
|
4571
|
+
- anything else -> HTTP-listen model, unchanged: serve on a ``-listen``
|
|
4572
|
+
socket that go2rtc pulls.
|
|
4573
|
+
"""
|
|
4560
4574
|
if not serve_url:
|
|
4561
4575
|
return None
|
|
4562
4576
|
if _ffmpeg_path() is None:
|
|
4563
4577
|
_LOGGER.error("DTLS serve: %s", _FFMPEG_MISSING_MSG)
|
|
4564
4578
|
return None
|
|
4579
|
+
if serve_url == "-":
|
|
4580
|
+
out_args = ["-f", "mpegts", "pipe:1"]
|
|
4581
|
+
out_target = 1 # this process's real stdout
|
|
4582
|
+
else:
|
|
4583
|
+
out_args = ["-f", "mpegts", "-listen", "1", serve_url]
|
|
4584
|
+
out_target = asyncio.subprocess.DEVNULL
|
|
4565
4585
|
cmd = [
|
|
4566
4586
|
"ffmpeg", "-y", "-loglevel", "warning",
|
|
4567
4587
|
# Suppress input-side buffering: the PyAV mux already writes
|
|
@@ -4572,13 +4592,13 @@ class CameraMixin(_CameraControlsMixin, _WebRTCOpenMixin, _SdesOpenMixin):
|
|
|
4572
4592
|
# bursty/choppy audio pattern. Matches the SDES serve's approach.
|
|
4573
4593
|
"-fflags", "+nobuffer",
|
|
4574
4594
|
"-i", "pipe:0",
|
|
4575
|
-
"-c", "copy",
|
|
4595
|
+
"-c", "copy", *out_args,
|
|
4576
4596
|
]
|
|
4577
4597
|
try:
|
|
4578
4598
|
return await asyncio.create_subprocess_exec(
|
|
4579
4599
|
*cmd,
|
|
4580
4600
|
stdin=stdin_fd,
|
|
4581
|
-
stdout=
|
|
4601
|
+
stdout=out_target,
|
|
4582
4602
|
stderr=asyncio.subprocess.DEVNULL,
|
|
4583
4603
|
)
|
|
4584
4604
|
except FileNotFoundError:
|
|
@@ -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",
|
|
223
|
+
"camera %s: ffmpeg SDES stderr:\n%s",
|
|
224
|
+
getattr(self, "_device_id", "?"), text
|
|
219
225
|
)
|
|
220
226
|
|
|
221
227
|
@staticmethod
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/sdes_open.py
RENAMED
|
@@ -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
|
|
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
|
|
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
|
|
2844
|
-
" lines):\n%s",
|
|
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.
|
|
7
|
+
version = "0.15.5"
|
|
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"
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5/python_aidot_cameras.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-aidot-cameras
|
|
3
|
-
Version: 0.15.
|
|
3
|
+
Version: 0.15.5
|
|
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
|
|
@@ -90,6 +90,7 @@ tests/test_dtls_serve_decode_skip.py
|
|
|
90
90
|
tests/test_dtls_serve_open_timeout.py
|
|
91
91
|
tests/test_dtls_skip_signaling_wait.py
|
|
92
92
|
tests/test_dtls_slow_probe.py
|
|
93
|
+
tests/test_dtls_stdout_producer.py
|
|
93
94
|
tests/test_egress_guard.py
|
|
94
95
|
tests/test_env_seams.py
|
|
95
96
|
tests/test_go2rtc.py
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""The DTLS serve can write MPEG-TS to stdout for a go2rtc ``exec:`` source.
|
|
2
|
+
|
|
3
|
+
SDES cameras get a lazily-managed producer for free: go2rtc spawns the process
|
|
4
|
+
per ``{output}``, the library RTSP-pushes into it, and go2rtc kills it when the
|
|
5
|
+
last viewer leaves. DTLS had no equivalent - it could only serve on an
|
|
6
|
+
``-listen`` socket, which has to be bound before anyone asks for it and stays
|
|
7
|
+
bound afterwards.
|
|
8
|
+
|
|
9
|
+
``-`` closes that gap: ffmpeg writes to this process's own stdout, so whoever
|
|
10
|
+
spawned us is the consumer and owns the lifecycle. Everything else about the
|
|
11
|
+
serve is untouched, which is what these tests pin - a regression here would
|
|
12
|
+
either break every existing HTTP-listen serve or silently send media to
|
|
13
|
+
/dev/null.
|
|
14
|
+
"""
|
|
15
|
+
import asyncio
|
|
16
|
+
import types
|
|
17
|
+
|
|
18
|
+
import aidot_cameras.camera.client as client_mod
|
|
19
|
+
from aidot_cameras.camera.client import CameraMixin
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _spawn(monkeypatch, serve_url):
|
|
23
|
+
"""Run the real _spawn_dtls_serve_ffmpeg, capturing what it would exec."""
|
|
24
|
+
seen = {}
|
|
25
|
+
|
|
26
|
+
async def _fake_exec(*cmd, stdin=None, stdout=None, stderr=None):
|
|
27
|
+
seen["cmd"] = list(cmd)
|
|
28
|
+
seen["stdout"] = stdout
|
|
29
|
+
seen["stdin"] = stdin
|
|
30
|
+
return object()
|
|
31
|
+
|
|
32
|
+
monkeypatch.setattr(client_mod, "_ffmpeg_path", lambda: "/usr/bin/ffmpeg")
|
|
33
|
+
monkeypatch.setattr(asyncio, "create_subprocess_exec", _fake_exec)
|
|
34
|
+
obj = types.SimpleNamespace()
|
|
35
|
+
fn = CameraMixin._spawn_dtls_serve_ffmpeg.__get__(obj)
|
|
36
|
+
proc = asyncio.run(fn(serve_url, 7))
|
|
37
|
+
return proc, seen
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_stdout_mode_writes_mpegts_to_this_process_stdout(monkeypatch):
|
|
41
|
+
proc, seen = _spawn(monkeypatch, "-")
|
|
42
|
+
assert proc is not None
|
|
43
|
+
assert seen["cmd"][-3:] == ["-f", "mpegts", "pipe:1"], seen["cmd"]
|
|
44
|
+
# fd 1, not DEVNULL: the media has to reach the parent that spawned us.
|
|
45
|
+
assert seen["stdout"] == 1, (
|
|
46
|
+
"stdout mode must hand ffmpeg this process's real stdout - anything "
|
|
47
|
+
"else sends the camera to nowhere while looking healthy"
|
|
48
|
+
)
|
|
49
|
+
assert "-listen" not in seen["cmd"]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_http_listen_mode_is_unchanged(monkeypatch):
|
|
53
|
+
url = "http://127.0.0.1:18981/cam.ts"
|
|
54
|
+
proc, seen = _spawn(monkeypatch, url)
|
|
55
|
+
assert proc is not None
|
|
56
|
+
assert seen["cmd"][-4:] == ["-f", "mpegts", "-listen", "1", url][-4:]
|
|
57
|
+
assert seen["cmd"][-1] == url
|
|
58
|
+
assert "-listen" in seen["cmd"]
|
|
59
|
+
assert seen["stdout"] == asyncio.subprocess.DEVNULL, (
|
|
60
|
+
"the listen serve must keep stdout discarded; writing media to our own "
|
|
61
|
+
"stdout there would corrupt whatever the parent reads"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_both_modes_still_copy_from_the_mux_pipe(monkeypatch):
|
|
66
|
+
for url in ("-", "http://127.0.0.1:1/x.ts"):
|
|
67
|
+
_proc, seen = _spawn(monkeypatch, url)
|
|
68
|
+
cmd = seen["cmd"]
|
|
69
|
+
assert cmd[:2] == ["ffmpeg", "-y"]
|
|
70
|
+
assert "-i" in cmd and cmd[cmd.index("-i") + 1] == "pipe:0"
|
|
71
|
+
assert "-c" in cmd and cmd[cmd.index("-c") + 1] == "copy"
|
|
72
|
+
assert seen["stdin"] == 7
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_no_serve_url_still_returns_none(monkeypatch):
|
|
76
|
+
proc, seen = _spawn(monkeypatch, "")
|
|
77
|
+
assert proc is None and "cmd" not in seen
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_ffmpeg_stderr_log.py
RENAMED
|
@@ -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(
|
|
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"):
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_serve_stderr_drain.py
RENAMED
|
@@ -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
|
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_teardown_exit_log.py
RENAMED
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/__init__.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/__init__.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/clock.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/events.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rate.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/rtp.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/sdp.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/stats.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/_vendor/aiortc/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/__init__.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/constants.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/controls.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/lan_control.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/playback.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/protocol.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/aidot_cameras/camera/webrtc_open.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_answer_sdp_video_pt.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_constants_imports_resolve.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_deferred_hardening.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_device_login_guard.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_device_user_info_cache.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dormant_camera_cleanup.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_mux_terminal_write.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_not_ready_burst.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_serve_decode_skip.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_serve_open_timeout.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_dtls_skip_signaling_wait.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_h264_decode_rate_limit.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_highport_nomination.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_ice_peer_reflexive.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_idle_release_both_loops.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_light_active_color_mode.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_live_validate_policy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_mqtt_credential_refetch.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_mqtt_credential_self_heal.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_mqtt_session_reconnect.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_no_self_referential_go2rtc.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_no_undefined_names.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_offline_keepalive_pause.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_persistent_mqtt_robustness.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_post_merge_hardening.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_resolution_persists.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_scripts_importable.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_bridge_break_gate.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_echo_wait_timeout.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_fast_liveplay.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdes_terminal_ack_latency.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdp_narrowing_properties.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_sdp_payload_type_narrowing.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_security_hardening.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_serializable_login_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_stream_drain_ownership.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_token_file_robustness.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_turn_create_permission.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_viewer_check_throttle.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_viewer_present_push_mode.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.15.3 → python_aidot_cameras-0.15.5}/tests/test_wake_readiness_retry.py
RENAMED
|
File without changes
|