Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add h265 tests #55

Merged
merged 6 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,9 @@ defmodule Membrane.H26x.NALuParser.SchemeParser do
ExpGolombConverter.to_integer(payload, negatives: true)

unsigned_int ->
how_many_bits = Atom.to_string(unsigned_int) |> String.slice(1..-1) |> String.to_integer()
how_many_bits =
Atom.to_string(unsigned_int) |> String.slice(1..-1//1) |> String.to_integer()

<<value::unsigned-size(how_many_bits), rest::bitstring>> = payload
{value, rest}
end
Expand Down
Binary file added test/fixtures/h265/input-10-1920x1080.h265
Binary file not shown.
Binary file not shown.
Binary file added test/fixtures/h265/input-10-640x480-main10.h265
Binary file not shown.
Binary file added test/fixtures/h265/input-10-no-vps-sps-pps.h265
Binary file not shown.
Binary file not shown.
Binary file added test/fixtures/h265/input-30-1280x720-rext.h265
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added test/fixtures/h265/input-32-640x360-main.h265
Binary file not shown.
Binary file added test/fixtures/h265/input-60-1920x1080.h265
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added test/fixtures/h265/input-60-640x480.h265
Binary file not shown.
Binary file added test/fixtures/h265/input-8-2K.h265
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added test/fixtures/h265/mp4/ref_video.mp4
Binary file not shown.
Binary file not shown.
Binary file added test/fixtures/h265/msr/ref_video-hev1-au.msr
Binary file not shown.
Binary file not shown.
Binary file added test/fixtures/h265/msr/ref_video-hvc1-au.msr
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ defmodule Membrane.H264.ModesTest do

import Membrane.ChildrenSpec
import Membrane.Testing.Assertions
import Membrane.H264.Support.Common
import Membrane.H26x.Support.Common

alias Membrane.Buffer
alias Membrane.H264.Parser
alias Membrane.H264.Support.TestSource
alias Membrane.H26x.Support.TestSource
alias Membrane.Testing.{Pipeline, Sink}

@h264_input_file "test/fixtures/input-10-720p.h264"
@h264_input_file "test/fixtures/h264/input-10-720p.h264"

test "if the pts and dts are set to nil in :bytestream mode" do
binary = File.read!(@h264_input_file)
mode = :bytestream
input_buffers = prepare_buffers(binary, mode)
input_buffers = prepare_h264_buffers(binary, mode)

{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
Expand All @@ -30,7 +30,7 @@ defmodule Membrane.H264.ModesTest do
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

output_buffers = prepare_buffers(binary, :au_aligned)
output_buffers = prepare_h264_buffers(binary, :au_aligned)

Enum.each(output_buffers, fn buf ->
payload = buf.payload
Expand All @@ -43,7 +43,7 @@ defmodule Membrane.H264.ModesTest do
test "if the pts and dts are rewritten properly in :nalu_aligned mode" do
binary = File.read!(@h264_input_file)
mode = :nalu_aligned
input_buffers = prepare_buffers(binary, mode)
input_buffers = prepare_h264_buffers(binary, mode)

{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
Expand All @@ -58,7 +58,7 @@ defmodule Membrane.H264.ModesTest do
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

output_buffers = prepare_buffers(binary, :au_aligned)
output_buffers = prepare_h264_buffers(binary, :au_aligned)

Enum.each(output_buffers, fn buf ->
payload = buf.payload
Expand All @@ -73,7 +73,7 @@ defmodule Membrane.H264.ModesTest do
test "if the pts and dts are rewritten properly in :au_aligned mode" do
binary = File.read!(@h264_input_file)
mode = :au_aligned
input_buffers = prepare_buffers(binary, mode)
input_buffers = prepare_h264_buffers(binary, mode)

{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
Expand Down Expand Up @@ -114,7 +114,7 @@ defmodule Membrane.H264.ModesTest do
assert_sink_stream_format(pid, :sink, %Membrane.H264{alignment: :nalu})

binary = File.read!(@h264_input_file)
ref_buffers = prepare_buffers(binary, :nalu_aligned)
ref_buffers = prepare_h264_buffers(binary, :nalu_aligned)

Enum.each(ref_buffers, fn ref_buffer ->
assert_sink_buffer(pid, :sink, buffer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,14 @@ defmodule Membrane.H264.TimestampGenerationTest do

import Membrane.ChildrenSpec
import Membrane.Testing.Assertions
import Membrane.H264.Support.Common
import Membrane.H26x.Support.Common

alias Membrane.Buffer
alias Membrane.H264.Parser
alias Membrane.H264.Support.TestSource
alias Membrane.H26x.Support.TestSource
alias Membrane.Testing.{Pipeline, Sink}

defmodule EnhancedPipeline do
@moduledoc false

use Membrane.Pipeline

@impl true
def handle_init(_ctx, args) do
{[spec: args], %{}}
end

@impl true
def handle_call({:get_child_pid, child}, ctx, state) do
child_pid = Map.get(ctx.children, child).pid
{[reply: child_pid], state}
end
end

@h264_input_file_main "test/fixtures/input-10-720p.h264"
@h264_input_file_main "test/fixtures/h264/input-10-720p.h264"
@h264_input_timestamps_main [
{0, -500},
{133, -467},
Expand All @@ -42,14 +25,14 @@ defmodule Membrane.H264.TimestampGenerationTest do
{233, -233},
{300, -200}
]
@h264_input_file_baseline "test/fixtures/input-10-720p-baseline.h264"
@h264_input_file_baseline "test/fixtures/h264/input-10-720p-baseline.h264"
@h264_input_timestamps_baseline [0, 33, 67, 100, 133, 167, 200, 233, 267, 300]
|> Enum.map(&{&1, &1 - 500})

test "if the pts and dts are set to nil in :bytestream mode when framerate isn't given" do
binary = File.read!(@h264_input_file_baseline)
mode = :bytestream
input_buffers = prepare_buffers(binary, mode)
input_buffers = prepare_h264_buffers(binary, mode)

{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
Expand All @@ -64,7 +47,7 @@ defmodule Membrane.H264.TimestampGenerationTest do
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

output_buffers = prepare_buffers(binary, :au_aligned)
output_buffers = prepare_h264_buffers(binary, :au_aligned)

Enum.each(output_buffers, fn buf ->
payload = buf.payload
Expand All @@ -87,7 +70,7 @@ defmodule Membrane.H264.TimestampGenerationTest do
""" do
binary = File.read!(unquote(file))
mode = :bytestream
input_buffers = prepare_buffers(binary, mode)
input_buffers = prepare_h264_buffers(binary, mode)

framerate = {30, 1}

Expand All @@ -106,7 +89,7 @@ defmodule Membrane.H264.TimestampGenerationTest do
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

output_buffers = prepare_buffers(binary, :au_aligned)
output_buffers = prepare_h264_buffers(binary, :au_aligned)

output_buffers
|> Enum.zip(unquote(timestamps))
Expand Down
129 changes: 129 additions & 0 deletions test/integration/h265/modes_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
defmodule Membrane.H265.ModesTest do
@moduledoc false
use ExUnit.Case, async: true

import Membrane.ChildrenSpec
import Membrane.H26x.Support.Common
import Membrane.Testing.Assertions

alias Membrane.Buffer
alias Membrane.H265.Parser
alias Membrane.H26x.Support.TestSource
alias Membrane.Testing.{Pipeline, Sink}

@h265_input_file "test/fixtures/h265/input-8-2K.h265"

test "if the pts and dts are set to nil in :bytestream mode" do
binary = File.read!(@h265_input_file)
mode = :bytestream
input_buffers = prepare_h265_buffers(binary, mode)

pid =
Pipeline.start_supervised!(
spec: [
child(:source, %TestSource{mode: mode, codec: :H265})
|> child(:parser, Parser)
|> child(:sink, Sink)
]
)

assert_sink_playing(pid, :sink)
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

output_buffers = prepare_h265_buffers(binary, :au_aligned)

Enum.each(output_buffers, fn buf ->
payload = buf.payload
assert_sink_buffer(pid, :sink, %Buffer{payload: ^payload, pts: nil, dts: nil})
end)

Pipeline.terminate(pid)
end

test "if the pts and dts are rewritten properly in :nalu_aligned mode" do
binary = File.read!(@h265_input_file)
mode = :nalu_aligned
input_buffers = prepare_h265_buffers(binary, mode)

pid =
Pipeline.start_supervised!(
spec: [
child(:source, %TestSource{mode: mode, codec: :H265})
|> child(:parser, Parser)
|> child(:sink, Sink)
]
)

assert_sink_playing(pid, :sink)
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

output_buffers = prepare_h265_buffers(binary, :au_aligned)

Enum.each(output_buffers, fn buf ->
payload = buf.payload
pts = buf.pts
dts = buf.dts
assert_sink_buffer(pid, :sink, %Buffer{payload: ^payload, pts: ^pts, dts: ^dts})
end)

Pipeline.terminate(pid)
end

test "if the pts and dts are rewritten properly in :au_aligned mode" do
binary = File.read!(@h265_input_file)
mode = :au_aligned
input_buffers = prepare_h265_buffers(binary, mode)

pid =
Pipeline.start_supervised!(
spec: [
child(:source, %TestSource{mode: mode, codec: :H265})
|> child(:parser, Parser)
|> child(:sink, Sink)
]
)

assert_sink_playing(pid, :sink)
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

output_buffers = input_buffers

Enum.each(output_buffers, fn buf ->
payload = buf.payload
pts = buf.pts
dts = buf.dts
assert_sink_buffer(pid, :sink, %Buffer{payload: ^payload, pts: ^pts, dts: ^dts})
end)

Pipeline.terminate(pid)
end

test "if single NAL unit is sent per buffer with `output_alignment: :nalu`" do
pid =
Pipeline.start_supervised!(
spec: [
child(:source, %Membrane.File.Source{location: @h265_input_file})
|> child(:parser, %Parser{output_alignment: :nalu})
|> child(:sink, Sink)
]
)

assert_sink_playing(pid, :sink)
assert_sink_stream_format(pid, :sink, %Membrane.H265{alignment: :nalu})

binary = File.read!(@h265_input_file)
ref_buffers = prepare_h265_buffers(binary, :nalu_aligned)

Enum.each(ref_buffers, fn ref_buffer ->
assert_sink_buffer(pid, :sink, buffer)
assert buffer.payload == ref_buffer.payload
assert Map.has_key?(buffer.metadata, :h265) and Map.has_key?(buffer.metadata.h265, :type)
end)

assert_end_of_stream(pid, :sink)
Pipeline.terminate(pid)
end
end
Loading