From 366e8fbcf5052cdce34c6ff1de4383720a3130ce Mon Sep 17 00:00:00 2001 From: Leandro Moreira Date: Sun, 19 May 2024 19:16:24 -0300 Subject: [PATCH] move filters and add codec context setters --- .../engine/donut_engine_controller.go | 12 ++++++-- .../controllers/streamers/libav_ffmpeg.go | 15 ++++++---- internal/entities/entities.go | 28 +++++++++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/internal/controllers/engine/donut_engine_controller.go b/internal/controllers/engine/donut_engine_controller.go index da1511a..82c2d40 100644 --- a/internal/controllers/engine/donut_engine_controller.go +++ b/internal/controllers/engine/donut_engine_controller.go @@ -114,14 +114,20 @@ func (d *donutEngine) RecipeFor(server, client *entities.StreamInfo) (*entities. r := &entities.DonutRecipe{ Input: appetizer, Video: entities.DonutMediaTask{ + // Action: entities.DonutTranscode, Action: entities.DonutBypass, Codec: entities.H264, DonutBitStreamFilter: &entities.DonutH264AnnexB, + // CodecContextOptions: []entities.LibAVOptionsCodecContext{ + // entities.SetBitRate(100_000), + // entities.SetBaselineProfile(), + // entities.SetGopSize(30), + // }, }, Audio: entities.DonutMediaTask{ - Action: entities.DonutTranscode, - Codec: entities.Opus, - // TODO: create method list options per Codec + Action: entities.DonutTranscode, + Codec: entities.Opus, + DonutStreamFilter: entities.AudioResamplerFilter(48000), CodecContextOptions: []entities.LibAVOptionsCodecContext{ entities.SetSampleRate(48000), entities.SetSampleFormat("fltp"), diff --git a/internal/controllers/streamers/libav_ffmpeg.go b/internal/controllers/streamers/libav_ffmpeg.go index cfbc676..7599fd2 100644 --- a/internal/controllers/streamers/libav_ffmpeg.go +++ b/internal/controllers/streamers/libav_ffmpeg.go @@ -391,10 +391,11 @@ func (c *LibAVFFmpegStreamer) prepareFilters(p *libAVParams, closer *astikit.Clo } buffersrc = astiav.FindFilterByName("abuffer") buffersink = astiav.FindFilterByName("abuffersink") - content = fmt.Sprintf( - "aresample=%s", // necessary for opus - strconv.Itoa(s.encCodecContext.SampleRate()), - ) + if donut.Recipe.Audio.DonutStreamFilter != nil { + content = string(*donut.Recipe.Audio.DonutStreamFilter) + } else { + content = "anull" /* passthrough (dummy) filter for audio */ + } } if isVideo { @@ -406,7 +407,11 @@ func (c *LibAVFFmpegStreamer) prepareFilters(p *libAVParams, closer *astikit.Clo } buffersrc = astiav.FindFilterByName("buffer") buffersink = astiav.FindFilterByName("buffersink") - content = fmt.Sprintf("format=pix_fmts=%s", s.encCodecContext.PixelFormat().Name()) + if donut.Recipe.Video.DonutStreamFilter != nil { + content = string(*donut.Recipe.Video.DonutStreamFilter) + } else { + content = "null" /* passthrough (dummy) filter for video */ + } } if buffersrc == nil { diff --git a/internal/entities/entities.go b/internal/entities/entities.go index c31566d..f89cf49 100644 --- a/internal/entities/entities.go +++ b/internal/entities/entities.go @@ -156,6 +156,13 @@ type DonutBitStreamFilter string var DonutH264AnnexB DonutBitStreamFilter = "h264_mp4toannexb" +type DonutStreamFilter string + +func AudioResamplerFilter(sampleRate int) *DonutStreamFilter { + filter := DonutStreamFilter(fmt.Sprintf("aresample=%d", sampleRate)) + return &filter +} + // TODO: split entities per domain or files avoiding name collision. // DonutMediaTask is a transformation template to apply over a media. @@ -171,6 +178,9 @@ type DonutMediaTask struct { // DonutBitStreamFilter is the bitstream filter DonutBitStreamFilter *DonutBitStreamFilter + + // DonutStreamFilter is a regular filter + DonutStreamFilter *DonutStreamFilter } type DonutInputOptionKey string @@ -220,6 +230,24 @@ func SetTimeBase(num, den int) LibAVOptionsCodecContext { } } +func SetBitRate(bitRate int64) LibAVOptionsCodecContext { + return func(c *astiav.CodecContext) { + c.SetBitRate(bitRate) + } +} + +func SetBaselineProfile() LibAVOptionsCodecContext { + return func(c *astiav.CodecContext) { + c.SetProfile(astiav.ProfileH264Baseline) + } +} + +func SetGopSize(gopSize int) LibAVOptionsCodecContext { + return func(c *astiav.CodecContext) { + c.SetGopSize(gopSize) + } +} + // SetSampleFormat sets sample format, // CAUTION it only contains partial list of fmt // TODO: move it to mappers