diff --git a/README.md b/README.md index eb2836d..fe7a7be 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ The package can be installed by adding `membrane_aac_fdk_plugin` to your list of ```elixir def deps do [ - {:membrane_aac_fdk_plugin, "~> 0.18.7"} + {:membrane_aac_fdk_plugin, "~> 0.18.8"} ] end ``` diff --git a/lib/membrane_aac_fdk_plugin/encoder.ex b/lib/membrane_aac_fdk_plugin/encoder.ex index eb15346..bb9c8ae 100644 --- a/lib/membrane_aac_fdk_plugin/encoder.ex +++ b/lib/membrane_aac_fdk_plugin/encoder.ex @@ -277,7 +277,8 @@ defmodule Membrane.AAC.FDK.Encoder do end defp validate_pts_integrity(packets, input_pts) do - with [%Buffer{pts: first_pts}, %Buffer{pts: second_pts} | _tail] <- packets do + with [%Buffer{pts: first_pts}, %Buffer{pts: second_pts} | _tail] + when first_pts != nil and second_pts != nil <- packets do duration = second_pts - first_pts epsilon = duration / 10 diff --git a/mix.exs b/mix.exs index 5308a8b..45696cb 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule Membrane.AAC.FDK.Plugin.MixProject do use Mix.Project - @version "0.18.7" + @version "0.18.8" @github_url "https://github.com/membraneframework/membrane_aac_fdk_plugin" def project do diff --git a/test/membrane_element_fdk_aac/pts_test.exs b/test/membrane_element_fdk_aac/pts_test.exs new file mode 100644 index 0000000..30664b0 --- /dev/null +++ b/test/membrane_element_fdk_aac/pts_test.exs @@ -0,0 +1,77 @@ +defmodule Membrane.FLAC.Parser.IntegrationTest do + use ExUnit.Case, async: true + import Membrane.Testing.Assertions + alias Membrane.{Pipeline, Time} + + test "encode with timestamps" do + pipeline = prepare_pts_test_pipeline(true) + + Enum.each(0..294, fn index -> + assert_sink_buffer(pipeline, :sink, %Membrane.Buffer{pts: out_pts}) + + # every other buffer gets queued and concated with next one to be big enough, because of that we expect different pts than on input + assert out_pts == (index * 2 * 1000) |> Time.nanoseconds() + end) + + Pipeline.terminate(pipeline) + end + + test "encode without timestamps" do + pipeline = prepare_pts_test_pipeline(false) + + Enum.each(0..294, fn _index -> + assert_sink_buffer(pipeline, :sink, %Membrane.Buffer{pts: out_pts}) + assert out_pts == nil + end) + + Pipeline.terminate(pipeline) + end + + defp prepare_pts_test_pipeline(with_pts?) do + import Membrane.ChildrenSpec + + spec = + child(:source, %Membrane.Testing.Source{ + output: buffers_from_file(with_pts?), + stream_format: %Membrane.RawAudio{ + sample_format: :s16le, + sample_rate: 16_000, + channels: 1 + } + }) + |> child(:aac_encoder, Membrane.AAC.FDK.Encoder) + |> child(:sink, Membrane.Testing.Sink) + + Membrane.Testing.Pipeline.start_link_supervised!(spec: spec) + end + + defp buffers_from_file(with_pts?) do + # 589 buffers is generated from this binary + binary = "../fixtures/input-encoder.raw" |> Path.expand(__DIR__) |> File.read!() + + split_binary(binary) + |> Enum.with_index() + |> Enum.map(fn {payload, index} -> + %Membrane.Buffer{ + payload: payload, + pts: + if with_pts? do + (index * 1000) |> Time.nanoseconds() + else + nil + end + } + end) + end + + @spec split_binary(binary(), list(binary())) :: list(binary()) + def split_binary(binary, acc \\ []) + + def split_binary(<>, acc) do + split_binary(rest, [binary] ++ acc) + end + + def split_binary(rest, acc) when byte_size(rest) <= 1024 do + Enum.reverse(acc) ++ [rest] + end +end