From a4be345350794e3e35c0a4174e87e6db981128c2 Mon Sep 17 00:00:00 2001 From: DominikWolek Date: Thu, 12 Oct 2023 12:20:36 +0200 Subject: [PATCH] Use precompiled ffmpeg (#49) * Use precompiled ffmpeg * Change releases to latests * Ignore gcc warnings * Prepare for releasing * Unify get_ffmpeg_url * Cleanup pragmas * Replace depracated av_get_channel_layout_nb_channels with AVChannelLayout * Remove unecessary warning ignoring --- README.md | 24 ++++- bundlex.exs | 22 ++++- .../converter.h | 3 +- .../converter_lib.c | 99 +++++++++++++------ .../converter_lib.h | 8 +- mix.exs | 4 +- mix.lock | 21 ++-- 7 files changed, 134 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 68b729d..4ba143c 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,30 @@ It is a part of [Membrane Multimedia Framework](https://membrane.stream). Add the following line to your `deps` in `mix.exs`. Run `mix deps.get`. ```elixir -{:membrane_ffmpeg_swresample_plugin, "~> 0.17.3"} +{:membrane_ffmpeg_swresample_plugin, "~> 0.18.0"} ``` -You also need to have [FFmpeg](https://www.ffmpeg.org/) library installed. +The precompiled builds of the [ffmpeg](https://www.ffmpeg.org) will be pulled and linked automatically. However, should there be any problems, consider installing it manually. + +### Manual instalation of dependencies + +#### macOS + +```shell +brew install ffmpeg +``` + +#### Ubuntu + +```shell +sudo apt-get install ffmpeg +``` + +#### Arch / Manjaro + +```shell +pacman -S ffmpeg +``` ## Usage diff --git a/bundlex.exs b/bundlex.exs index 161adf4..dcde3f4 100644 --- a/bundlex.exs +++ b/bundlex.exs @@ -1,6 +1,26 @@ defmodule Membrane.FFmpeg.SWResample.BundlexProject do use Bundlex.Project + defp get_ffmpeg_url() do + membrane_precompiled_url_prefix = + "https://github.com/membraneframework-precompiled/precompiled_ffmpeg/releases/latest/download/ffmpeg" + + case Bundlex.get_target() do + %{os: "linux"} -> + {:precompiled, + "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n6.0-latest-linux64-gpl-shared-6.0.tar.xz"} + + %{architecture: "x86_64", os: "darwin" <> _rest_of_os_name} -> + {:precompiled, "#{membrane_precompiled_url_prefix}_macos_intel.tar.gz"} + + %{architecture: "aarch64", os: "darwin" <> _rest_of_os_name} -> + {:precompiled, "#{membrane_precompiled_url_prefix}_macos_arm.tar.gz"} + + _other -> + nil + end + end + def project do [ natives: natives() @@ -13,7 +33,7 @@ defmodule Membrane.FFmpeg.SWResample.BundlexProject do interface: :nif, sources: ["converter.c", "converter_lib.c"], deps: [membrane_common_c: :membrane, unifex: :unifex], - pkg_configs: ["libavutil", "libswresample"], + os_deps: [{[get_ffmpeg_url(), :pkg_config], ["libswresample", "libavutil"]}], preprocessor: Unifex ] ] diff --git a/c_src/membrane_ffmpeg_swresample_plugin/converter.h b/c_src/membrane_ffmpeg_swresample_plugin/converter.h index da96051..6e0971b 100644 --- a/c_src/membrane_ffmpeg_swresample_plugin/converter.h +++ b/c_src/membrane_ffmpeg_swresample_plugin/converter.h @@ -1,7 +1,8 @@ #pragma once -#include #include + +#include #include #include "converter_lib.h" diff --git a/c_src/membrane_ffmpeg_swresample_plugin/converter_lib.c b/c_src/membrane_ffmpeg_swresample_plugin/converter_lib.c index 8987753..861d6a5 100644 --- a/c_src/membrane_ffmpeg_swresample_plugin/converter_lib.c +++ b/c_src/membrane_ffmpeg_swresample_plugin/converter_lib.c @@ -1,13 +1,16 @@ + #include "converter_lib.h" char *lib_init(ConverterState *state, char from_s24le, enum AVSampleFormat src_sample_fmt, int src_rate, int64_t src_ch_layout, enum AVSampleFormat dst_sample_fmt, - int dst_rate, int64_t dst_ch_layout) { + int dst_rate, int64_t dst_ch_layout) +{ state->swr_ctx = NULL; struct SwrContext *swr_ctx = swr_alloc(); - if (!swr_ctx) { + if (!swr_ctx) + { return "swr_alloc"; } @@ -23,14 +26,19 @@ char *lib_init(ConverterState *state, char from_s24le, if (swr_init(swr_ctx) < 0) return "swr_init"; + AVChannelLayout src_ch_av_layout; + AVChannelLayout dst_ch_av_layout; + av_channel_layout_from_mask(&src_ch_av_layout, src_ch_layout); + av_channel_layout_from_mask(&dst_ch_av_layout, dst_ch_layout); + *state = (ConverterState){ .swr_ctx = swr_ctx, .src_rate = src_rate, .dst_rate = dst_rate, .src_sample_fmt = src_sample_fmt, .dst_sample_fmt = dst_sample_fmt, - .src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout), - .dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout), + .src_nb_channels = src_ch_av_layout.nb_channels, + .dst_nb_channels = dst_ch_av_layout.nb_channels, .from_s24le = from_s24le}; return NULL; @@ -38,20 +46,26 @@ char *lib_init(ConverterState *state, char from_s24le, static char *free_conversion_data(char *error, ConverterState *state, uint8_t *input, uint8_t **src_data, - uint8_t **dst_data) { - if (state->from_s24le && input) { + uint8_t **dst_data) +{ + if (state->from_s24le && input) + { unifex_free(input); } - if (src_data) { - if (src_data[0]) { + if (src_data) + { + if (src_data[0]) + { av_freep(&src_data[0]); } av_freep(&src_data); } - if (dst_data) { - if (error && dst_data[0]) { + if (dst_data) + { + if (error && dst_data[0]) + { av_freep(&dst_data[0]); } av_freep(&dst_data); @@ -60,18 +74,21 @@ static char *free_conversion_data(char *error, ConverterState *state, return error; } -static char *convert_s24le_to_s32le(uint8_t **data, int *data_size) { +static char *convert_s24le_to_s32le(uint8_t **data, int *data_size) +{ uint8_t *input = *data; int input_size = *data_size; - if (input_size % 3 != 0) { + if (input_size % 3 != 0) + { return "invalid_input_size"; } int output_size = input_size * 4 / 3; uint8_t *output = unifex_alloc(output_size); - for (int i = 0; i < input_size / 3; i++) { + for (int i = 0; i < input_size / 3; i++) + { uint8_t b0 = input[3 * i]; uint8_t b1 = input[3 * i + 1]; uint8_t b2 = input[3 * i + 2]; @@ -87,10 +104,13 @@ static char *convert_s24le_to_s32le(uint8_t **data, int *data_size) { } char *lib_convert(ConverterState *state, uint8_t *input, int input_size, - uint8_t **output, int *output_size) { - if (state->from_s24le) { + uint8_t **output, int *output_size) +{ + if (state->from_s24le) + { char *res = convert_s24le_to_s32le(&input, &input_size); - if (res) { + if (res) + { return res; } } @@ -103,7 +123,8 @@ char *lib_convert(ConverterState *state, uint8_t *input, int input_size, if (0 > av_samples_alloc_array_and_samples( &src_data, &src_linesize, state->src_nb_channels, src_nb_samples, - state->src_sample_fmt, 1)) { + state->src_sample_fmt, 1)) + { return free_conversion_data("alloc_source_samples", state, input, src_data, dst_data); } @@ -114,7 +135,8 @@ char *lib_convert(ConverterState *state, uint8_t *input, int input_size, if (0 > av_samples_alloc_array_and_samples( &dst_data, &dst_linesize, state->dst_nb_channels, - max_dst_nb_samples, state->dst_sample_fmt, 1)) { + max_dst_nb_samples, state->dst_sample_fmt, 1)) + { return free_conversion_data("alloc_destination_samples", state, input, src_data, dst_data); } @@ -122,18 +144,23 @@ char *lib_convert(ConverterState *state, uint8_t *input, int input_size, int dst_nb_samples = swr_convert(state->swr_ctx, dst_data, max_dst_nb_samples, (const uint8_t **)src_data, src_nb_samples); - if (dst_nb_samples < 0) { + if (dst_nb_samples < 0) + { return free_conversion_data("convert", state, input, src_data, dst_data); } - if (dst_nb_samples == 0) { + if (dst_nb_samples == 0) + { *output_size = 0; - } else { + } + else + { *output_size = av_samples_get_buffer_size(&dst_linesize, state->dst_nb_channels, dst_nb_samples, state->dst_sample_fmt, 1); - if (*output_size < 0) { + if (*output_size < 0) + { return free_conversion_data("calculate_output_size", state, input, src_data, dst_data); } @@ -144,13 +171,15 @@ char *lib_convert(ConverterState *state, uint8_t *input, int input_size, return NULL; } -char *lib_flush(ConverterState *state, uint8_t **output, int *output_size) { +char *lib_flush(ConverterState *state, uint8_t **output, int *output_size) +{ uint8_t **dst_data = NULL; int dst_linesize; int max_dst_nb_samples = swr_get_out_samples(state->swr_ctx, 0); - if (max_dst_nb_samples == 0) { + if (max_dst_nb_samples == 0) + { // nothing was buffered, converter does not need flush *output = NULL; *output_size = 0; @@ -159,7 +188,8 @@ char *lib_flush(ConverterState *state, uint8_t **output, int *output_size) { if (0 > av_samples_alloc_array_and_samples( &dst_data, &dst_linesize, state->dst_nb_channels, - max_dst_nb_samples, state->dst_sample_fmt, 0)) { + max_dst_nb_samples, state->dst_sample_fmt, 0)) + { return free_conversion_data("alloc_destination_samples", state, NULL, NULL, dst_data); } @@ -167,19 +197,24 @@ char *lib_flush(ConverterState *state, uint8_t **output, int *output_size) { int dst_nb_samples = swr_convert(state->swr_ctx, dst_data, max_dst_nb_samples, NULL, 0); - if (dst_nb_samples < 0) { + if (dst_nb_samples < 0) + { return free_conversion_data("convert", state, NULL, NULL, dst_data); } - if (dst_nb_samples == 0) { + if (dst_nb_samples == 0) + { *output = NULL; *output_size = 0; - } else { + } + else + { *output = dst_data[0]; *output_size = av_samples_get_buffer_size(&dst_linesize, state->dst_nb_channels, dst_nb_samples, state->dst_sample_fmt, 1); - if (*output_size < 0) { + if (*output_size < 0) + { return free_conversion_data("calculate_output_size", state, NULL, NULL, dst_data); } @@ -191,8 +226,10 @@ char *lib_flush(ConverterState *state, uint8_t **output, int *output_size) { void lib_free_output(uint8_t **output) { av_freep(output); } -void lib_destroy(ConverterState *state) { - if (state->swr_ctx) { +void lib_destroy(ConverterState *state) +{ + if (state->swr_ctx) + { swr_free(&(state->swr_ctx)); } } diff --git a/c_src/membrane_ffmpeg_swresample_plugin/converter_lib.h b/c_src/membrane_ffmpeg_swresample_plugin/converter_lib.h index 2490d97..f0b503f 100644 --- a/c_src/membrane_ffmpeg_swresample_plugin/converter_lib.h +++ b/c_src/membrane_ffmpeg_swresample_plugin/converter_lib.h @@ -1,10 +1,10 @@ -#include -#include -#include #include +#include +#include #include -typedef struct ConverterState { +typedef struct ConverterState +{ struct SwrContext *swr_ctx; enum AVSampleFormat src_sample_fmt, dst_sample_fmt; int src_rate, dst_rate; diff --git a/mix.exs b/mix.exs index fb68e98..094456b 100644 --- a/mix.exs +++ b/mix.exs @@ -2,7 +2,7 @@ defmodule Membrane.FFmpeg.SWResample.Mixfile do use Mix.Project @github_url "https://github.com/membraneframework/membrane_ffmpeg_swresample_plugin" - @version "0.17.3" + @version "0.18.0" def project do [ @@ -45,7 +45,7 @@ defmodule Membrane.FFmpeg.SWResample.Mixfile do {:bunch, "~> 1.6"}, {:unifex, "~> 1.1"}, {:membrane_common_c, "~> 0.15.0"}, - {:bundlex, "~> 1.0"}, + {:bundlex, "~> 1.2"}, # Testing {:mockery, "~> 2.1", runtime: false}, {:membrane_file_plugin, "~> 0.15.0", only: :test}, diff --git a/mix.lock b/mix.lock index b0fd690..ba4972a 100644 --- a/mix.lock +++ b/mix.lock @@ -2,30 +2,39 @@ "bimap": {:hex, :bimap, "1.3.0", "3ea4832e58dc83a9b5b407c6731e7bae87458aa618e6d11d8e12114a17afa4b3", [:mix], [], "hexpm", "bf5a2b078528465aa705f405a5c638becd63e41d280ada41e0f77e6d255a10b4"}, "bunch": {:hex, :bunch, "1.6.0", "4775f8cdf5e801c06beed3913b0bd53fceec9d63380cdcccbda6be125a6cfd54", [:mix], [], "hexpm", "ef4e9abf83f0299d599daed3764d19e8eac5d27a5237e5e4d5e2c129cfeb9a22"}, "bunch_native": {:hex, :bunch_native, "0.5.0", "8ac1536789a597599c10b652e0b526d8833348c19e4739a0759a2bedfd924e63", [:mix], [{:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "24190c760e32b23b36edeb2dc4852515c7c5b3b8675b1a864e0715bdd1c8f80d"}, - "bundlex": {:hex, :bundlex, "1.1.1", "e637b79a1eaab1bf019de4100b6db262aa3b660beff0cd2f3617949b1618eeda", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:secure_random, "~> 0.5", [hex: :secure_random, repo: "hexpm", optional: false]}], "hexpm", "1fdfa3d6240baa5a2d5496a86e2e43116f80105e93d9adfd4f1fc75be487ea30"}, + "bundlex": {:hex, :bundlex, "1.2.0", "a89869208a019376a38e8a10e1bd573dcbeae8addd381c2cd74e2817010bef8f", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, "~> 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:secure_random, "~> 0.5", [hex: :secure_random, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "d2182b91a2a53847baadf4745ad2291853e786ad28671f474a611e7703dbca9b"}, "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, + "castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"}, "coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"}, - "credo": {:hex, :credo, "1.7.0", "6119bee47272e85995598ee04f2ebbed3e947678dee048d10b5feca139435f75", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "6839fcf63d1f0d1c0f450abc8564a57c43d644077ab96f2934563e68b8a769d7"}, - "dialyxir": {:hex, :dialyxir, "1.3.0", "fd1672f0922b7648ff9ce7b1b26fcf0ef56dda964a459892ad15f6b4410b5284", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "00b2a4bcd6aa8db9dcb0b38c1225b7277dca9bc370b6438715667071a304696f"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.33", "3c3fd9673bb5dcc9edc28dd90f50c87ce506d1f71b70e3de69aa8154bc695d44", [:mix], [], "hexpm", "2d526833729b59b9fdb85785078697c72ac5e5066350663e5be6a1182da61b8f"}, + "credo": {:hex, :credo, "1.7.1", "6e26bbcc9e22eefbff7e43188e69924e78818e2fe6282487d0703652bc20fd62", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e9871c6095a4c0381c89b6aa98bc6260a8ba6addccf7f6a53da8849c748a58a2"}, + "dialyxir": {:hex, :dialyxir, "1.4.1", "a22ed1e7bd3a3e3f197b68d806ef66acb61ee8f57b3ac85fc5d57354c5482a93", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "84b795d6d7796297cca5a3118444b80c7d94f7ce247d49886e7c291e1ae49801"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.37", "2ad73550e27c8946648b06905a57e4d454e4d7229c2dafa72a0348c99d8be5f7", [:mix], [], "hexpm", "6b19783f2802f039806f375610faa22da130b8edc21209d0bff47918bb48360e"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.30.5", "aa6da96a5c23389d7dc7c381eba862710e108cee9cfdc629b7ec021313900e9e", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "88a1e115dcb91cefeef7e22df4a6ebbe4634fbf98b38adcbc25c9607d6d9d8e6"}, + "ex_doc": {:hex, :ex_doc, "0.30.6", "5f8b54854b240a2b55c9734c4b1d0dd7bdd41f71a095d42a70445c03cf05a281", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bd48f2ddacf4e482c727f9293d9498e0881597eae6ddc3d9562bd7923375109f"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, + "finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"}, + "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, "membrane_common_c": {:hex, :membrane_common_c, "0.15.0", "4b6005c562bf025e4a53c95a9646a9f5fa993ac440dd44c1a4d1ea210ec53793", [:mix], [{:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "f9584cca9865ed754b8333e362d49d6c449c708d7c87be6c5f7bd5a1d978d6bf"}, - "membrane_core": {:hex, :membrane_core, "0.12.7", "9d3dd564e32768919c1105b4579bd2eef12df7473da5d789185544ae22610e2d", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "321e4009b7068ca04b65daf5c79b8c3772d4286c27d05e50939ec6d9b4d50e59"}, + "membrane_core": {:hex, :membrane_core, "0.12.9", "b80239deacf98f24cfd2e0703b632e92ddded8b989227cd6e724140f433b0aac", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "389b4b22da0e35d5b053ec2fa87bf36882e0ab88f8fb841af895982fb4abe504"}, "membrane_file_plugin": {:hex, :membrane_file_plugin, "0.15.0", "ddf9535fda82aae5b0688a98de1d02268287ffc8bcc6dba1a85e057d71c522af", [:mix], [{:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "fa2f7219f96c9e815475dc0d8c238c0a5648012917584756eb3eee476f737ce2"}, "membrane_raw_audio_format": {:hex, :membrane_raw_audio_format, "0.11.0", "9b7e8c77f321a3fa1cac2ef157c897938084b704a90ac5450d9f5c87a249b613", [:mix], [{:bimap, "~> 1.1", [hex: :bimap, repo: "hexpm", optional: false]}, {:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "89e0d46893b7cd63d1ab76467d3aae95bd8081e487b18ab0d1679c70d75f7bd8"}, + "mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"}, + "mint": {:hex, :mint, "1.5.1", "8db5239e56738552d85af398798c80648db0e90f343c8469f6c6d8898944fb6f", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "4a63e1e76a7c3956abd2c72f370a0d0aecddc3976dea5c27eccbecfa5e7d5b1e"}, "mockery": {:hex, :mockery, "2.3.1", "a02fd60b10ac9ed37a7a2ecf6786c1f1dd5c75d2b079a60594b089fba32dc087", [:mix], [], "hexpm", "1d0971d88ebf084e962da3f2cfee16f0ea8e04ff73a7710428500d4500b947fa"}, + "nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"}, "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, + "nimble_pool": {:hex, :nimble_pool, "1.0.0", "5eb82705d138f4dd4423f69ceb19ac667b3b492ae570c9f5c900bb3d2f50a847", [:mix], [], "hexpm", "80be3b882d2d351882256087078e1b1952a28bf98d0a287be87e4a24a710b67a"}, "numbers": {:hex, :numbers, "5.2.4", "f123d5bb7f6acc366f8f445e10a32bd403c8469bdbce8ce049e1f0972b607080", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "eeccf5c61d5f4922198395bf87a465b6f980b8b862dd22d28198c5e6fab38582"}, "qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"}, "ratio": {:hex, :ratio, "2.4.2", "c8518f3536d49b1b00d88dd20d49f8b11abb7819638093314a6348139f14f9f9", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "441ef6f73172a3503de65ccf1769030997b0d533b1039422f1e5e0e0b4cbf89e"}, + "req": {:hex, :req, "0.4.4", "a17b6bec956c9af4f08b5d8e8a6fc6e4edf24ccc0ac7bf363a90bba7a0f0138c", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.9", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "2618c0493444fee927d12073afb42e9154e766b3f4448e1011f0d3d551d1a011"}, "secure_random": {:hex, :secure_random, "0.5.1", "c5532b37c89d175c328f5196a0c2a5680b15ebce3e654da37129a9fe40ebf51b", [:mix], [], "hexpm", "1b9754f15e3940a143baafd19da12293f100044df69ea12db5d72878312ae6ab"}, "shmex": {:hex, :shmex, "0.5.0", "7dc4fb1a8bd851085a652605d690bdd070628717864b442f53d3447326bcd3e8", [:mix], [{:bunch_native, "~> 0.5.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "b67bb1e22734758397c84458dbb746519e28eac210423c267c7248e59fc97bdc"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "unifex": {:hex, :unifex, "1.1.0", "26b1bcb6c3b3454e1ea15f85b2e570aaa5b5c609566aa9f5c2e0a8b213379d6b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "d8f47e9e3240301f5b20eec5792d1d4341e1a3a268d94f7204703b48da4aaa06"}, + "zarex": {:hex, :zarex, "1.0.3", "a9e9527a1c31df7f39499819bd76ccb15b0b4e479eed5a4a40db9df7ad7db25c", [:mix], [], "hexpm", "4400a7d33bbf222383ce9a3d5ec9411798eb2b12e86c65ad8e6ac08d8116ca8b"}, }