From 69e4ecf3a4612e6aac6301a84aabe728da11f278 Mon Sep 17 00:00:00 2001 From: Billal GHILAS Date: Thu, 8 Jan 2026 18:19:45 +0100 Subject: [PATCH 1/2] Rename fourcc to codec id --- lib/ex_flv/tag/audio_data.ex | 11 +++---- lib/ex_flv/tag/ex_audio_data.ex | 25 ++++++++-------- lib/ex_flv/tag/ex_video_data.ex | 41 +++++++++++++++++--------- lib/ex_flv/tag/video_data.ex | 6 ++-- test/ex_flv/reader_test.exs | 2 +- test/ex_flv/tag/ex_audio_data_test.exs | 6 ++-- test/ex_flv/tag/ex_video_data_test.exs | 2 +- test/ex_flv/tag_test.exs | 2 +- 8 files changed, 55 insertions(+), 40 deletions(-) diff --git a/lib/ex_flv/tag/audio_data.ex b/lib/ex_flv/tag/audio_data.ex index 7195bb8..a9f71f5 100644 --- a/lib/ex_flv/tag/audio_data.ex +++ b/lib/ex_flv/tag/audio_data.ex @@ -13,8 +13,8 @@ defmodule ExFLV.Tag.AudioData do | :nellymoser_16khz_mono | :nellymoser_8khz_mono | :nellymoser - | :g711_alaw - | :g711_mulaw + | :pcma + | :pcmu | :reserved | :aac | :speex @@ -31,7 +31,8 @@ defmodule ExFLV.Tag.AudioData do data: iodata() | AAC.t() } - defstruct [:sound_format, :sound_rate, :sound_size, :sound_type, :data] + @enforce_keys [:sound_format, :sound_rate, :sound_size, :sound_type] + defstruct @enforce_keys ++ [data: <<>>] @sound_format_map %{ 0 => :pcm, @@ -41,8 +42,8 @@ defmodule ExFLV.Tag.AudioData do 4 => :nellymoser_16khz_mono, 5 => :nellymoser_8khz_mono, 6 => :nellymoser, - 7 => :g711_alaw, - 8 => :g711_mulaw, + 7 => :pcma, + 8 => :pcmu, 9 => :reserved, 10 => :aac, 11 => :speex, diff --git a/lib/ex_flv/tag/ex_audio_data.ex b/lib/ex_flv/tag/ex_audio_data.ex index d0a37cf..9b1d11d 100644 --- a/lib/ex_flv/tag/ex_audio_data.ex +++ b/lib/ex_flv/tag/ex_audio_data.ex @@ -3,7 +3,7 @@ defmodule ExFLV.Tag.ExAudioData do Module describing an enhanced audio data tag. """ - @type fourcc :: :ac3 | :eac3 | :opus | :mp3 | :flac | :aac + @type codec_id :: :ac3 | :eac3 | :opus | :mp3 | :flac | :aac @type channel_order :: :unspecified | :native | :custom @type packet_type :: @@ -44,14 +44,15 @@ defmodule ExFLV.Tag.ExAudioData do @type t :: %__MODULE__{ packet_type: packet_type(), - fourcc: fourcc(), + codec_id: codec_id(), channel_order: channel_order() | nil, channel_count: non_neg_integer() | nil, channels: list(channel()) | nil, data: iodata() } - defstruct [:packet_type, :fourcc, :channel_order, :channel_count, :channels, data: <<>>] + @enforce_keys [:packet_type, :codec_id] + defstruct @enforce_keys ++ [:channel_order, :channel_count, :channels, data: <<>>] @audio_channels %{ 0 => :front_left, @@ -91,7 +92,7 @@ defmodule ExFLV.Tag.ExAudioData do {:ok, %ExFLV.Tag.ExAudioData{ packet_type: :multi_channel_config, - fourcc: :flac, + codec_id: :flac, channel_order: :native, channel_count: 2, channels: [:front_left, :front_right], @@ -102,7 +103,7 @@ defmodule ExFLV.Tag.ExAudioData do {:ok, %ExFLV.Tag.ExAudioData{ packet_type: :coded_frames, - fourcc: :aac, + codec_id: :aac, channel_order: nil, channel_count: nil, channels: nil, @@ -122,12 +123,12 @@ defmodule ExFLV.Tag.ExAudioData do when channel_order in 0..2 do channel_order = parse_channel_order(channel_order) - with {:ok, fourcc} <- parse_fourcc(fourcc), + with {:ok, codec_id} <- parse_fourcc(fourcc), {:ok, channels, rest} <- parse_channels(channel_order, channel_count, data) do {:ok, %__MODULE__{ packet_type: :multi_channel_config, - fourcc: fourcc, + codec_id: codec_id, channel_order: channel_order, channel_count: channel_count, channels: channels, @@ -138,11 +139,11 @@ defmodule ExFLV.Tag.ExAudioData do def parse(<<9::4, packet_type::4, fourcc::binary-size(4), data::binary>>) when packet_type in [0, 1, 2, 7] do - with {:ok, fourcc} <- parse_fourcc(fourcc) do + with {:ok, codec_id} <- parse_fourcc(fourcc) do {:ok, %__MODULE__{ packet_type: parse_packet_type(packet_type), - fourcc: fourcc, + codec_id: codec_id, data: data }} end @@ -156,7 +157,7 @@ defmodule ExFLV.Tag.ExAudioData do iex> ExFLV.Tag.ExAudioData.parse!(<<148, 102, 76, 97, 67, 1, 2, 0, 0, 0, 3>>) %ExFLV.Tag.ExAudioData{ packet_type: :multi_channel_config, - fourcc: :flac, + codec_id: :flac, channel_order: :native, channel_count: 2, channels: [:front_left, :front_right], @@ -233,8 +234,8 @@ defmodule ExFLV.Tag.ExAudioData do end [ - <<9::4, packet_type(audio_data.packet_type)::4, fourcc(audio_data.fourcc)::binary-size(4), - channels::binary>>, + <<9::4, packet_type(audio_data.packet_type)::4, + fourcc(audio_data.codec_id)::binary-size(4), channels::binary>>, audio_data.data ] end diff --git a/lib/ex_flv/tag/ex_video_data.ex b/lib/ex_flv/tag/ex_video_data.ex index 864f822..fdf12a2 100644 --- a/lib/ex_flv/tag/ex_video_data.ex +++ b/lib/ex_flv/tag/ex_video_data.ex @@ -17,17 +17,18 @@ defmodule ExFLV.Tag.ExVideoData do | :multi_track | :mod_ex - @type fourcc :: :avc1 | :hvc1 | :vp08 | :vp09 | :av01 + @type codec_id :: :h264 | :h265 | :vp8 | :vp9 | :av1 @type t :: %__MODULE__{ frame_type: VideoData.frame_type(), packet_type: packet_type(), composition_time_offset: integer(), - fourcc: fourcc(), + codec_id: codec_id(), data: iodata() } - defstruct [:frame_type, :packet_type, :fourcc, :composition_time_offset, :data] + @enforce_keys [:frame_type, :packet_type, :codec_id] + defstruct @enforce_keys ++ [composition_time_offset: 0, data: <<>>] @doc """ Parses the binary into an `ExVideoTag` tag. @@ -37,7 +38,7 @@ defmodule ExFLV.Tag.ExVideoData do %ExFLV.Tag.ExVideoData{ frame_type: :keyframe, packet_type: :sequence_start, - fourcc: :hvc1, + codec_id: :h265, composition_time_offset: 0, data: <<1, 2, 3, 4, 5>> }} @@ -47,7 +48,7 @@ defmodule ExFLV.Tag.ExVideoData do %ExFLV.Tag.ExVideoData{ frame_type: :interframe, packet_type: :coded_frames, - fourcc: :avc1, + codec_id: :h264, composition_time_offset: -10, data: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 255>> }} @@ -57,7 +58,7 @@ defmodule ExFLV.Tag.ExVideoData do %ExFLV.Tag.ExVideoData{ frame_type: :interframe, packet_type: :coded_frames_x, - fourcc: :avc1, + codec_id: :h264, composition_time_offset: 0, data: <<1, 2, 3, 4>> }} @@ -72,13 +73,13 @@ defmodule ExFLV.Tag.ExVideoData do def parse(<<1::1, frame_type::3, packet_type::4, fourcc::binary-size(4), data::binary>>) when frame_type in 1..5 and packet_type in 0..7 and packet_type != 6 do packet_type = packet_type(packet_type) - fourcc = String.to_existing_atom(fourcc) - {composition_time_offset, data} = parse_body(packet_type, fourcc, data) + codec_id = codec_id(fourcc) + {composition_time_offset, data} = parse_body(packet_type, codec_id, data) {:ok, %__MODULE__{ frame_type: frame_type(frame_type), - fourcc: fourcc, + codec_id: codec_id, composition_time_offset: composition_time_offset, packet_type: packet_type, data: data @@ -94,7 +95,7 @@ defmodule ExFLV.Tag.ExVideoData do %ExFLV.Tag.ExVideoData{ frame_type: :keyframe, packet_type: :sequence_start, - fourcc: :hvc1, + codec_id: :h265, composition_time_offset: 0, data: <<1, 2, 3, 4, 5>> } @@ -107,11 +108,17 @@ defmodule ExFLV.Tag.ExVideoData do end end - defp parse_body(:coded_frames, fourcc, <>) - when fourcc in [:avc1, :hvc1], + defp parse_body(:coded_frames, codec, <>) + when codec in [:h264, :h265], do: {composition_time_offset, data} - defp parse_body(_packet_type, _fourcc, data), do: {0, data} + defp parse_body(_packet_type, _codec, data), do: {0, data} + + defp codec_id("avc1"), do: :h264 + defp codec_id("hvc1"), do: :h265 + defp codec_id("vp08"), do: :vp8 + defp codec_id("vp09"), do: :vp9 + defp codec_id("av01"), do: :av1 defp packet_type(0), do: :sequence_start defp packet_type(1), do: :coded_frames @@ -140,11 +147,17 @@ defmodule ExFLV.Tag.ExVideoData do [ <<1::1, frame_type(video_data.frame_type)::3, packet_type(video_data.packet_type)::4, - to_string(video_data.fourcc)::binary-size(4), composition_time::binary>>, + fourcc(video_data.codec_id)::binary-size(4), composition_time::binary>>, video_data.data ] end + defp fourcc(:h264), do: "avc1" + defp fourcc(:h265), do: "hvc1" + defp fourcc(:vp8), do: "vp08" + defp fourcc(:vp9), do: "vp09" + defp fourcc(:av1), do: "av01" + defp frame_type(:keyframe), do: 1 defp frame_type(:interframe), do: 2 defp frame_type(:disposable_interframe), do: 3 diff --git a/lib/ex_flv/tag/video_data.ex b/lib/ex_flv/tag/video_data.ex index 03bd5b9..3b7f9a3 100644 --- a/lib/ex_flv/tag/video_data.ex +++ b/lib/ex_flv/tag/video_data.ex @@ -91,10 +91,10 @@ defmodule ExFLV.Tag.VideoData do defp parse_codec_id(4), do: :vp6 defp parse_codec_id(5), do: :vp6_alpha defp parse_codec_id(6), do: :screen_video_v2 - defp parse_codec_id(7), do: :avc + defp parse_codec_id(7), do: :h264 defp parse_codec_id(_), do: :unknown - defp parse_payload(:avc, data), do: AVC.parse(data) + defp parse_payload(:h264, data), do: AVC.parse(data) defp parse_payload(_, data), do: {:ok, data} defimpl ExFLV.Tag.Serializer do @@ -120,7 +120,7 @@ defmodule ExFLV.Tag.VideoData do defp serialize_codec_id(:vp6), do: 4 defp serialize_codec_id(:vp6_alpha), do: 5 defp serialize_codec_id(:screen_video_v2), do: 6 - defp serialize_codec_id(:avc), do: 7 + defp serialize_codec_id(:h264), do: 7 defp serialize_data(%AVC{} = data), do: Serializer.serialize(data) defp serialize_data(data), do: data diff --git a/test/ex_flv/reader_test.exs b/test/ex_flv/reader_test.exs index 327177d..e2595b2 100644 --- a/test/ex_flv/reader_test.exs +++ b/test/ex_flv/reader_test.exs @@ -35,7 +35,7 @@ defmodule ExFLV.ReaderTest do assert Enum.all?(tags, fn %{type: :audio} = tag -> tag.data.sound_format == :aac - %{type: :video} = tag -> tag.data.codec_id == :avc + %{type: :video} = tag -> tag.data.codec_id == :h264 end) end diff --git a/test/ex_flv/tag/ex_audio_data_test.exs b/test/ex_flv/tag/ex_audio_data_test.exs index 9ef8b9f..273d17c 100644 --- a/test/ex_flv/tag/ex_audio_data_test.exs +++ b/test/ex_flv/tag/ex_audio_data_test.exs @@ -9,7 +9,7 @@ defmodule ExFLV.Tag.ExAudioDataTest do setup do audio_data = %ExFLV.Tag.ExAudioData{ packet_type: :multi_channel_config, - fourcc: :flac, + codec_id: :flac, channel_order: :native, channel_count: 2, channels: [:front_left, :front_right], @@ -35,7 +35,7 @@ defmodule ExFLV.Tag.ExAudioDataTest do audio_data = %ExAudioData{ packet_type: :coded_frames, - fourcc: :mp3, + codec_id: :mp3, data: <<1, 2, 3, 4, 5>> } @@ -45,7 +45,7 @@ defmodule ExFLV.Tag.ExAudioDataTest do audio_data = %ExAudioData{ packet_type: :multi_channel_config, - fourcc: :flac, + codec_id: :flac, channel_order: :custom, channel_count: 4, channels: [:front_left, :front_right, :back_left, :back_right], diff --git a/test/ex_flv/tag/ex_video_data_test.exs b/test/ex_flv/tag/ex_video_data_test.exs index f566165..066add4 100644 --- a/test/ex_flv/tag/ex_video_data_test.exs +++ b/test/ex_flv/tag/ex_video_data_test.exs @@ -18,7 +18,7 @@ defmodule ExFLV.Tag.ExVideoDataTest do video_data = %ExVideoData{ frame_type: :interframe, packet_type: :coded_frames, - fourcc: :avc1, + codec_id: :h264, composition_time_offset: -10, data: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 255>> } diff --git a/test/ex_flv/tag_test.exs b/test/ex_flv/tag_test.exs index 0a2da76..bdcb61d 100644 --- a/test/ex_flv/tag_test.exs +++ b/test/ex_flv/tag_test.exs @@ -29,7 +29,7 @@ defmodule ExFLV.TagTest do data = @video_data |> AVC.new(:nalu, 0) - |> VideoData.new(:avc, :interframe) + |> VideoData.new(:h264, :interframe) tag = %ExFLV.Tag{type: :video, timestamp: 1_000, data: data} serialized = ExFLV.Tag.serialize(tag) From bbd744b7619436e0055923ee89f1a4d25c1703d3 Mon Sep 17 00:00:00 2001 From: Billal GHILAS Date: Thu, 8 Jan 2026 18:28:17 +0100 Subject: [PATCH 2/2] Bump version --- README.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 920eff6..caabb6e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ The package can be installed by adding `ex_flv` to your list of dependencies in ```elixir def deps do [ - {:ex_flv, "~> 0.3.0"} + {:ex_flv, "~> 0.4.0"} ] end ``` diff --git a/mix.exs b/mix.exs index 536140e..e613e27 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule ExFLV.MixProject do use Mix.Project - @version "0.3.0" + @version "0.4.0" @github_url "https://github.com/elixir-streaming/ex_flv" def project do