From 5778c96185cb31d60998151d225611da815d0ce4 Mon Sep 17 00:00:00 2001 From: noarkhh Date: Wed, 3 Jul 2024 16:28:49 +0200 Subject: [PATCH] Add encoding deadline calculation --- lib/membrane_vpx/encoder/vp8_encoder.ex | 7 +++--- lib/membrane_vpx/encoder/vp9_encoder.ex | 7 +++--- lib/membrane_vpx/encoder/vpx_encoder.ex | 33 ++++++++++++++++--------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/lib/membrane_vpx/encoder/vp8_encoder.ex b/lib/membrane_vpx/encoder/vp8_encoder.ex index 6d354df..f4b1661 100644 --- a/lib/membrane_vpx/encoder/vp8_encoder.ex +++ b/lib/membrane_vpx/encoder/vp8_encoder.ex @@ -7,14 +7,15 @@ defmodule Membrane.VP8.Encoder do alias Membrane.{VP8, VPx} def_options encoding_deadline: [ - spec: Membrane.Time.t(), - default: Membrane.Time.microsecond(), - inspector: &Membrane.Time.inspect/1, + spec: Membrane.Time.t() | :auto, + default: :auto, description: """ Determines how long should it take the encoder to encode a frame. The longer the encoding takes the better the quality will be. If set to 0 the encoder will take as long as it needs to produce the best frame possible. Note that this is a soft limit, there is no guarantee that the encoding process will never exceed it. + If set to `:auto` the deadline will be calculated based on the framerate provided by + incoming stream format. If it's `nil` a fixed deadline of 10ms will be set. """ ] diff --git a/lib/membrane_vpx/encoder/vp9_encoder.ex b/lib/membrane_vpx/encoder/vp9_encoder.ex index d71dcc0..0763c22 100644 --- a/lib/membrane_vpx/encoder/vp9_encoder.ex +++ b/lib/membrane_vpx/encoder/vp9_encoder.ex @@ -7,14 +7,15 @@ defmodule Membrane.VP9.Encoder do alias Membrane.{VP9, VPx} def_options encoding_deadline: [ - spec: Membrane.Time.t(), - default: Membrane.Time.microsecond(), - inspector: &Membrane.Time.inspect/1, + spec: Membrane.Time.t() | :auto, + default: :auto, description: """ Determines how long should it take the encoder to encode a frame. The longer the encoding takes the better the quality will be. If set to 0 the encoder will take as long as it needs to produce the best frame possible. Note that this is a soft limit, there is no guarantee that the encoding process will never exceed it. + If set to `:auto` the deadline will be calculated based on the framerate provided by + incoming stream format. If it's `nil` a fixed deadline of 10ms will be set. """ ] diff --git a/lib/membrane_vpx/encoder/vpx_encoder.ex b/lib/membrane_vpx/encoder/vpx_encoder.ex index 9bb7283..5b12123 100644 --- a/lib/membrane_vpx/encoder/vpx_encoder.ex +++ b/lib/membrane_vpx/encoder/vpx_encoder.ex @@ -5,6 +5,8 @@ defmodule Membrane.VPx.Encoder do alias Membrane.Element.CallbackContext alias Membrane.VPx.Encoder.Native + @default_encoding_deadline Membrane.Time.milliseconds(10) + defmodule State do @moduledoc false @@ -58,28 +60,35 @@ defmodule Membrane.VPx.Encoder do output_stream_format = struct(codec_module, width: width, height: height, framerate: framerate) - {buffers, native} = + encoding_deadline = + case {state.encoding_deadline, framerate} do + {:auto, nil} -> @default_encoding_deadline |> Membrane.Time.as_microseconds(:round) + {:auto, {num, denom}} -> div(denom * 1_000_000, num) + {fixed_deadline, _framerate} -> fixed_deadline |> Membrane.Time.as_microseconds(:round) + end + + {buffers, encoder_ref} = case ctx.pads.input.stream_format do - nil -> - native = - Native.create!(state.codec, width, height, pixel_format, state.encoding_deadline) + ^raw_video_format -> + {[], state.encoder_ref} - {[], native} + nil -> + encoder_ref = + Native.create!(state.codec, width, height, pixel_format, encoding_deadline) - %RawVideo{width: ^width, height: ^height, pixel_format: ^pixel_format} -> - {[], state.encoder_ref} + {[], encoder_ref} - _other_format -> + _changed_format -> buffers = flush(state.encoder_ref) - native = - Native.create!(state.codec, width, height, pixel_format, state.encoding_deadline) + encoder_ref = + Native.create!(state.codec, width, height, pixel_format, encoding_deadline) - {buffers, native} + {buffers, encoder_ref} end {[buffer: {:output, buffers}, stream_format: {:output, output_stream_format}], - %{state | encoder_ref: native}} + %{state | encoder_ref: encoder_ref}} end @spec handle_buffer(:input, Membrane.Buffer.t(), CallbackContext.t(), State.t()) ::