Add h264_v4l2m2m codec and profiles to HomeKit cameras (#91246)

This commit is contained in:
Assaf Inbal 2023-04-12 23:46:21 +03:00 committed by GitHub
parent 4f507e7f57
commit 7446ff478f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 90 additions and 4 deletions

View file

@ -19,6 +19,8 @@ VIDEO_CODEC_COPY = "copy"
VIDEO_CODEC_LIBX264 = "libx264"
AUDIO_CODEC_OPUS = "libopus"
VIDEO_CODEC_H264_OMX = "h264_omx"
VIDEO_CODEC_H264_V4L2M2M = "h264_v4l2m2m"
VIDEO_PROFILE_NAMES = ["baseline", "main", "high"]
AUDIO_CODEC_COPY = "copy"
# #### Attributes ####
@ -54,6 +56,7 @@ CONF_STREAM_ADDRESS = "stream_address"
CONF_STREAM_SOURCE = "stream_source"
CONF_SUPPORT_AUDIO = "support_audio"
CONF_VIDEO_CODEC = "video_codec"
CONF_VIDEO_PROFILE_NAMES = "video_profile_names"
CONF_VIDEO_MAP = "video_map"
CONF_VIDEO_PACKET_SIZE = "video_packet_size"
CONF_STREAM_COUNT = "stream_count"
@ -71,6 +74,7 @@ DEFAULT_MAX_WIDTH = 1920
DEFAULT_PORT = 21063
DEFAULT_CONFIG_FLOW_PORT = 21064
DEFAULT_VIDEO_CODEC = VIDEO_CODEC_LIBX264
DEFAULT_VIDEO_PROFILE_NAMES = VIDEO_PROFILE_NAMES
DEFAULT_VIDEO_MAP = "0:v:0"
DEFAULT_VIDEO_PACKET_SIZE = 1316
DEFAULT_STREAM_COUNT = 3

View file

@ -40,6 +40,7 @@ from .const import (
CONF_VIDEO_CODEC,
CONF_VIDEO_MAP,
CONF_VIDEO_PACKET_SIZE,
CONF_VIDEO_PROFILE_NAMES,
DEFAULT_AUDIO_CODEC,
DEFAULT_AUDIO_MAP,
DEFAULT_AUDIO_PACKET_SIZE,
@ -51,6 +52,7 @@ from .const import (
DEFAULT_VIDEO_CODEC,
DEFAULT_VIDEO_MAP,
DEFAULT_VIDEO_PACKET_SIZE,
DEFAULT_VIDEO_PROFILE_NAMES,
SERV_DOORBELL,
SERV_MOTION_SENSOR,
SERV_SPEAKER,
@ -111,8 +113,6 @@ RESOLUTIONS = [
(1600, 1200),
]
VIDEO_PROFILE_NAMES = ["baseline", "main", "high"]
FFMPEG_WATCH_INTERVAL = timedelta(seconds=5)
FFMPEG_LOGGER = "ffmpeg_logger"
FFMPEG_WATCHER = "ffmpeg_watcher"
@ -128,6 +128,7 @@ CONFIG_DEFAULTS = {
CONF_AUDIO_MAP: DEFAULT_AUDIO_MAP,
CONF_VIDEO_MAP: DEFAULT_VIDEO_MAP,
CONF_VIDEO_CODEC: DEFAULT_VIDEO_CODEC,
CONF_VIDEO_PROFILE_NAMES: DEFAULT_VIDEO_PROFILE_NAMES,
CONF_AUDIO_PACKET_SIZE: DEFAULT_AUDIO_PACKET_SIZE,
CONF_VIDEO_PACKET_SIZE: DEFAULT_VIDEO_PACKET_SIZE,
CONF_STREAM_COUNT: DEFAULT_STREAM_COUNT,
@ -346,7 +347,7 @@ class Camera(HomeAccessory, PyhapCamera):
if self.config[CONF_VIDEO_CODEC] != "copy":
video_profile = (
"-profile:v "
+ VIDEO_PROFILE_NAMES[
+ self.config[CONF_VIDEO_PROFILE_NAMES][
int.from_bytes(stream_config["v_profile_id"], byteorder="big")
]
+ " "

View file

@ -95,6 +95,7 @@ from .const import (
TYPE_VALVE,
VIDEO_CODEC_COPY,
VIDEO_CODEC_H264_OMX,
VIDEO_CODEC_H264_V4L2M2M,
VIDEO_CODEC_LIBX264,
)
@ -107,7 +108,12 @@ MAX_VERSION_PART = 2**32 - 1
MAX_PORT = 65535
VALID_VIDEO_CODECS = [VIDEO_CODEC_LIBX264, VIDEO_CODEC_H264_OMX, AUDIO_CODEC_COPY]
VALID_VIDEO_CODECS = [
VIDEO_CODEC_LIBX264,
VIDEO_CODEC_H264_OMX,
VIDEO_CODEC_H264_V4L2M2M,
AUDIO_CODEC_COPY,
]
VALID_AUDIO_CODECS = [AUDIO_CODEC_OPUS, VIDEO_CODEC_COPY]
BASIC_INFO_SCHEMA = vol.Schema(

View file

@ -19,11 +19,13 @@ from homeassistant.components.homekit.const import (
CONF_STREAM_SOURCE,
CONF_SUPPORT_AUDIO,
CONF_VIDEO_CODEC,
CONF_VIDEO_PROFILE_NAMES,
SERV_DOORBELL,
SERV_MOTION_SENSOR,
SERV_STATELESS_PROGRAMMABLE_SWITCH,
VIDEO_CODEC_COPY,
VIDEO_CODEC_H264_OMX,
VIDEO_CODEC_H264_V4L2M2M,
)
from homeassistant.components.homekit.type_cameras import Camera
from homeassistant.components.homekit.type_switches import Switch
@ -516,6 +518,79 @@ async def test_camera_stream_source_configured_and_copy_codec(
)
async def test_camera_stream_source_configured_and_override_profile_names(
hass: HomeAssistant, run_driver, events
) -> None:
"""Test a camera that can stream with a configured source over overridden profile names."""
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
await async_setup_component(
hass, camera.DOMAIN, {camera.DOMAIN: {"platform": "demo"}}
)
await hass.async_block_till_done()
entity_id = "camera.demo_camera"
hass.states.async_set(entity_id, None)
await hass.async_block_till_done()
acc = Camera(
hass,
run_driver,
"Camera",
entity_id,
2,
{
CONF_STREAM_SOURCE: "/dev/null",
CONF_SUPPORT_AUDIO: True,
CONF_VIDEO_CODEC: VIDEO_CODEC_H264_V4L2M2M,
CONF_VIDEO_PROFILE_NAMES: ["0", "2", "4"],
CONF_AUDIO_CODEC: AUDIO_CODEC_COPY,
},
)
bridge = HomeBridge("hass", run_driver, "Test Bridge")
bridge.add_accessory(acc)
await acc.run()
assert acc.aid == 2
assert acc.category == 17 # Camera
await _async_setup_endpoints(hass, acc)
session_info = acc.sessions[MOCK_START_STREAM_SESSION_UUID]
working_ffmpeg = _get_working_mock_ffmpeg()
with patch(
"homeassistant.components.demo.camera.DemoCamera.stream_source",
return_value=None,
), patch(
"homeassistant.components.homekit.type_cameras.HAFFmpeg",
return_value=working_ffmpeg,
):
await _async_start_streaming(hass, acc)
await _async_reconfigure_stream(hass, acc, session_info, {})
await _async_stop_all_streams(hass, acc)
expected_output = (
"-map 0:v:0 -an -c:v h264_v4l2m2m -profile:v 4 -tune zerolatency -pix_fmt yuv420p -r 30 -b:v 299k "
"-bufsize 1196k -maxrate 299k -payload_type 99 -ssrc {v_ssrc} -f rtp -srtp_out_suite "
"AES_CM_128_HMAC_SHA1_80 -srtp_out_params zdPmNLWeI86DtLJHvVLI6YPvqhVeeiLsNtrAgbgL "
"srtp://192.168.208.5:51246?rtcpport=51246&localrtcpport=51246&pkt_size=1316 -map 0:a:0 "
"-vn -c:a copy -ac 1 -ar 24k -b:a 24k -bufsize 96k -payload_type 110 -ssrc {a_ssrc} "
"-f rtp -srtp_out_suite AES_CM_128_HMAC_SHA1_80 -srtp_out_params "
"shnETgfD+7xUQ8zRdsaytY11wu6CO73IJ+RZVJpU "
"srtp://192.168.208.5:51108?rtcpport=51108&localrtcpport=51108&pkt_size=188"
)
working_ffmpeg.open.assert_called_with(
cmd=[],
input_source="-i /dev/null",
output=expected_output.format(**session_info),
stdout_pipe=False,
extra_cmd="-hide_banner -nostats",
stderr_pipe=True,
)
async def test_camera_streaming_fails_after_starting_ffmpeg(
hass: HomeAssistant, run_driver, events
) -> None: