From b4a5a370b1cf0ddc6cc36ebc115a6ead27262e65 Mon Sep 17 00:00:00 2001 From: Billal Ghilas <84322223+gBillal@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:30:27 +0100 Subject: [PATCH] Refactor get live snapshot (#549) * refactor get snapshot from recording * delete old code * upgrade deps --- nerves_fw/mix.lock | 24 +++--- rtsp/mix.lock | 2 +- ui/config/runtime.exs | 9 +-- ui/lib/ex_nvr/decoder.ex | 18 ++++- ui/lib/ex_nvr/elements/cvs_bufferer.ex | 37 +++++---- ui/lib/ex_nvr/elements/snapshot_bin.ex | 81 ------------------- ui/lib/ex_nvr/pipeline/output/socket.ex | 2 +- ui/lib/ex_nvr/pipeline/output/storage.ex | 2 +- ui/lib/ex_nvr/pipeline/output/thumbnailer.ex | 5 +- ui/lib/ex_nvr/pipelines/main.ex | 22 +---- ui/lib/ex_nvr/pipelines/snapshot.ex | 55 ------------- ui/lib/ex_nvr/recordings.ex | 14 +--- .../output/storage => utils}/media_utils.ex | 12 ++- ui/lib/ex_nvr/{ => utils}/utils.ex | 0 ui/mix.exs | 2 +- ui/mix.lock | 14 ++-- ui/test/ex_nvr/elements/cvs_bufferer_test.exs | 31 +++---- ui/test/ex_nvr/pipelines/snapshot_test.exs | 67 --------------- 18 files changed, 93 insertions(+), 304 deletions(-) delete mode 100644 ui/lib/ex_nvr/elements/snapshot_bin.ex delete mode 100644 ui/lib/ex_nvr/pipelines/snapshot.ex rename ui/lib/ex_nvr/{pipeline/output/storage => utils}/media_utils.ex (91%) rename ui/lib/ex_nvr/{ => utils}/utils.ex (100%) delete mode 100644 ui/test/ex_nvr/pipelines/snapshot_test.exs diff --git a/nerves_fw/mix.lock b/nerves_fw/mix.lock index 5a3d9e1d..ae4b6ffe 100644 --- a/nerves_fw/mix.lock +++ b/nerves_fw/mix.lock @@ -22,7 +22,7 @@ "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, "ecto": {:hex, :ecto, "3.12.5", "4a312960ce612e17337e7cefcf9be45b95a3be6b36b6f94dfb3d8c361d631866", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6eb18e80bef8bb57e17f5a7f068a1719fbda384d40fc37acb8eb8aeca493b6ea"}, "ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"}, - "ecto_sqlite3": {:hex, :ecto_sqlite3, "0.18.0", "dd25010d7b536bb00857f3bf47193f293619b0c30538bf912d4bd82861d25fba", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:exqlite, "~> 0.22", [hex: :exqlite, repo: "hexpm", optional: false]}], "hexpm", "e42ef8252e22c6f65e5421289f9e5ceffd1a4a7e01cb2818d5eab78205d3cce7"}, + "ecto_sqlite3": {:hex, :ecto_sqlite3, "0.18.1", "63c4b01cbb67f5e7eecde6819bc050fbb835141b534b779f80f40d479cdce669", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:exqlite, "~> 0.22", [hex: :exqlite, repo: "hexpm", optional: false]}], "hexpm", "ce223f0eda408437e7dc2b5f2a9dab306c7a709dc865f96172ba5eadfea3ce48"}, "ecto_sqlite3_extras": {:hex, :ecto_sqlite3_extras, "1.2.2", "36e60b561a11441d15f26c791817999269fb578b985162207ebb08b04ca71e40", [:mix], [{:exqlite, ">= 0.13.2", [hex: :exqlite, repo: "hexpm", optional: false]}, {:table_rex, "~> 4.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "2b66ba7246bb4f7e39e2578acd4a0e4e4be54f60ff52d450a01be95eeb78ff1e"}, "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, @@ -59,7 +59,7 @@ "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "logger_backends": {:hex, :logger_backends, "1.0.0", "09c4fad6202e08cb0fbd37f328282f16539aca380f512523ce9472b28edc6bdf", [:mix], [], "hexpm", "1faceb3e7ec3ef66a8f5746c5afd020e63996df6fd4eb8cdb789e5665ae6c9ce"}, - "logger_json": {:hex, :logger_json, "5.1.4", "9e30a4f2e31a8b9e402bdc20bd37cf9b67d3a31f19d0b33082a19a06b4c50f6d", [:mix], [{:ecto, "~> 2.1 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.5.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "3f20eea58e406a33d3eb7814c7dff5accb503bab2ee8601e84da02976fa3934c"}, + "logger_json": {:hex, :logger_json, "6.2.1", "a1db30e1164e6057f2328a1e4d6b632b9583c015574fdf6c38cf73721128edcb", [:mix], [{:decimal, ">= 0.0.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:ecto, "~> 3.11", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "34acd0bfd419d5fcf08c4108a8a4b59b695fcc60409dc1dd1a868b70c42e1d1f"}, "mdns_lite": {:hex, :mdns_lite, "0.8.11", "d1c77ec52512a63601ffc6a0423b2872836d18ec015aa647b14975b768d755d8", [:mix], [{:vintage_net, "~> 0.7", [hex: :vintage_net, repo: "hexpm", optional: true]}], "hexpm", "ec1c860cd016b4cf64b7b091fc28e04e2db0198dea1965990a55300f02c98a89"}, "membrane_aac_format": {:hex, :membrane_aac_format, "0.8.0", "515631eabd6e584e0e9af2cea80471fee6246484dbbefc4726c1d93ece8e0838", [:mix], [{:bimap, "~> 1.1", [hex: :bimap, repo: "hexpm", optional: false]}], "hexpm", "a30176a94491033ed32be45e51d509fc70a5ee6e751f12fd6c0d60bd637013f6"}, "membrane_aac_plugin": {:hex, :membrane_aac_plugin, "0.19.0", "58a15efaaa4f2cc91b968464cfd269244e035efdd983aac2e3ddeb176fcf0585", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_aac_format, "~> 0.8.0", [hex: :membrane_aac_format, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "eb7e786e650608ee205f4eebff4c1df3677e545acf09802458f77f64f9942fe9"}, @@ -68,7 +68,7 @@ "membrane_core": {:hex, :membrane_core, "1.1.2", "3ca206893e1d3739a24d5092d21c06fcb4db326733a1798f9788fc53abb74829", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 3.0 or ~> 4.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a989fd7e0516a7e66f5fb63950b1027315b7f8c8d82d8d685e178b0fb780901b"}, "membrane_ffmpeg_swscale_plugin": {:hex, :membrane_ffmpeg_swscale_plugin, "0.16.1", "df82dda3c52c4260d7a3613753d1d2d23248713dfef80b8b9647dd0e601e3606", [:mix], [{:bundlex, "~> 1.2", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.1", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}], "hexpm", "d75ee0e663e8446d84f26edca44b923d898317b2d68a2f5b4841ae56ec8d0f11"}, "membrane_file_plugin": {:hex, :membrane_file_plugin, "0.17.2", "650e134c2345d946f930082fac8bac9f5aba785a7817d38a9a9da41ffc56fa92", [:mix], [{:logger_backends, "~> 1.0", [hex: :logger_backends, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "df50c6040004cd7b901cf057bd7e99c875bbbd6ae574efc93b2c753c96f43b9d"}, - "membrane_funnel_plugin": {:hex, :membrane_funnel_plugin, "0.9.1", "9e108f4ef9d905ebff2da3ba5e58a5b756b58812f4fa68bd576add68fda310a0", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "39fdef1bf29eac949f65a37ea941f997c22ed042c55af044d27a781b63e82f6b"}, + "membrane_funnel_plugin": {:hex, :membrane_funnel_plugin, "0.9.2", "2b2e840dbb232ce29aaff2d55bd329d9978766518dbeb6e8dba7aba7115fadcc", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "865ac9d84f86698e2cfeb7904d3b12ab74855a38ca651a880db1505965fa77cc"}, "membrane_h264_ffmpeg_plugin": {:hex, :membrane_h264_ffmpeg_plugin, "0.32.3", "40e20024c4d2c8715a11327ac5390ebff048be2e4351022ee84093c669e42fe6", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "118f1461a6ef147e8333201edc5cb42a684d0b3b88347a338323dc3a9badde18"}, "membrane_h264_format": {:hex, :membrane_h264_format, "0.6.1", "44836cd9de0abe989b146df1e114507787efc0cf0da2368f17a10c47b4e0738c", [:mix], [], "hexpm", "4b79be56465a876d2eac2c3af99e115374bbdc03eb1dea4f696ee9a8033cd4b0"}, "membrane_h265_ffmpeg_plugin": {:hex, :membrane_h265_ffmpeg_plugin, "0.4.1", "79eef765dab750e59aefdd11b59cbe73d0bc01e47c72d6e50b1f7d800adfc6f0", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h265_format, "~> 0.2.0", [hex: :membrane_h265_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.1", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "7980e830963885ca76a31925393839271d368f7436a54bc1b7dcd26aeef96076"}, @@ -93,19 +93,19 @@ "modbux": {:hex, :modbux, "0.3.13", "a023e36c9678a83f0367ec585924a5df0456654a0bd91a6fee09e9b926901316", [:mix], [{:circuits_uart, "~> 1.3", [hex: :circuits_uart, repo: "hexpm", optional: false]}, {:ring_logger, "~> 0.4", [hex: :ring_logger, repo: "hexpm", optional: false]}], "hexpm", "7fa474bcc49d83a8a60b7241ad804607f30655dc0660d6bbc4a20220150c46e1"}, "multipart": {:hex, :multipart, "0.4.0", "634880a2148d4555d050963373d0e3bbb44a55b2badd87fa8623166172e9cda0", [:mix], [{:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm", "3c5604bc2fb17b3137e5d2abdf5dacc2647e60c5cc6634b102cf1aef75a06f0a"}, "muontrap": {:hex, :muontrap, "1.5.0", "bf5c273872379968615a39974458328209ac97fa1f588396192131ff973d1ca2", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "daf605e877f60b5be9215e3420d7971fc468677b29921e40915b15fd928273d4"}, - "nerves": {:hex, :nerves, "1.11.2", "a6733509c433f244aaf8a3aef28fcc3cc653fd5c5e3dc3f475b233730dbb1b2a", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "0b554421e7d1b82b03955fda3d966c83ab2414c5ed52f57ad7f4bcdc98279c57"}, + "nerves": {:hex, :nerves, "1.11.3", "437aa0a961ff8583e7f377342662495cdb90af42a473ae4d76449917bd12c386", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "ef2076e0c0cb2c95421d12fd9069942c0ad73f3c77c0d6bb2cfb18972dacf675"}, "nerves_hub_cli": {:hex, :nerves_hub_cli, "2.0.1", "782e9ac1a3c3802b47710b8096acfc46b0e4f4fca2495dc392be85cb1cdd247e", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.5", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 0.7 or ~> 1.1", [hex: :nimble_csv, repo: "hexpm", optional: false]}, {:pbcs, "0.1.2 or ~> 0.1.4", [hex: :pbcs, repo: "hexpm", optional: false]}, {:table_rex, "~> 2.0.0 or ~> 3.0 or ~> 4.0", [hex: :table_rex, repo: "hexpm", optional: false]}, {:tesla, "~> 1.2.1 or ~> 1.3", [hex: :tesla, repo: "hexpm", optional: false]}, {:x509, "~> 0.3", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "127b033d840f21e09cb62e3e9880f5f768334c52525c4808c6791ebd41d2232d"}, "nerves_hub_link": {:hex, :nerves_hub_link, "2.6.0", "6524fe8e525436a6d7cd872028bacccca80c641baeea04e035cf9d3372476b3d", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:extty, "~> 0.4.1", [hex: :extty, repo: "hexpm", optional: false]}, {:fwup, "~> 1.0", [hex: :fwup, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.2", [hex: :mint, repo: "hexpm", optional: false]}, {:nerves_key, "~> 0.5 or ~> 1.0", [hex: :nerves_key, repo: "hexpm", optional: true]}, {:nerves_runtime, "~> 0.8", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:nerves_time, "~> 0.4", [hex: :nerves_time, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:slipstream, "~> 0.8 or ~> 1.0", [hex: :slipstream, repo: "hexpm", optional: false]}, {:vintage_net, "~> 0.13", [hex: :vintage_net, repo: "hexpm", optional: true]}, {:whenwhere, "~> 0.1.1", [hex: :whenwhere, repo: "hexpm", optional: false]}, {:x509, "~> 0.5", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "ee91a4622693e5256305d8c5dd50746d19860bff8325b147f5b4e79ff1263958"}, "nerves_logging": {:hex, :nerves_logging, "0.2.2", "d0e878ac92e6907757fa9898b661250fa1cf50474763ca59ecfadca1c2235337", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "74c181c6f011ea0c2d52956ad82065a59d7c7b62ddfba5967b010ef125f460a5"}, "nerves_motd": {:hex, :nerves_motd, "0.1.15", "12a5ec9fdc19c2289f0df4afa1e0934a9408ac3f3b738ee94cf9b29cabacefe8", [:mix], [{:nerves_runtime, "~> 0.8", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:nerves_time, "~> 0.4", [hex: :nerves_time, repo: "hexpm", optional: true]}, {:nerves_time_zones, "~> 0.1", [hex: :nerves_time_zones, repo: "hexpm", optional: true]}], "hexpm", "280a5fc439889e61ac6b9b2c2f60503dc741e993ca6d4330585b55aab62c2e4a"}, "nerves_pack": {:hex, :nerves_pack, "0.7.1", "f069a9c3cfcde445498aad618af95c846f2ee032a69c2d715a9e5d4f632fb1b5", [:mix], [{:mdns_lite, "> 0.0.0", [hex: :mdns_lite, repo: "hexpm", optional: false]}, {:nerves_motd, "> 0.0.0", [hex: :nerves_motd, repo: "hexpm", optional: false]}, {:nerves_runtime, "> 0.0.0", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:nerves_ssh, "> 0.0.0", [hex: :nerves_ssh, repo: "hexpm", optional: false]}, {:nerves_time, "> 0.0.0", [hex: :nerves_time, repo: "hexpm", optional: false]}, {:ring_logger, "> 0.0.0", [hex: :ring_logger, repo: "hexpm", optional: false]}, {:vintage_net, "> 0.0.0", [hex: :vintage_net, repo: "hexpm", optional: false]}, {:vintage_net_direct, "> 0.0.0", [hex: :vintage_net_direct, repo: "hexpm", optional: false]}, {:vintage_net_ethernet, "> 0.0.0", [hex: :vintage_net_ethernet, repo: "hexpm", optional: false]}, {:vintage_net_wifi, "> 0.0.0", [hex: :vintage_net_wifi, repo: "hexpm", optional: false]}], "hexpm", "6b94d38771e3a97c3ed63e62fb5f78b47461208ee162e20bfbcf6e36fd900616"}, "nerves_runtime": {:hex, :nerves_runtime, "0.13.7", "0a7b15d5f55af1b695f7a4a1bd597c2f6101f8cbe7fe7a30743e3e441b7e233f", [:mix], [{:nerves_logging, "~> 0.2.0", [hex: :nerves_logging, repo: "hexpm", optional: false]}, {:nerves_uevent, "~> 0.1.0", [hex: :nerves_uevent, repo: "hexpm", optional: false]}, {:uboot_env, "~> 0.3.0 or ~> 1.0", [hex: :uboot_env, repo: "hexpm", optional: false]}], "hexpm", "6bafb89344709e5405cc7f9b140f91ca76ea3749f0eb3af80d8f8b8c53388b2d"}, - "nerves_ssh": {:hex, :nerves_ssh, "1.0.0", "a3683859674224a00aac5ae2a416185ca0129f5c5c6d09ab70a6d98bec79d3d8", [:mix], [{:nerves_runtime, "~> 0.11", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:ssh_subsystem_fwup, "~> 0.5", [hex: :ssh_subsystem_fwup, repo: "hexpm", optional: false]}], "hexpm", "2f3bbbb7752bc19aaca19ec9433dd029da728a67f9f497508581602e4cba68f4"}, + "nerves_ssh": {:hex, :nerves_ssh, "1.0.1", "81ccecd4ad8375315ab884f90448eb4067d3dbccd4e705afd50d496453d6d36b", [:mix], [{:nerves_runtime, "~> 0.11", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:ssh_subsystem_fwup, "~> 0.5", [hex: :ssh_subsystem_fwup, repo: "hexpm", optional: false]}], "hexpm", "4298c6e056c4b924fd49655e9bf2f16f04e35ea0ec6e9882d946f4cf581811bd"}, "nerves_system_br": {:hex, :nerves_system_br, "1.28.3", "979ac2d9ca66e45cb14ffb440a65e691892569070bb2104a9db65cb7a847b9f7", [:mix], [], "hexpm", "4bb6df0823696762c4e81c944fe3e08f46136e982b6bd34258a936b43b389a90"}, "nerves_time": {:hex, :nerves_time, "0.4.8", "50523376d487dfaea9bde973b9160a2ce811ade3ba2533776ef5c2ff4d80c277", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:muontrap, "~> 0.5 or ~> 1.0", [hex: :muontrap, repo: "hexpm", optional: false]}], "hexpm", "84479a25b725c24d1b758eaef3450043868591c8102c0ca1d7cc051a6402dd03"}, "nerves_toolchain_aarch64_nerves_linux_gnu": {:hex, :nerves_toolchain_aarch64_nerves_linux_gnu, "13.2.0", "68fcd2c21c86cceb9545948fae052d72f88b7c7c10205b252dac88559e2a3369", [:mix], [{:nerves, "~> 1.4", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.10.0", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm", "f92212606919a062f975e7bd82ed8a1b95bd4864abb3444cd0d5d0e610e94cc5"}, "nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.10.0", "c6b35377a0b7a93633a8673a788f1580fe1fa06083374b0e4df36da65828d2ef", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}], "hexpm", "e4ae1a2b84de3502ecac195765819be0ce2834eb276553163a7c03133f1760f1"}, - "nerves_uevent": {:hex, :nerves_uevent, "0.1.0", "651111a46be9a238560cbf7946989fc500e5f33d7035fd9ea7194d07a281bc19", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:property_table, "~> 0.2.0", [hex: :property_table, repo: "hexpm", optional: false]}], "hexpm", "cb0b1993c3ed3cefadbcdb534e910af0661f95c3445796ce8a7c8be3519a4e5f"}, + "nerves_uevent": {:hex, :nerves_uevent, "0.1.1", "2cf5a612698722b2898d2d98dc157c30623b2158cde45a072ef2d489b221c653", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:property_table, "~> 0.2.0 or ~> 0.3.0", [hex: :property_table, repo: "hexpm", optional: false]}], "hexpm", "9a354034e1ccd199a7daa3ff94e8794b39a528219e940b2f4e7bf39d63367752"}, "nimble_csv": {:hex, :nimble_csv, "1.2.0", "4e26385d260c61eba9d4412c71cea34421f296d5353f914afe3f2e71cce97722", [:mix], [], "hexpm", "d0628117fcc2148178b034044c55359b26966c6eaa8e2ce15777be3bbc91b12a"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, @@ -116,20 +116,20 @@ "onvif": {:git, "https://github.com/hammeraj/onvif.git", "1c54a1141c029267677dc50186d0e38a6479287d", [ref: "1c54a11"]}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "pbcs": {:hex, :pbcs, "0.1.4", "84c64d6ec826a57821021c03b0db3598ee587ba64430badee77809c2f68a9f8c", [:mix], [], "hexpm", "1f96954e50077e9cfde3cce62da452f4e56906d019ef141c011a96f79137dec0"}, - "peep": {:hex, :peep, "3.4.0", "2de27e5f05225df72e4a8a7728dd9c9cc00a02c772c61251eb5d3fe7aa89fffb", [:mix], [{:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:plug, "~> 1.16", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "07af52763804eae8f99a92a0fa4728ab7464eb3840671382124f4c52b1fbfbe2"}, + "peep": {:hex, :peep, "3.4.1", "0e5263710fa0b42675bd0a11fdcdd3ee4f484e319105b6ad9a576c91a5d3cb55", [:mix], [{:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:plug, "~> 1.16", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "7a9b8c1f17b8b9475efb27b7048afa4d89ab84ef33a3d1df13696c85c12cd632"}, "phoenix": {:hex, :phoenix, "1.7.18", "5310c21443514be44ed93c422e15870aef254cf1b3619e4f91538e7529d2b2e4", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "1797fcc82108442a66f2c77a643a62980f342bfeb63d6c9a515ab8294870004e"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.3", "f686701b0499a07f2e3b122d84d52ff8a31f5def386e03706c916f6feddf69ef", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "909502956916a657a197f94cc1206d9a65247538de8a5e186f7537c895d95764"}, "phoenix_html": {:hex, :phoenix_html, "4.2.0", "83a4d351b66f472ebcce242e4ae48af1b781866f00ef0eb34c15030d4e2069ac", [:mix], [], "hexpm", "9713b3f238d07043583a94296cc4bbdceacd3b3a6c74667f4df13971e7866ec8"}, "phoenix_html_helpers": {:hex, :phoenix_html_helpers, "1.0.1", "7eed85c52eff80a179391036931791ee5d2f713d76a81d0d2c6ebafe1e11e5ec", [:mix], [{:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cffd2385d1fa4f78b04432df69ab8da63dc5cf63e07b713a4dcf36a3740e3090"}, "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.6", "7b1f0327f54c9eb69845fd09a77accf922f488c549a7e7b8618775eb603a62c7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "1681ab813ec26ca6915beb3414aa138f298e17721dc6a2bde9e6eb8a62360ff6"}, - "phoenix_live_view": {:hex, :phoenix_live_view, "1.0.1", "5389a30658176c0de816636ce276567478bffd063c082515a6e8368b8fc9a0db", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c0f517e6f290f10dbb94343ac22e0109437fb1fa6f0696e7c73967b789c1c285"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "1.0.2", "e7b1dd68c86326e2c45cc81da41e332cc8aa7228a7161e2c811dcd7f1dd14db1", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8a40265b0cd7d3a35f136dfa3cc048e3b198fc3718763411a78c323a44ebebee"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, "plug_cowboy": {:hex, :plug_cowboy, "2.7.2", "fdadb973799ae691bf9ecad99125b16625b1c6039999da5fe544d99218e662e4", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "245d8a11ee2306094840c000e8816f0cbed69a23fc0ac2bcf8d7835ae019bb2f"}, "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "prom_ex": {:hex, :prom_ex, "1.11.0", "1f6d67f2dead92224cb4f59beb3e4d319257c5728d9638b4a5e8ceb51a4f9c7e", [:mix], [{:absinthe, ">= 1.7.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:broadway, ">= 1.1.0", [hex: :broadway, repo: "hexpm", optional: true]}, {:ecto, ">= 3.11.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.18", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, ">= 2.10.0", [hex: :oban, repo: "hexpm", optional: true]}, {:octo_fetch, "~> 0.4", [hex: :octo_fetch, repo: "hexpm", optional: false]}, {:peep, "~> 3.0", [hex: :peep, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, ">= 0.20.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, ">= 1.16.0", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 2.6.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, ">= 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.2", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.1", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "76b074bc3730f0802978a7eb5c7091a65473eaaf07e99ec9e933138dcc327805"}, - "property_table": {:hex, :property_table, "0.2.6", "41fb5e94cabc360827213abcf0b2ae255a22f834f86828df63001fccbaf3d319", [:mix], [], "hexpm", "7545a31384eb9e98da91a54cfa4ad7cb8b38ba556d6b7051c3f7d9f9f4caf567"}, + "property_table": {:hex, :property_table, "0.3.0", "aa51e0eb5e9789edb45e1048223f7f30ffd4e4dd0e3bd4924d8fa22d7800f9f6", [:mix], [], "hexpm", "696289fe01a2d685eb460e5440e64736ec8a07d8e4748e2d573b12b590b931e3"}, "qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"}, "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "ratio": {:hex, :ratio, "4.0.1", "3044166f2fc6890aa53d3aef0c336f84b2bebb889dc57d5f95cc540daa1912f8", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "c60cbb3ccdff9ffa56e7d6d1654b5c70d9f90f4d753ab3a43a6bf40855b881ce"}, @@ -141,7 +141,7 @@ "slipstream": {:hex, :slipstream, "1.1.3", "26bfd2b91c75bde3eb4f13fdb25940272395a1b04bcbc48b017f63f40fd09b29", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint_web_socket, "~> 0.2 or ~> 1.0", [hex: :mint_web_socket, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.1 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b1e81cca0369834060077ff43a7e557200dc33a22300e39524a2f5edec9eb023"}, "ssh_subsystem_fwup": {:hex, :ssh_subsystem_fwup, "0.6.2", "f551804decfa81254eadb6a69e5f905bcf2cb97a2f3069918cb7e55de0210c30", [:mix], [], "hexpm", "7cb8c598b02d95a6aea8888004082de5a74ae977ddfb5b608b1b6b1aaceb2ff3"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, - "sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"}, + "sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"}, "swoosh": {:hex, :swoosh, "1.17.6", "27ff070f96246e35b7105ab1c52b2b689f523a3cb83ed9faadb2f33bd653ccba", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9798f3e72165f40c950f6762c06dab68afcdcf616138fc4a07965c09c250e1e2"}, "table_rex": {:hex, :table_rex, "4.0.0", "3c613a68ebdc6d4d1e731bc973c233500974ec3993c99fcdabb210407b90959b", [:mix], [], "hexpm", "c35c4d5612ca49ebb0344ea10387da4d2afe278387d4019e4d8111e815df8f55"}, "tailwind": {:hex, :tailwind, "0.2.4", "5706ec47182d4e7045901302bf3a333e80f3d1af65c442ba9a9eed152fb26c2e", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "c6e4a82b8727bab593700c998a4d98cf3d8025678bfde059aed71d0000c3e463"}, @@ -157,10 +157,10 @@ "uboot_env": {:hex, :uboot_env, "1.0.1", "b0e136cf1a561412ff7db23ed2b6df18d7c7ce2fc59941afd851006788a67f3d", [:mix], [], "hexpm", "b6d4fe7c24123be57ed946c48116d23173e37944bc945b8b76fccc437909c60b"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "unifex": {:hex, :unifex, "1.1.2", "ed3366515b6612a5a08d24a38658dea18a6c6001e79cf41e3a2edd07004d3c6d", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "c25b9d4d1a1c76716ecdf68d0873553fdab4105f418ef76f646a5cb47e0396ab"}, - "vintage_net": {:hex, :vintage_net, "0.13.5", "b02cbb44434eba68d8e991e7c9a75d491da73c3073ff4823843e66f451d6f088", [:make, :mix], [{:beam_notify, "~> 0.2.0 or ~> 1.0", [hex: :beam_notify, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:gen_state_machine, "~> 2.0.0 or ~> 2.1.0 or ~> 3.0.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:muontrap, "~> 0.5.1 or ~> 0.6.0 or ~> 1.0", [hex: :muontrap, repo: "hexpm", optional: false]}, {:property_table, "~> 0.2.0", [hex: :property_table, repo: "hexpm", optional: false]}], "hexpm", "67e04b8eaa40600bbea4902aba363792598b31cf144f6033d93d7662b60519ad"}, + "vintage_net": {:hex, :vintage_net, "0.13.6", "87b6426d4748dce32b530025236444932c4e18c5e68297f8a48c9a33a15891fa", [:make, :mix], [{:beam_notify, "~> 0.2.0 or ~> 1.0", [hex: :beam_notify, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:gen_state_machine, "~> 2.0.0 or ~> 2.1.0 or ~> 3.0.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:muontrap, "~> 0.5.1 or ~> 0.6.0 or ~> 1.0", [hex: :muontrap, repo: "hexpm", optional: false]}, {:property_table, "~> 0.2.0 or ~> 0.3.0", [hex: :property_table, repo: "hexpm", optional: false]}], "hexpm", "f8410507f47dab294431802c4d501c50871c45fed74d279d1a97e34e8b4fed4c"}, "vintage_net_direct": {:hex, :vintage_net_direct, "0.10.7", "940561c375f04d6734ac78100ae1d8ef790ffd7e966f70efb525230fa1bc5774", [:mix], [{:one_dhcpd, "~> 0.2.3 or ~> 1.0 or ~> 2.0", [hex: :one_dhcpd, repo: "hexpm", optional: false]}, {:vintage_net, "~> 0.9.1 or ~> 0.10.0 or ~> 0.11.0 or ~> 0.12.0 or ~> 0.13.0", [hex: :vintage_net, repo: "hexpm", optional: false]}], "hexpm", "c040e9c33220495c28ba4464c5924da00bd4949627c4cb9c99ba1ed96f7b9429"}, "vintage_net_ethernet": {:hex, :vintage_net_ethernet, "0.11.2", "ef67db5ace9ad5ca5bf229a507247f9eb45b847dc0ff694a6e8a156ed9c5915d", [:mix], [{:vintage_net, "~> 0.12.0 or ~> 0.13.0", [hex: :vintage_net, repo: "hexpm", optional: false]}], "hexpm", "6915f9e15e1aa15e52d1948f318ce5109181d1ad7aaa50016bad5dd8e22df9ea"}, - "vintage_net_wifi": {:hex, :vintage_net_wifi, "0.12.5", "a19a3f78070470ecc00fa1d3d32982c41f39c2c06edb6cd53a8c13905aed8623", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:vintage_net, "~> 0.12.0 or ~> 0.13.0", [hex: :vintage_net, repo: "hexpm", optional: false]}], "hexpm", "4b477b9cccf54145bd6f7bf1f023ece63fa11395229bae365861de062c60a2f0"}, + "vintage_net_wifi": {:hex, :vintage_net_wifi, "0.12.6", "bbf5fecf4032b12976c46f02fcc85748787075dc10e625c971e7e9ab46b0a1f3", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:vintage_net, "~> 0.12.0 or ~> 0.13.0", [hex: :vintage_net, repo: "hexpm", optional: false]}], "hexpm", "db0a4afa0456cb8af7d773f8198ec6566f78dcbb5b2eb1ba7fc2bec6a61aa689"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"}, "whenwhere": {:hex, :whenwhere, "0.1.1", "5551941805f003284586b5a679164af4f1d47c7106206840ee4eb9d40edb9009", [:mix], [], "hexpm", "4d908481d07f345f58afaa5c33c2c9093bf1c1d7e4bdbe532ff59f225b543cba"}, diff --git a/rtsp/mix.lock b/rtsp/mix.lock index 54f6150d..3fedace1 100644 --- a/rtsp/mix.lock +++ b/rtsp/mix.lock @@ -9,7 +9,7 @@ "ex_rtcp": {:hex, :ex_rtcp, "0.4.0", "f9e515462a9581798ff6413583a25174cfd2101c94a2ebee871cca7639886f0a", [:mix], [], "hexpm", "28956602cf210d692fcdaf3f60ca49681634e1deb28ace41246aee61ee22dc3b"}, "ex_rtp": {:hex, :ex_rtp, "0.4.0", "1f1b5c1440a904706011e3afbb41741f5da309ce251cb986690ce9fd82636658", [:mix], [], "hexpm", "0f72d80d5953a62057270040f0f1ee6f955c08eeae82ac659c038001d7d5a790"}, "ex_sdp": {:hex, :ex_sdp, "1.1.1", "1a7b049491e5ec02dad9251c53d960835dc5631321ae978ec331831f3e4f6d5f", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}], "hexpm", "1b13a72ac9c5c695b8824dbdffc671be8cbb4c0d1ccb4ff76a04a6826759f233"}, - "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, + "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"}, "ham": {:hex, :ham, "0.3.0", "7cd031b4a55fba219c11553e7b13ba73bd86eab4034518445eff1e038cb9a44d", [:mix], [], "hexpm", "7d6c6b73d7a6a83233876cc1b06a4d9b5de05562b228effda4532f9a49852bf6"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "membrane_core": {:hex, :membrane_core, "1.1.2", "3ca206893e1d3739a24d5092d21c06fcb4db326733a1798f9788fc53abb74829", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 3.0 or ~> 4.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a989fd7e0516a7e66f5fb63950b1027315b7f8c8d82d8d685e178b0fb780901b"}, diff --git a/ui/config/runtime.exs b/ui/config/runtime.exs index c2b317d1..f83dad1a 100644 --- a/ui/config/runtime.exs +++ b/ui/config/runtime.exs @@ -70,12 +70,9 @@ if config_env() == :prod do log_json? = System.get_env("EXNVR_JSON_LOGGER", "true") == "true" if log_json? do - config :logger_json, :backend, - metadata: :all, - formatter: LoggerJSON.Formatters.BasicLogger, - on_init: :disabled - - config :logger, level: :info, backends: [LoggerJSON] + config :logger, :default_handler, + level: :info, + formatter: {LoggerJSON.Formatters.Basic, []} end config :ex_nvr, diff --git a/ui/lib/ex_nvr/decoder.ex b/ui/lib/ex_nvr/decoder.ex index d4a3b7ad..c8981630 100644 --- a/ui/lib/ex_nvr/decoder.ex +++ b/ui/lib/ex_nvr/decoder.ex @@ -53,6 +53,9 @@ defmodule ExNVR.Decoder do end end + @type t :: %__MODULE__{mod: module(), state: any()} + defstruct [:mod, :state] + @spec new(atom()) :: {:ok, {module(), decoder()}} | error() def new(:h264) do case H264.init() do @@ -68,7 +71,16 @@ defmodule ExNVR.Decoder do end end - @spec new!(atom()) :: {module(), decoder()} - def new!(:h264), do: {H264, H264.init!()} - def new!(:h265), do: {H265, H265.init!()} + @spec new!(atom()) :: t() + def new!(:h264), do: %__MODULE__{mod: H264, state: H264.init!()} + def new!(:h265), do: %__MODULE__{mod: H265, state: H265.init!()} + + @spec decode(t(), Buffer.t()) :: {:ok, [Buffer.t()]} | error() + def decode(%__MODULE__{mod: mod, state: state}, buffer), do: mod.decode(state, buffer) + + @spec decode!(t(), Buffer.t()) :: [Buffer.t()] + def decode!(%__MODULE__{mod: mod, state: state}, buffer), do: mod.decode!(state, buffer) + + @spec flush!(t()) :: [Buffer.t()] + def flush!(%__MODULE__{mod: mod, state: state}), do: mod.flush!(state) end diff --git a/ui/lib/ex_nvr/elements/cvs_bufferer.ex b/ui/lib/ex_nvr/elements/cvs_bufferer.ex index 72eb663a..851af8cf 100644 --- a/ui/lib/ex_nvr/elements/cvs_bufferer.ex +++ b/ui/lib/ex_nvr/elements/cvs_bufferer.ex @@ -8,7 +8,7 @@ defmodule ExNVR.Elements.CVSBufferer do decode it to get the latest snapshot """ - use Membrane.Filter + use Membrane.Sink require ExNVR.Utils @@ -24,23 +24,26 @@ defmodule ExNVR.Elements.CVSBufferer do ), availability: :always - def_output_pad :output, - flow_control: :auto, - accepted_format: - any_of( - %H264{alignment: :au}, - %H265{alignment: :au} - ), - availability: :on_request - @impl true def handle_init(_ctx, _options) do - {[], %{cvs: [], stream_format: nil}} + {[], %{cvs: [], decoder: nil, width: 0, height: 0}} end @impl true def handle_stream_format(:input, stream_format, _ctx, state) do - {[], %{state | stream_format: stream_format}} + codec = + case stream_format do + %H264{} -> :h264 + %H265{} -> :h265 + end + + {[], + %{ + state + | decoder: ExNVR.Decoder.new!(codec), + width: stream_format.width, + height: stream_format.height + }} end @impl true @@ -54,12 +57,14 @@ defmodule ExNVR.Elements.CVSBufferer do end @impl true - def handle_pad_added(Pad.ref(:output, _ref) = pad, _ctx, state) do - actions = + def handle_parent_notification(:snapshot, _ctx, state) do + {:ok, snapshot} = state.cvs |> Enum.reverse() - |> Enum.map(&{:buffer, {pad, &1}}) + |> ExNVR.MediaUtils.decode_last(state.decoder) + |> Map.get(:payload) + |> Turbojpeg.yuv_to_jpeg(state.width, state.height, 75, :I420) - {[stream_format: {pad, state.stream_format}] ++ actions ++ [end_of_stream: pad], state} + {[notify_parent: {:snapshot, snapshot}], state} end end diff --git a/ui/lib/ex_nvr/elements/snapshot_bin.ex b/ui/lib/ex_nvr/elements/snapshot_bin.ex deleted file mode 100644 index 4f142390..00000000 --- a/ui/lib/ex_nvr/elements/snapshot_bin.ex +++ /dev/null @@ -1,81 +0,0 @@ -defmodule ExNVR.Elements.SnapshotBin do - @moduledoc """ - A bin element that receives an encoded video stream and create a snapshot in - JPEG format by using the first or last access unit. - - Once the snapshot is created a parent notification is sent: `{:notify_parent, {:snapshot, snapshot}}` - """ - - use Membrane.Bin - - alias Membrane.{H264, H265} - - def_input_pad :input, - accepted_format: - any_of( - %H264{alignment: :au}, - %H265{alignment: :au} - ), - availability: :on_request, - options: [ - format: [ - spec: :jpeg, - default: :jpeg - ], - rank: [ - spec: :first | :last, - default: :last, - description: """ - Create a snapshot from the first or last access unit - """ - ], - encoding: [ - spec: ExNVR.Pipelines.Main.encoding(), - description: "The video encoding" - ] - ] - - @impl true - def handle_init(_ctx, _options) do - {[], %{}} - end - - @impl true - def handle_pad_added(Pad.ref(:input, ref) = pad, ctx, state) do - decoder = - case ctx.pad_options[:encoding] do - :H264 -> %Membrane.H264.FFmpeg.Decoder{use_shm?: true} - :H265 -> %Membrane.H265.FFmpeg.Decoder{use_shm?: true} - end - - spec = [ - bin_input(pad) - |> child({:decoder, ref}, decoder) - |> child({:filter, ref}, %ExNVR.Elements.OnePass{allow: ctx.pad_options[:rank]}) - |> child({:jpeg, ref}, Turbojpeg.Filter) - |> child({:sink, ref}, %ExNVR.Elements.Process.Sink{pid: self()}) - ] - - {[spec: spec], state} - end - - @impl true - def handle_element_end_of_stream({:sink, ref}, _pad, ctx, state) do - Map.keys(ctx.children) - |> Enum.filter(fn - {_, ^ref} -> true - _ -> false - end) - |> then(&{[remove_children: &1], state}) - end - - @impl true - def handle_element_end_of_stream(_element, _pad, _ctx, state) do - {[], state} - end - - @impl true - def handle_info({:buffer, snapshot}, _ctx, state) do - {[notify_parent: {:snapshot, snapshot}], state} - end -end diff --git a/ui/lib/ex_nvr/pipeline/output/socket.ex b/ui/lib/ex_nvr/pipeline/output/socket.ex index d0c60482..761f3723 100644 --- a/ui/lib/ex_nvr/pipeline/output/socket.ex +++ b/ui/lib/ex_nvr/pipeline/output/socket.ex @@ -29,7 +29,7 @@ defmodule ExNVR.Pipeline.Output.Socket do alias Membrane.{H264, H265} def_options encoding: [ - spec: ExNVR.Pipelines.encoding(), + spec: ExNVR.Pipelines.Main.encoding(), description: "The video encoding" ] diff --git a/ui/lib/ex_nvr/pipeline/output/storage.ex b/ui/lib/ex_nvr/pipeline/output/storage.ex index 32054a74..65274a50 100644 --- a/ui/lib/ex_nvr/pipeline/output/storage.ex +++ b/ui/lib/ex_nvr/pipeline/output/storage.ex @@ -6,7 +6,7 @@ defmodule ExNVR.Pipeline.Output.Storage do require ExNVR.Utils require Membrane.Logger - import __MODULE__.MediaUtils + import ExNVR.MediaUtils alias ExMP4.Writer alias ExNVR.Model.Device diff --git a/ui/lib/ex_nvr/pipeline/output/thumbnailer.ex b/ui/lib/ex_nvr/pipeline/output/thumbnailer.ex index 7639d21e..5301ae03 100644 --- a/ui/lib/ex_nvr/pipeline/output/thumbnailer.ex +++ b/ui/lib/ex_nvr/pipeline/output/thumbnailer.ex @@ -59,7 +59,7 @@ defmodule ExNVR.Pipeline.Output.Thumbnailer do out_height = div(state.thumbnail_width * format.height, format.width) out_height = out_height - rem(out_height, 2) - {decoder, decoder_state} = Decoder.new!(codec) + decoder = Decoder.new!(codec) scaler = Image.Scaler.new!(format.width, format.height, state.thumbnail_width, out_height) {[], @@ -67,7 +67,6 @@ defmodule ExNVR.Pipeline.Output.Thumbnailer do state | thumbnail_height: out_height, decoder: decoder, - decoder_state: decoder_state, scaler: scaler }} end @@ -99,7 +98,7 @@ defmodule ExNVR.Pipeline.Output.Thumbnailer do end defp decode(state, buffer) do - with {:ok, []} <- state.decoder.decode(state.decoder_state, buffer) do + with {:ok, []} <- Decoder.decode(state.decoder, buffer) do state.decoder.flush(state.decoder_state) end end diff --git a/ui/lib/ex_nvr/pipelines/main.ex b/ui/lib/ex_nvr/pipelines/main.ex index 1b4b9257..12090965 100644 --- a/ui/lib/ex_nvr/pipelines/main.ex +++ b/ui/lib/ex_nvr/pipelines/main.ex @@ -126,8 +126,7 @@ defmodule ExNVR.Pipelines.Main do child(:hls_sink, %Output.HLS{ location: Path.join(Utils.hls_dir(device.id), "live"), segment_name_prefix: "live" - }), - child(:snapshooter, ExNVR.Elements.SnapshotBin) + }) ] ++ build_device_spec(device) # Set device state and make last active run inactive @@ -252,10 +251,10 @@ defmodule ExNVR.Pipelines.Main do end @impl true - def handle_call({:live_snapshot, image_format}, ctx, state) do + def handle_call({:live_snapshot, _image_format}, ctx, state) do case state.live_snapshot_waiting_pids do [] -> - {[spec: link_live_snapshot_elements(state, image_format)], + {[notify_child: {{:snapshooter, :main_stream}, :snapshot}], %{state | live_snapshot_waiting_pids: [ctx.from]}} pids -> @@ -338,7 +337,7 @@ defmodule ExNVR.Pipelines.Main do |> get_child(:hls_sink), get_child(:tee) |> via_out(:video_output) - |> child({:cvs_bufferer, :main_stream}, ExNVR.Elements.CVSBufferer), + |> child({:snapshooter, :main_stream}, ExNVR.Elements.CVSBufferer), get_child(:tee) |> via_out(:video_output) |> child({:stats_reporter, :main_stream}, %VideoStreamStatReporter{ @@ -410,19 +409,6 @@ defmodule ExNVR.Pipelines.Main do end end - defp link_live_snapshot_elements(state, image_format) do - ref = make_ref() - - [ - get_child({:cvs_bufferer, :main_stream}) - |> via_out(Pad.ref(:output, ref)) - |> via_in(Pad.ref(:input, ref), - options: [format: image_format, encoding: state.main_stream_video_track.encoding] - ) - |> get_child(:snapshooter) - ] - end - defp maybe_update_device_and_report(%{device: %{state: device_state}} = state, device_state), do: state diff --git a/ui/lib/ex_nvr/pipelines/snapshot.ex b/ui/lib/ex_nvr/pipelines/snapshot.ex deleted file mode 100644 index b359f125..00000000 --- a/ui/lib/ex_nvr/pipelines/snapshot.ex +++ /dev/null @@ -1,55 +0,0 @@ -defmodule ExNVR.Pipelines.Snapshot do - @moduledoc """ - Pipeline responsible for retrieving a snapshot from an MP4 file - """ - - use Membrane.Pipeline - - require Membrane.Logger - - alias ExNVR.Elements - alias ExNVR.Elements.Recording - - def start(options) do - Pipeline.start(__MODULE__, Keyword.put(options, :caller, self())) - end - - @impl true - def handle_init(_ctx, options) do - Logger.metadata(device_id: options[:device].id) - Membrane.Logger.info("Start snapshot pipeline with options: #{inspect(options)}") - - rank = if options[:method] == :precise, do: :last, else: :first - - spec = [ - child(:source, %Recording{ - device: options[:device], - start_date: options[:date], - end_date: options[:date] - }) - ] - - {[spec: spec], %{caller: options[:caller], rank: rank, format: options[:format] || :jpeg}} - end - - @impl true - def handle_child_notification({:new_track, track_id, track}, :source, _ctx, state) do - spec = [ - get_child(:source) - |> via_out(Pad.ref(:video, track_id)) - |> via_in(Pad.ref(:input, make_ref()), - options: [format: state.format, rank: state.rank, encoding: track.encoding] - ) - |> child(:sink, Elements.SnapshotBin) - ] - - {[spec: spec], state} - end - - @impl true - def handle_child_notification({:snapshot, snapshot}, :sink, _ctx, state) do - Membrane.Logger.info("Got snapshot") - send(state.caller, {:snapshot, snapshot}) - {[terminate: :shutdown], %{state | caller: nil}} - end -end diff --git a/ui/lib/ex_nvr/recordings.ex b/ui/lib/ex_nvr/recordings.ex index fd94315f..74c26837 100644 --- a/ui/lib/ex_nvr/recordings.ex +++ b/ui/lib/ex_nvr/recordings.ex @@ -109,19 +109,13 @@ defmodule ExNVR.Recordings do method = Keyword.get(opts, :method, :before) with {:ok, reader} <- ExMP4.Reader.new(path) do - track = ExMP4.Reader.tracks(reader) |> Enum.find(&(&1.type == :video)) + track = ExMP4.Reader.track(reader, :video) offset = ExMP4.Helper.timescalify(offset, :microsecond, track.timescale) - samples = read_samples(reader, track, offset, method) - {decoder, decoder_state} = ExNVR.Decoder.new!(track.media) - - samples + reader + |> read_samples(track, offset, method) |> Stream.map(&%Membrane.Buffer{payload: &1.payload, dts: &1.dts, pts: &1.pts}) - |> Stream.map(&decoder.decode!(decoder_state, &1)) - |> Enum.to_list() - |> Kernel.++(decoder.flush!(decoder_state)) - |> List.flatten() - |> List.last() + |> ExNVR.MediaUtils.decode_last(ExNVR.Decoder.new!(track.media)) |> then(fn buffer -> datetime = DateTime.add( diff --git a/ui/lib/ex_nvr/pipeline/output/storage/media_utils.ex b/ui/lib/ex_nvr/utils/media_utils.ex similarity index 91% rename from ui/lib/ex_nvr/pipeline/output/storage/media_utils.ex rename to ui/lib/ex_nvr/utils/media_utils.ex index ff50ef1f..5e796e1d 100644 --- a/ui/lib/ex_nvr/pipeline/output/storage/media_utils.ex +++ b/ui/lib/ex_nvr/utils/media_utils.ex @@ -1,4 +1,4 @@ -defmodule ExNVR.Pipeline.Output.Storage.MediaUtils do +defmodule ExNVR.MediaUtils do @moduledoc false alias Membrane.Buffer @@ -40,6 +40,16 @@ defmodule ExNVR.Pipeline.Output.Storage.MediaUtils do |> Enum.join() end + @spec decode_last(Enumerable.t(Buffer.t()), ExNVR.Decoder.t()) :: Buffer.t() + def decode_last(buffers, decoder) do + buffers + |> Stream.map(&ExNVR.Decoder.decode!(decoder, &1)) + |> Enum.to_list() + |> Kernel.++(ExNVR.Decoder.flush!(decoder)) + |> List.flatten() + |> List.last() + end + defp pss?(:h264, <<_prefix::3, type::5, _rest::binary>>) when type == 7 or type == 8, do: true defp pss?(:h265, <<0::1, type::6, _rest::bitstring>>) when type in 32..34, do: true defp pss?(_codec, _nalu), do: false diff --git a/ui/lib/ex_nvr/utils.ex b/ui/lib/ex_nvr/utils/utils.ex similarity index 100% rename from ui/lib/ex_nvr/utils.ex rename to ui/lib/ex_nvr/utils/utils.ex diff --git a/ui/mix.exs b/ui/mix.exs index 524b5245..ac367019 100644 --- a/ui/mix.exs +++ b/ui/mix.exs @@ -83,7 +83,7 @@ defmodule ExNVR.MixProject do {:jason, "~> 1.2"}, {:plug_cowboy, "~> 2.5"}, {:corsica, "~> 2.1"}, - {:logger_json, "~> 5.1"}, + {:logger_json, "~> 6.1"}, {:flop_phoenix, "~> 0.23.0"}, {:prom_ex, "~> 1.11.0"}, {:reverse_proxy_plug, "~> 3.0"}, diff --git a/ui/mix.lock b/ui/mix.lock index b29bec89..90b0a92e 100644 --- a/ui/mix.lock +++ b/ui/mix.lock @@ -23,7 +23,7 @@ "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, "ecto": {:hex, :ecto, "3.12.5", "4a312960ce612e17337e7cefcf9be45b95a3be6b36b6f94dfb3d8c361d631866", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6eb18e80bef8bb57e17f5a7f068a1719fbda384d40fc37acb8eb8aeca493b6ea"}, "ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"}, - "ecto_sqlite3": {:hex, :ecto_sqlite3, "0.18.0", "dd25010d7b536bb00857f3bf47193f293619b0c30538bf912d4bd82861d25fba", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:exqlite, "~> 0.22", [hex: :exqlite, repo: "hexpm", optional: false]}], "hexpm", "e42ef8252e22c6f65e5421289f9e5ceffd1a4a7e01cb2818d5eab78205d3cce7"}, + "ecto_sqlite3": {:hex, :ecto_sqlite3, "0.18.1", "63c4b01cbb67f5e7eecde6819bc050fbb835141b534b779f80f40d479cdce669", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:exqlite, "~> 0.22", [hex: :exqlite, repo: "hexpm", optional: false]}], "hexpm", "ce223f0eda408437e7dc2b5f2a9dab306c7a709dc865f96172ba5eadfea3ce48"}, "ecto_sqlite3_extras": {:hex, :ecto_sqlite3_extras, "1.2.2", "36e60b561a11441d15f26c791817999269fb578b985162207ebb08b04ca71e40", [:mix], [{:exqlite, ">= 0.13.2", [hex: :exqlite, repo: "hexpm", optional: false]}, {:table_rex, "~> 4.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "2b66ba7246bb4f7e39e2578acd4a0e4e4be54f60ff52d450a01be95eeb78ff1e"}, "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, @@ -44,7 +44,7 @@ "expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"}, "exqlite": {:hex, :exqlite, "0.27.1", "73fc0b3dc3b058a77a2b3771f82a6af2ddcf370b069906968a34083d2ffd2884", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "79ef5756451cfb022e8013e1ed00d0f8f7d1333c19502c394dc16b15cfb4e9b4"}, "faker": {:hex, :faker, "0.18.0", "943e479319a22ea4e8e39e8e076b81c02827d9302f3d32726c5bf82f430e6e14", [:mix], [], "hexpm", "bfbdd83958d78e2788e99ec9317c4816e651ad05e24cfd1196ce5db5b3e81797"}, - "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, + "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"}, "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, "floki": {:hex, :floki, "0.37.0", "b83e0280bbc6372f2a403b2848013650b16640cd2470aea6701f0632223d719e", [:mix], [], "hexpm", "516a0c15a69f78c47dc8e0b9b3724b29608aa6619379f91b1ffa47109b5d0dd3"}, "flop": {:hex, :flop, "0.26.1", "f0e9c6895cf876f667e9ff1c0398e53df87087fcd82d9cea8989332b9c0e1358", [:mix], [{:ecto, "~> 3.11", [hex: :ecto, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}], "hexpm", "5fcab8a1ee78111159fc4752dc9823862343b6d6bd527ff947ec1e1c27018485"}, @@ -58,7 +58,7 @@ "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "logger_backends": {:hex, :logger_backends, "1.0.0", "09c4fad6202e08cb0fbd37f328282f16539aca380f512523ce9472b28edc6bdf", [:mix], [], "hexpm", "1faceb3e7ec3ef66a8f5746c5afd020e63996df6fd4eb8cdb789e5665ae6c9ce"}, - "logger_json": {:hex, :logger_json, "5.1.4", "9e30a4f2e31a8b9e402bdc20bd37cf9b67d3a31f19d0b33082a19a06b4c50f6d", [:mix], [{:ecto, "~> 2.1 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.5.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "3f20eea58e406a33d3eb7814c7dff5accb503bab2ee8601e84da02976fa3934c"}, + "logger_json": {:hex, :logger_json, "6.2.1", "a1db30e1164e6057f2328a1e4d6b632b9583c015574fdf6c38cf73721128edcb", [:mix], [{:decimal, ">= 0.0.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:ecto, "~> 3.11", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "34acd0bfd419d5fcf08c4108a8a4b59b695fcc60409dc1dd1a868b70c42e1d1f"}, "membrane_aac_format": {:hex, :membrane_aac_format, "0.8.0", "515631eabd6e584e0e9af2cea80471fee6246484dbbefc4726c1d93ece8e0838", [:mix], [{:bimap, "~> 1.1", [hex: :bimap, repo: "hexpm", optional: false]}], "hexpm", "a30176a94491033ed32be45e51d509fc70a5ee6e751f12fd6c0d60bd637013f6"}, "membrane_aac_plugin": {:hex, :membrane_aac_plugin, "0.19.0", "58a15efaaa4f2cc91b968464cfd269244e035efdd983aac2e3ddeb176fcf0585", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_aac_format, "~> 0.8.0", [hex: :membrane_aac_format, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "eb7e786e650608ee205f4eebff4c1df3677e545acf09802458f77f64f9942fe9"}, "membrane_cmaf_format": {:hex, :membrane_cmaf_format, "0.7.1", "9ea858faefdcb181cdfa8001be827c35c5f854e9809ad57d7062cff1f0f703fd", [:mix], [], "hexpm", "3c7b4ed2a986e27f6f336d2f19e9442cb31d93b3142fc024c019572faca54a73"}, @@ -66,7 +66,7 @@ "membrane_core": {:hex, :membrane_core, "1.1.2", "3ca206893e1d3739a24d5092d21c06fcb4db326733a1798f9788fc53abb74829", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 3.0 or ~> 4.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a989fd7e0516a7e66f5fb63950b1027315b7f8c8d82d8d685e178b0fb780901b"}, "membrane_ffmpeg_swscale_plugin": {:hex, :membrane_ffmpeg_swscale_plugin, "0.16.1", "df82dda3c52c4260d7a3613753d1d2d23248713dfef80b8b9647dd0e601e3606", [:mix], [{:bundlex, "~> 1.2", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.1", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}], "hexpm", "d75ee0e663e8446d84f26edca44b923d898317b2d68a2f5b4841ae56ec8d0f11"}, "membrane_file_plugin": {:hex, :membrane_file_plugin, "0.17.2", "650e134c2345d946f930082fac8bac9f5aba785a7817d38a9a9da41ffc56fa92", [:mix], [{:logger_backends, "~> 1.0", [hex: :logger_backends, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "df50c6040004cd7b901cf057bd7e99c875bbbd6ae574efc93b2c753c96f43b9d"}, - "membrane_funnel_plugin": {:hex, :membrane_funnel_plugin, "0.9.1", "9e108f4ef9d905ebff2da3ba5e58a5b756b58812f4fa68bd576add68fda310a0", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "39fdef1bf29eac949f65a37ea941f997c22ed042c55af044d27a781b63e82f6b"}, + "membrane_funnel_plugin": {:hex, :membrane_funnel_plugin, "0.9.2", "2b2e840dbb232ce29aaff2d55bd329d9978766518dbeb6e8dba7aba7115fadcc", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "865ac9d84f86698e2cfeb7904d3b12ab74855a38ca651a880db1505965fa77cc"}, "membrane_h264_ffmpeg_plugin": {:hex, :membrane_h264_ffmpeg_plugin, "0.32.3", "40e20024c4d2c8715a11327ac5390ebff048be2e4351022ee84093c669e42fe6", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "118f1461a6ef147e8333201edc5cb42a684d0b3b88347a338323dc3a9badde18"}, "membrane_h264_format": {:hex, :membrane_h264_format, "0.6.1", "44836cd9de0abe989b146df1e114507787efc0cf0da2368f17a10c47b4e0738c", [:mix], [], "hexpm", "4b79be56465a876d2eac2c3af99e115374bbdc03eb1dea4f696ee9a8033cd4b0"}, "membrane_h265_ffmpeg_plugin": {:hex, :membrane_h265_ffmpeg_plugin, "0.4.1", "79eef765dab750e59aefdd11b59cbe73d0bc01e47c72d6e50b1f7d800adfc6f0", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h265_format, "~> 0.2.0", [hex: :membrane_h265_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.1", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "7980e830963885ca76a31925393839271d368f7436a54bc1b7dcd26aeef96076"}, @@ -96,14 +96,14 @@ "octo_fetch": {:hex, :octo_fetch, "0.4.0", "074b5ecbc08be10b05b27e9db08bc20a3060142769436242702931c418695b19", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "cf8be6f40cd519d7000bb4e84adcf661c32e59369ca2827c4e20042eda7a7fc6"}, "onvif": {:git, "https://github.com/hammeraj/onvif.git", "1c54a1141c029267677dc50186d0e38a6479287d", [ref: "1c54a11"]}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, - "peep": {:hex, :peep, "3.4.0", "2de27e5f05225df72e4a8a7728dd9c9cc00a02c772c61251eb5d3fe7aa89fffb", [:mix], [{:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:plug, "~> 1.16", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "07af52763804eae8f99a92a0fa4728ab7464eb3840671382124f4c52b1fbfbe2"}, + "peep": {:hex, :peep, "3.4.1", "0e5263710fa0b42675bd0a11fdcdd3ee4f484e319105b6ad9a576c91a5d3cb55", [:mix], [{:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:plug, "~> 1.16", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "7a9b8c1f17b8b9475efb27b7048afa4d89ab84ef33a3d1df13696c85c12cd632"}, "phoenix": {:hex, :phoenix, "1.7.18", "5310c21443514be44ed93c422e15870aef254cf1b3619e4f91538e7529d2b2e4", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "1797fcc82108442a66f2c77a643a62980f342bfeb63d6c9a515ab8294870004e"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.3", "f686701b0499a07f2e3b122d84d52ff8a31f5def386e03706c916f6feddf69ef", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "909502956916a657a197f94cc1206d9a65247538de8a5e186f7537c895d95764"}, "phoenix_html": {:hex, :phoenix_html, "4.2.0", "83a4d351b66f472ebcce242e4ae48af1b781866f00ef0eb34c15030d4e2069ac", [:mix], [], "hexpm", "9713b3f238d07043583a94296cc4bbdceacd3b3a6c74667f4df13971e7866ec8"}, "phoenix_html_helpers": {:hex, :phoenix_html_helpers, "1.0.1", "7eed85c52eff80a179391036931791ee5d2f713d76a81d0d2c6ebafe1e11e5ec", [:mix], [{:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cffd2385d1fa4f78b04432df69ab8da63dc5cf63e07b713a4dcf36a3740e3090"}, "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.6", "7b1f0327f54c9eb69845fd09a77accf922f488c549a7e7b8618775eb603a62c7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "1681ab813ec26ca6915beb3414aa138f298e17721dc6a2bde9e6eb8a62360ff6"}, "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.5.3", "f2161c207fda0e4fb55165f650f7f8db23f02b29e3bff00ff7ef161d6ac1f09d", [:mix], [{:file_system, "~> 0.3 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b4ec9cd73cb01ff1bd1cac92e045d13e7030330b74164297d1aee3907b54803c"}, - "phoenix_live_view": {:hex, :phoenix_live_view, "1.0.1", "5389a30658176c0de816636ce276567478bffd063c082515a6e8368b8fc9a0db", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c0f517e6f290f10dbb94343ac22e0109437fb1fa6f0696e7c73967b789c1c285"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "1.0.2", "e7b1dd68c86326e2c45cc81da41e332cc8aa7228a7161e2c811dcd7f1dd14db1", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8a40265b0cd7d3a35f136dfa3cc048e3b198fc3718763411a78c323a44ebebee"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, @@ -117,7 +117,7 @@ "reverse_proxy_plug": {:hex, :reverse_proxy_plug, "3.0.2", "38fde2f59bca8b219ef4f1ec0c0849a67c6d9705160e426a2354f35399db5c7b", [:mix], [{:finch, "~> 0.18", [hex: :finch, repo: "hexpm", optional: true]}, {:httpoison, "~> 1.2 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: false]}, {:req, "~> 0.3.0 or ~> 0.4.0 or ~> 0.5.0", [hex: :req, repo: "hexpm", optional: true]}, {:tesla, "~> 1.4", [hex: :tesla, repo: "hexpm", optional: true]}], "hexpm", "31ae5e068f7f504fba1b5c17c31c87966c720809ac15140c6c181440fbd24eda"}, "shmex": {:hex, :shmex, "0.5.1", "81dd209093416bf6608e66882cb7e676089307448a1afd4fc906c1f7e5b94cf4", [:mix], [{:bunch_native, "~> 0.5.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "c29f8286891252f64c4e1dac40b217d960f7d58def597c4e606ff8fbe71ceb80"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, - "sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"}, + "sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"}, "swoosh": {:hex, :swoosh, "1.17.6", "27ff070f96246e35b7105ab1c52b2b689f523a3cb83ed9faadb2f33bd653ccba", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9798f3e72165f40c950f6762c06dab68afcdcf616138fc4a07965c09c250e1e2"}, "table_rex": {:hex, :table_rex, "4.0.0", "3c613a68ebdc6d4d1e731bc973c233500974ec3993c99fcdabb210407b90959b", [:mix], [], "hexpm", "c35c4d5612ca49ebb0344ea10387da4d2afe278387d4019e4d8111e815df8f55"}, "tailwind": {:hex, :tailwind, "0.2.4", "5706ec47182d4e7045901302bf3a333e80f3d1af65c442ba9a9eed152fb26c2e", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "c6e4a82b8727bab593700c998a4d98cf3d8025678bfde059aed71d0000c3e463"}, diff --git a/ui/test/ex_nvr/elements/cvs_bufferer_test.exs b/ui/test/ex_nvr/elements/cvs_bufferer_test.exs index 17c79bd8..9bbbae21 100644 --- a/ui/test/ex_nvr/elements/cvs_bufferer_test.exs +++ b/ui/test/ex_nvr/elements/cvs_bufferer_test.exs @@ -3,10 +3,7 @@ defmodule ExNVR.Elements.CVSBuffererTest do use ExUnit.Case - require Membrane.Pad - alias ExNVR.Elements.CVSBufferer - alias Membrane.Pad @ctx %{} @stream_format %Membrane.H264{width: 1080, height: 720} @@ -14,30 +11,22 @@ defmodule ExNVR.Elements.CVSBuffererTest do test "Buffer CVS (coded video sequence)" do assert {[], state} = CVSBufferer.handle_init(@ctx, nil) - assert {[], %{stream_format: @stream_format} = state} = + assert {[], %{decoder: decoder, width: 1080, height: 720} = state} = CVSBufferer.handle_stream_format(:input, @stream_format, @ctx, state) - {state, buffers} = - Enum.reduce(1..10, {state, []}, fn idx, {state, buffers} -> - key_frame? = rem(idx, 4) == 0 - buffer = generate_buffer(key_frame?) - - buffers = if key_frame?, do: [buffer], else: [buffer | buffers] - - assert {[], %{cvs: ^buffers} = state} = - CVSBufferer.handle_buffer(:input, buffer, @ctx, state) + assert is_struct(decoder, ExNVR.Decoder) - {state, buffers} - end) + Enum.reduce(1..10, {state, []}, fn idx, {state, buffers} -> + key_frame? = rem(idx, 4) == 0 + buffer = generate_buffer(key_frame?) - buffers = Enum.reverse(buffers) - pad = Pad.ref(:output, make_ref()) + buffers = if key_frame?, do: [buffer], else: [buffer | buffers] - actions = - [stream_format: {pad, @stream_format}] ++ - Enum.map(buffers, &{:buffer, {pad, &1}}) ++ [end_of_stream: pad] + assert {[], %{cvs: ^buffers} = state} = + CVSBufferer.handle_buffer(:input, buffer, @ctx, state) - assert {^actions, ^state} = CVSBufferer.handle_pad_added(pad, @ctx, state) + {state, buffers} + end) end defp generate_buffer(key_frame?) do diff --git a/ui/test/ex_nvr/pipelines/snapshot_test.exs b/ui/test/ex_nvr/pipelines/snapshot_test.exs deleted file mode 100644 index af28b94d..00000000 --- a/ui/test/ex_nvr/pipelines/snapshot_test.exs +++ /dev/null @@ -1,67 +0,0 @@ -defmodule ExNVR.Pipelines.SnapshotTest do - @moduledoc false - - use ExNVR.DataCase - - import ExNVR.DevicesFixtures - import ExNVR.RecordingsFixtures - - alias ExNVR.Pipelines - - @moduletag :tmp_dir - - setup ctx do - device = camera_device_fixture(ctx.tmp_dir) - - avc_recording = - recording_fixture(device, - start_date: ~U(2023-06-23 10:00:00Z), - end_date: ~U(2023-06-23 10:00:05Z) - ) - - hevc_recording = - recording_fixture(device, - start_date: ~U(2023-06-23 10:00:10Z), - end_date: ~U(2023-06-23 10:00:15Z), - encoding: :H265 - ) - - %{device: device, avc_recording: avc_recording, hevc_recording: hevc_recording} - end - - defp perform_test(device, recording, ref_path, method \\ :before) do - assert {:ok, _sup_pid, _pid} = - Pipelines.Snapshot.start( - device: device, - date: DateTime.add(recording.start_date, 3050, :millisecond), - method: method - ) - - assert_receive {:snapshot, snapshot}, 1_000, "No snapshot received" - assert snapshot == File.read!(ref_path), "Content not the same" - end - - defp ref_path(encoding, method) do - Path.expand("../../fixtures/images/#{encoding}/ref-#{method}.jpeg", __DIR__) - end - - describe "snapshot is created" do - test "from closest keyframe before specified date time", %{ - device: device, - avc_recording: avc_recording, - hevc_recording: hevc_recording - } do - perform_test(device, avc_recording, ref_path(:h264, "before-keyframe")) - perform_test(device, hevc_recording, ref_path(:h265, "before-keyframe")) - end - - test "with exact time", %{ - device: device, - avc_recording: avc_recording, - hevc_recording: hevc_recording - } do - perform_test(device, avc_recording, ref_path(:h264, "precise"), :precise) - perform_test(device, hevc_recording, ref_path(:h265, "precise"), :precise) - end - end -end