Skip to content
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
11 changes: 6 additions & 5 deletions lib/ex_flv/tag/audio_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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,
Expand Down
25 changes: 13 additions & 12 deletions lib/ex_flv/tag/ex_audio_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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 ::
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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],
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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],
Expand Down Expand Up @@ -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
Expand Down
41 changes: 27 additions & 14 deletions lib/ex_flv/tag/ex_video_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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>>
}}
Expand All @@ -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>>
}}
Expand All @@ -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>>
}}
Expand All @@ -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
Expand All @@ -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>>
}
Expand All @@ -107,11 +108,17 @@ defmodule ExFLV.Tag.ExVideoData do
end
end

defp parse_body(:coded_frames, fourcc, <<composition_time_offset::24-signed, data::binary>>)
when fourcc in [:avc1, :hvc1],
defp parse_body(:coded_frames, codec, <<composition_time_offset::24-signed, data::binary>>)
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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions lib/ex_flv/tag/video_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
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 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
Expand Down
2 changes: 1 addition & 1 deletion test/ex_flv/reader_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions test/ex_flv/tag/ex_audio_data_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand All @@ -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>>
}

Expand All @@ -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],
Expand Down
2 changes: 1 addition & 1 deletion test/ex_flv/tag/ex_video_data_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>
}
Expand Down
2 changes: 1 addition & 1 deletion test/ex_flv/tag_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down