Skip to content

Commit

Permalink
Add h265 tests (#55)
Browse files Browse the repository at this point in the history
* Restructure h264 test files

* Add h265 test fixtures

* Add h265 tests

* Fix string slice warning on elixir 1.16

* Improve process all test

* rename functions and paths for consistency
  • Loading branch information
gBillal authored Jan 16, 2024
1 parent aeb5295 commit 205ac35
Show file tree
Hide file tree
Showing 81 changed files with 1,181 additions and 91 deletions.
4 changes: 3 additions & 1 deletion lib/membrane_h264_plugin/h26x/nalu_parser/scheme_parser.ex
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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
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 added test/fixtures/h265/input-irap-pss-no-irap.h265
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 added test/fixtures/h265/msr/ref_video-hev1-nalu.msr
Binary file not shown.
Binary file added test/fixtures/h265/msr/ref_video-hvc1-au.msr
Binary file not shown.
Binary file added test/fixtures/h265/msr/ref_video-hvc1-nalu.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.
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

0 comments on commit 205ac35

Please sign in to comment.