Skip to content

Commit

Permalink
Add YUV 10 bits formats (#15)
Browse files Browse the repository at this point in the history
* Add YUV 10 bits formats

* bump to v0.4.2
  • Loading branch information
gBillal authored Oct 24, 2024
1 parent e15a1ca commit 4b7944e
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ reason, just add the following line to your `deps` in the `mix.exs` and run
`mix deps.get`.

```elixir
{:membrane_raw_video_format, "~> 0.4.1"}
{:membrane_raw_video_format, "~> 0.4.2"}
```

## Copyright and License
Expand Down
55 changes: 52 additions & 3 deletions lib/membrane_raw_video.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,24 @@ defmodule Membrane.RawVideo do
Format used to encode the color of every pixel in each video frame.
"""
@type pixel_format ::
:I420 | :I422 | :I444 | :RGB | :BGRA | :RGBA | :NV12 | :NV21 | :YV12 | :AYUV | :YUY2
:I420
| :I422
| :I444
| :RGB
| :BGR
| :BGRA
| :RGBA
| :NV12
| :NV21
| :YV12
| :AYUV
| :YUY2
| :I420_10LE
| :I420_10BE
| :I422_10LE
| :I422_10BE
| :I444_10LE
| :I444_10BE

@typedoc """
Determines, whether buffers are aligned i.e. each buffer contains one frame.
Expand All @@ -51,13 +68,20 @@ defmodule Membrane.RawVideo do
:I422,
:I444,
:RGB,
:BGR,
:BGRA,
:RGBA,
:NV12,
:NV21,
:YV12,
:AYUV,
:YUY2
:YUY2,
:I420_10LE,
:I420_10BE,
:I422_10LE,
:I422_10BE,
:I444_10LE,
:I444_10BE
]

@doc """
Expand Down Expand Up @@ -96,7 +120,7 @@ defmodule Membrane.RawVideo do
{:ok, width * height * 2}
end

def frame_size(format, width, height) when format in [:I444, :RGB] do
def frame_size(format, width, height) when format in [:I444, :RGB, :BGR] do
# No subsampling
{:ok, width * height * 3}
end
Expand All @@ -106,6 +130,31 @@ defmodule Membrane.RawVideo do
{:ok, width * height * 4}
end

def frame_size(format, width, height)
when format in [:I420_10LE, :I420_10BE] and Integer.is_even(width) and
Integer.is_even(height) do
# Subsampling by 2 in both dimensions
# Each pixel requires 2 bytes.
# Y = 2 * width * height
# V = U = 2 * (width / 2) * (height / 2)
{:ok, 3 * width * height}
end

def frame_size(format, width, height)
when format in [:I422_10LE, :I422_10BE] and Integer.is_even(width) do
# Subsampling by 2 in horizontal dimension
# Each pixel requires 2 bytes.
# Y = 2 * width * height
# V = U = 2 * (width / 2) * height
{:ok, 4 * width * height}
end

def frame_size(format, width, height) when format in [:I444_10LE, :I444_10BE] do
# No subsampling
# Each pixel requires 2 bytes.
{:ok, 6 * width * height}
end

def frame_size(format, _width, _height) when format in @supported_pixel_formats do
{:error, :invalid_dimensions}
end
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Membrane.RawVideo.Mixfile do
use Mix.Project

@version "0.4.1"
@version "0.4.2"
@github_url "https://github.com/membraneframework/membrane_raw_video_format"

def project do
Expand Down
36 changes: 36 additions & 0 deletions test/membrane_raw_video_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,42 @@ defmodule Membrane.RawVideo.Test do
assert @module.frame_size(format_struct(format, 10, 19)) == {:ok, 760}
end

test "frame_size for :I420_10xx format" do
format = :I420_10LE

assert @module.frame_size(format, 10, 20) == {:ok, 600}
assert @module.frame_size(format, 9, 20) == {:error, :invalid_dimensions}
assert @module.frame_size(format, 10, 19) == {:error, :invalid_dimensions}

assert @module.frame_size(format_struct(format, 10, 20)) == {:ok, 600}
assert @module.frame_size(format_struct(format, 9, 20)) == {:error, :invalid_dimensions}
assert @module.frame_size(format_struct(format, 10, 19)) == {:error, :invalid_dimensions}
end

test "frame_size for :I422_10xx format" do
format = :I422_10LE

assert @module.frame_size(format, 10, 20) == {:ok, 800}
assert @module.frame_size(format, 9, 20) == {:error, :invalid_dimensions}
assert @module.frame_size(format, 10, 19) == {:ok, 760}

assert @module.frame_size(format_struct(format, 10, 20)) == {:ok, 800}
assert @module.frame_size(format_struct(format, 9, 20)) == {:error, :invalid_dimensions}
assert @module.frame_size(format_struct(format, 10, 19)) == {:ok, 760}
end

test "frame_size for :I44_10xx format" do
format = :I444_10LE

assert @module.frame_size(format, 10, 20) == {:ok, 1200}
assert @module.frame_size(format, 9, 20) == {:ok, 1080}
assert @module.frame_size(format, 10, 19) == {:ok, 1140}

assert @module.frame_size(format_struct(format, 10, 20)) == {:ok, 1200}
assert @module.frame_size(format_struct(format, 9, 20)) == {:ok, 1080}
assert @module.frame_size(format_struct(format, 10, 19)) == {:ok, 1140}
end

test "frame_size error on unknown pixel format" do
assert @module.frame_size(:yuv_240p, 10, 20) == {:error, :invalid_pixel_format}
end
Expand Down

0 comments on commit 4b7944e

Please sign in to comment.