Compare commits
5 commits
6ea3e971bb
...
a14500af6a
Author | SHA1 | Date | |
---|---|---|---|
DataHoarder | a14500af6a | ||
DataHoarder | b8f21ea1f3 | ||
DataHoarder | 53fd0c93f2 | ||
DataHoarder | 9ae28eedaa | ||
DataHoarder | 6c20429b0d |
|
@ -68,8 +68,8 @@ steps:
|
|||
git clone --depth 1 --branch $AOM_TAG https://aomedia.googlesource.com/aom.git && cd aom &&
|
||||
mkdir b && cd b &&
|
||||
cmake .. -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -D CMAKE_INSTALL_PREFIX:PATH=/drone/src/build_deps
|
||||
-DENABLE_DOCS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_TESTS=OFF -DENABLE_CCACHE=ON -DCONFIG_FRAME_PARALLEL_ENCODE=1 -DCONFIG_AV1_TEMPORAL_DENOISING=1
|
||||
-DCONFIG_BITRATE_ACCURACY=1 -DCONFIG_TUNE_VMAF=1 -DCONFIG_NN_V2=1 -DCONFIG_RT_ML_PARTITIONING=1 -DCONFIG_THREE_PASS=0 -DCONFIG_AV1_ENCODER=1 -DCONFIG_AV1_DECODER=1 &&
|
||||
-DENABLE_DOCS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_TESTS=OFF -DENABLE_CCACHE=ON
|
||||
-DCONFIG_TUNE_VMAF=1 -DCONFIG_THREE_PASS=0 -DCONFIG_AV1_ENCODER=1 -DCONFIG_AV1_DECODER=1 &&
|
||||
make -j$(nproc) &&
|
||||
make install &&
|
||||
cd ../..
|
||||
|
@ -226,8 +226,8 @@ steps:
|
|||
git clone --depth 1 --branch $AOM_TAG https://aomedia.googlesource.com/aom.git && cd aom &&
|
||||
mkdir b && cd b &&
|
||||
cmake .. -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -D CMAKE_INSTALL_PREFIX:PATH=/drone/src/build_deps
|
||||
-DENABLE_DOCS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_TESTS=OFF -DENABLE_CCACHE=ON -DCONFIG_FRAME_PARALLEL_ENCODE=1 -DCONFIG_AV1_TEMPORAL_DENOISING=1
|
||||
-DCONFIG_BITRATE_ACCURACY=1 -DCONFIG_TUNE_VMAF=1 -DCONFIG_NN_V2=1 -DCONFIG_RT_ML_PARTITIONING=1 -DCONFIG_THREE_PASS=0 -DCONFIG_AV1_ENCODER=1 -DCONFIG_AV1_DECODER=1 &&
|
||||
-DENABLE_DOCS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_TESTS=OFF -DENABLE_CCACHE=ON
|
||||
-DCONFIG_TUNE_VMAF=1 -DCONFIG_THREE_PASS=0 -DCONFIG_AV1_ENCODER=1 -DCONFIG_AV1_DECODER=1 &&
|
||||
make -j$(nproc) &&
|
||||
make install &&
|
||||
cd ../..
|
||||
|
|
|
@ -31,8 +31,8 @@ RUN git clone --depth 1 --branch "${VMAF_TAG}" https://github.com/Netflix/vmaf.g
|
|||
RUN git clone --depth 1 --branch "${AOM_TAG}" https://aomedia.googlesource.com/aom.git /tmp/aom && cd /tmp/aom && \
|
||||
mkdir b && cd b && \
|
||||
cmake .. -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -D CMAKE_INSTALL_PREFIX:PATH=/usr \
|
||||
-DENABLE_DOCS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_TESTS=OFF -DENABLE_CCACHE=ON -DCONFIG_FRAME_PARALLEL_ENCODE=1 -DCONFIG_AV1_TEMPORAL_DENOISING=1 \
|
||||
-DCONFIG_BITRATE_ACCURACY=1 -DCONFIG_TUNE_VMAF=1 -DCONFIG_NN_V2=1 -DCONFIG_RT_ML_PARTITIONING=1 -DCONFIG_THREE_PASS=0 -DCONFIG_AV1_ENCODER=1 -DCONFIG_AV1_DECODER=1 && \
|
||||
-DENABLE_DOCS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_TESTS=OFF -DENABLE_CCACHE=ON \
|
||||
-DCONFIG_TUNE_VMAF=1 -DCONFIG_THREE_PASS=0 -DCONFIG_AV1_ENCODER=1 -DCONFIG_AV1_DECODER=1 && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd / && \
|
||||
|
@ -53,7 +53,7 @@ ENV GOPROXY=${GOPROXY}
|
|||
COPY go.mod go.sum ./
|
||||
RUN go mod download -x && go mod verify
|
||||
|
||||
COPY . .
|
||||
COPY .. .
|
||||
|
||||
RUN go build -v -ldflags '-linkmode external -extldflags "-Wl,-z,stack-size=2097152 -fno-PIC -static -lstdc++"' -buildmode pie -tags 'osusergo netgo static_build' \
|
||||
-o /usr/bin/ git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-libaom git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-server
|
66
build/debian-shared/Dockerfile
Normal file
66
build/debian-shared/Dockerfile
Normal file
|
@ -0,0 +1,66 @@
|
|||
FROM golang:1.21-bookworm AS builder
|
||||
|
||||
ENV CFLAGS="-march=native -Ofast"
|
||||
ENV CXXFLAGS="-march=native -Ofast"
|
||||
ENV CGO_CFLAGS="-march=native -Ofast"
|
||||
|
||||
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends \
|
||||
git gcc g++ musl-dev bash nasm autoconf automake cmake make libtool gettext pkg-config meson ccache perl xxd && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/lib64/pkgconfig
|
||||
|
||||
ARG X264_TAG="stable"
|
||||
RUN git clone --depth 1 --branch "${X264_TAG}" https://code.videolan.org/videolan/x264.git /tmp/x264 && cd /tmp/x264 && \
|
||||
./configure --disable-cli --disable-ffms --disable-lavf --disable-swscale --enable-shared --bit-depth=all --chroma-format=all --enable-lto --enable-pic --disable-opencl --prefix=/usr && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd / && \
|
||||
rm -rf /tmp/x264
|
||||
|
||||
ARG VMAF_TAG="v2.3.1"
|
||||
RUN git clone --depth 1 --branch "${VMAF_TAG}" https://github.com/Netflix/vmaf.git /tmp/vmaf && cd /tmp/vmaf/libvmaf && \
|
||||
meson setup build . --prefix /usr --buildtype release --default-library=static \
|
||||
-Denable_float=true -Dbuilt_in_models=true -Denable_tests=false -Denable_docs=false && \
|
||||
ninja -vC build && \
|
||||
ninja -vC build install && \
|
||||
cd / && \
|
||||
rm -rf /tmp/vmaf
|
||||
|
||||
ARG DAV1D_TAG="1.3.0"
|
||||
RUN git clone --depth 1 --branch "${DAV1D_TAG}" https://code.videolan.org/videolan/dav1d.git /tmp/dav1d && cd /tmp/dav1d && \
|
||||
meson setup build . --prefix /usr --buildtype release --default-library=shared && \
|
||||
ninja -vC build && \
|
||||
ninja -vC build install && \
|
||||
cd / && \
|
||||
rm -rf /tmp/dav1d
|
||||
|
||||
ARG AOM_TAG="v3.7.0"
|
||||
RUN git clone --depth 1 --branch "${AOM_TAG}" https://aomedia.googlesource.com/aom.git /tmp/aom && cd /tmp/aom && \
|
||||
mkdir b && cd b && \
|
||||
cmake .. -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=ON -D CMAKE_INSTALL_PREFIX:PATH=/usr \
|
||||
-DENABLE_DOCS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_TESTS=OFF -DENABLE_CCACHE=ON \
|
||||
-DCONFIG_TUNE_VMAF=1 -DCONFIG_THREE_PASS=0 -DCONFIG_AV1_ENCODER=1 -DCONFIG_AV1_DECODER=1 && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd / && \
|
||||
rm -rf /tmp/aom
|
||||
|
||||
WORKDIR /usr/src/Ignite
|
||||
|
||||
ARG GOPROXY=""
|
||||
ENV GOPROXY=${GOPROXY}
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download -x && go mod verify
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN go build -v \
|
||||
-o /usr/bin/ git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-libaom git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-server
|
||||
RUN CGO_ENABLED=0 go build -v \
|
||||
-o /usr/bin/encode-pool git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-pool
|
||||
|
||||
WORKDIR /
|
71
build/debian/Dockerfile
Normal file
71
build/debian/Dockerfile
Normal file
|
@ -0,0 +1,71 @@
|
|||
FROM golang:1.21-bookworm AS builder
|
||||
|
||||
ENV CFLAGS="-march=native -Ofast"
|
||||
ENV CXXFLAGS="-march=native -Ofast"
|
||||
ENV LDFLAGS="-flto -static -static-libstdc++"
|
||||
ENV CGO_CFLAGS="-march=native -Ofast"
|
||||
|
||||
ARG X264_TAG="stable"
|
||||
ARG VMAF_TAG="v2.3.1"
|
||||
ARG AOM_TAG="v3.7.0"
|
||||
ARG DAV1D_TAG="1.3.0"
|
||||
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends \
|
||||
git gcc g++ musl-dev bash nasm autoconf automake cmake make libtool gettext pkg-config meson ccache perl xxd && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/lib64/pkgconfig
|
||||
|
||||
RUN git clone --depth 1 --branch "${X264_TAG}" https://code.videolan.org/videolan/x264.git /tmp/x264 && cd /tmp/x264 && \
|
||||
./configure --disable-cli --disable-ffms --disable-lavf --disable-swscale --enable-static --bit-depth=all --chroma-format=all --enable-lto --enable-pic --disable-opencl --prefix=/usr && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd / && \
|
||||
rm -rf /tmp/x264
|
||||
|
||||
RUN git clone --depth 1 --branch "${VMAF_TAG}" https://github.com/Netflix/vmaf.git /tmp/vmaf && cd /tmp/vmaf/libvmaf && \
|
||||
meson setup build . --prefix /usr --buildtype release --default-library=static \
|
||||
-Denable_float=true -Dbuilt_in_models=true -Denable_tests=false -Denable_docs=false && \
|
||||
ninja -vC build && \
|
||||
ninja -vC build install && \
|
||||
cd / && \
|
||||
rm -rf /tmp/vmaf
|
||||
|
||||
RUN git clone --depth 1 --branch "${AOM_TAG}" https://aomedia.googlesource.com/aom.git /tmp/aom && cd /tmp/aom && \
|
||||
mkdir b && cd b && \
|
||||
cmake .. -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -D CMAKE_INSTALL_PREFIX:PATH=/usr \
|
||||
-DENABLE_DOCS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_TESTS=OFF -DENABLE_CCACHE=ON \
|
||||
-DCONFIG_TUNE_VMAF=1 -DCONFIG_THREE_PASS=0 -DCONFIG_AV1_ENCODER=1 -DCONFIG_AV1_DECODER=1 && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd / && \
|
||||
rm -rf /tmp/aom
|
||||
|
||||
RUN git clone --depth 1 --branch "${DAV1D_TAG}" https://code.videolan.org/videolan/dav1d.git /tmp/dav1d && cd /tmp/dav1d && \
|
||||
meson setup build . --prefix /usr --buildtype release --default-library=static && \
|
||||
ninja -vC build && \
|
||||
ninja -vC build install && \
|
||||
cd / && \
|
||||
rm -rf /tmp/dav1d
|
||||
|
||||
WORKDIR /usr/src/Ignite
|
||||
|
||||
ARG GOPROXY=""
|
||||
ENV GOPROXY=${GOPROXY}
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download -x && go mod verify
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN go build -v -ldflags '-linkmode external -extldflags "-fno-PIC -static -lstdc++"' -buildmode pie -tags 'osusergo netgo static_build' \
|
||||
-o /usr/bin/ git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-libaom git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-server
|
||||
RUN CGO_ENABLED=0 go build -v -tags 'osusergo netgo static_build' \
|
||||
-o /usr/bin/encode-pool git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-pool
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
COPY --from=builder /usr/bin/encode-* /usr/bin/
|
||||
|
||||
WORKDIR /
|
|
@ -251,7 +251,7 @@ func main() {
|
|||
|
||||
stream := frameServerPool.GetFrames(startFrameNumber, endFrameNumber)
|
||||
|
||||
if encoder, err := libaom.NewEncoder(f, stream.Properties(), settings); err != nil {
|
||||
if encoder, err := libaom.NewEncoder(f, stream.Properties(), settings, log.Default()); err != nil {
|
||||
log.Panicf("could not create encoder for %s: %s", outputPath, err.Error())
|
||||
} else {
|
||||
defer encoder.Close()
|
||||
|
|
20
cli/encode-server/decoder_dav1d.go
Normal file
20
cli/encode-server/decoder_dav1d.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
//go:build cgo && !disable_library_libdav1d
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/decoder"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/decoder/libdav1d"
|
||||
"io"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Decoders = append(Decoders, DecoderEntry{
|
||||
Name: DecoderDav1d,
|
||||
Version: libdav1d.Version,
|
||||
MimeType: "video/x-ivf",
|
||||
New: func(w io.Reader, settings map[string]any) (decoder.Decoder, error) {
|
||||
return libdav1d.NewDecoder(w, settings)
|
||||
},
|
||||
})
|
||||
}
|
20
cli/encode-server/decoder_y4m.go
Normal file
20
cli/encode-server/decoder_y4m.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/decoder"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/decoder/y4m"
|
||||
"io"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Decoders = append(Decoders, DecoderEntry{
|
||||
Name: DecoderY4M,
|
||||
Version: func() string {
|
||||
return "1.0"
|
||||
},
|
||||
MimeType: "video/x-yuv4mpeg2",
|
||||
New: func(w io.Reader, settings map[string]any) (decoder.Decoder, error) {
|
||||
return y4m.NewDecoder(w, settings)
|
||||
},
|
||||
})
|
||||
}
|
38
cli/encode-server/decoders.go
Normal file
38
cli/encode-server/decoders.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/decoder"
|
||||
"io"
|
||||
"slices"
|
||||
)
|
||||
|
||||
const (
|
||||
DecoderY4M = "y4m"
|
||||
DecoderDav1d = "libdav1d"
|
||||
)
|
||||
|
||||
type DecoderEntry struct {
|
||||
Name string
|
||||
Version func() string
|
||||
MimeType string
|
||||
New func(w io.Reader, settings map[string]any) (decoder.Decoder, error)
|
||||
}
|
||||
|
||||
var Decoders []DecoderEntry
|
||||
|
||||
func GetDecoderByName(name string) *DecoderEntry {
|
||||
if i := slices.IndexFunc(Decoders, func(entry DecoderEntry) bool {
|
||||
return entry.Name == name
|
||||
}); i != -1 {
|
||||
return &Decoders[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func GetDecoderByMimeType(mimeType string) *DecoderEntry {
|
||||
if i := slices.IndexFunc(Decoders, func(entry DecoderEntry) bool {
|
||||
return entry.MimeType == mimeType
|
||||
}); i != -1 {
|
||||
return &Decoders[i]
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
//go:build cgo && !disable_library_libaom && !disable_library_libx264
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -8,7 +6,6 @@ import (
|
|||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/decoder/y4m"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/frame"
|
||||
"github.com/ulikunitz/xz"
|
||||
"io"
|
||||
|
@ -44,8 +41,15 @@ func handleDecompress(contentEncoding string, reader io.ReadCloser) (io.ReadClos
|
|||
return reader, nil
|
||||
}
|
||||
|
||||
func encodeFromReader(reader io.ReadCloser, job *Job, w http.ResponseWriter) {
|
||||
func encodeFromReader(reader io.ReadCloser, job *Job, inputMimeType string, w http.ResponseWriter) {
|
||||
defer reader.Close()
|
||||
|
||||
d := GetDecoderByMimeType(inputMimeType)
|
||||
if d == nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
log.Printf("[job %s] finished, took %s", job.Id, time.Now().Sub(time.Unix(int64(job.Status.Start.Load()), 0)))
|
||||
}()
|
||||
|
@ -60,7 +64,7 @@ func encodeFromReader(reader io.ReadCloser, job *Job, w http.ResponseWriter) {
|
|||
settings["timecodes"] = job.Config.Timecodes
|
||||
}
|
||||
|
||||
decoder, err := y4m.NewDecoder(reader, settings)
|
||||
decoder, err := d.New(reader, settings)
|
||||
if err != nil {
|
||||
w.Header().Set("x-encoder-error", "")
|
||||
w.Header().Set("x-decoder-error", err.Error())
|
||||
|
@ -81,7 +85,12 @@ func encodeFromReader(reader io.ReadCloser, job *Job, w http.ResponseWriter) {
|
|||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
mimeType := "application/octet-stream"
|
||||
if e := GetEncoder(job.Config.Encoder.Name); e != nil {
|
||||
mimeType = e.MimeType
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", mimeType)
|
||||
w.Header().Add("Trailer", "x-encoder-error, x-decoder-error")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
job.Logger = log.New(os.Stderr, fmt.Sprintf("[job %s] ", job.Id), log.LstdFlags)
|
||||
|
|
22
cli/encode-server/encoder_libaom.go
Normal file
22
cli/encode-server/encoder_libaom.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
//go:build cgo && !disable_library_libaom
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder/libaom"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/frame"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/utilities"
|
||||
"io"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Encoders = append(Encoders, EncoderEntry{
|
||||
Name: EncoderAOM,
|
||||
Version: libaom.Version,
|
||||
MimeType: "video/x-ivf",
|
||||
New: func(w io.Writer, properties frame.StreamProperties, settings map[string]any, logger utilities.Logger) (encoder.Encoder, error) {
|
||||
return libaom.NewEncoder(w, properties, settings, logger)
|
||||
},
|
||||
})
|
||||
}
|
22
cli/encode-server/encoder_libx264.go
Normal file
22
cli/encode-server/encoder_libx264.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
//go:build cgo && !disable_library_libx264
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder/libx264"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/frame"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/utilities"
|
||||
"io"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Encoders = append(Encoders, EncoderEntry{
|
||||
Name: EncoderX264,
|
||||
Version: libx264.Version,
|
||||
MimeType: "video/h264",
|
||||
New: func(w io.Writer, properties frame.StreamProperties, settings map[string]any, logger utilities.Logger) (encoder.Encoder, error) {
|
||||
return libx264.NewEncoder(w, properties, settings, logger)
|
||||
},
|
||||
})
|
||||
}
|
32
cli/encode-server/encoders.go
Normal file
32
cli/encode-server/encoders.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/frame"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/utilities"
|
||||
"io"
|
||||
"slices"
|
||||
)
|
||||
|
||||
const (
|
||||
EncoderX264 = "libx264"
|
||||
EncoderAOM = "libaom"
|
||||
)
|
||||
|
||||
type EncoderEntry struct {
|
||||
Name string
|
||||
Version func() string
|
||||
MimeType string
|
||||
New func(w io.Writer, properties frame.StreamProperties, settings map[string]any, logger utilities.Logger) (encoder.Encoder, error)
|
||||
}
|
||||
|
||||
var Encoders []EncoderEntry
|
||||
|
||||
func GetEncoder(name string) *EncoderEntry {
|
||||
if i := slices.IndexFunc(Encoders, func(entry EncoderEntry) bool {
|
||||
return entry.Name == name
|
||||
}); i != -1 {
|
||||
return &Encoders[i]
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
//go:build cgo && !disable_library_libaom && !disable_library_libx264
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -8,8 +6,6 @@ import (
|
|||
"errors"
|
||||
encode_utils "git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-utils"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder/libaom"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder/libx264"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/utilities"
|
||||
"io"
|
||||
"maps"
|
||||
|
@ -45,20 +41,18 @@ func (j *Job) Init(w io.Writer) error {
|
|||
// Do not modify original settings
|
||||
settings := maps.Clone(j.Config.Encoder.Settings)
|
||||
|
||||
switch j.Config.Encoder.Name {
|
||||
case encode_utils.EncoderX264:
|
||||
x264enc, err := libx264.NewEncoder(w, j.Config.Properties, settings, j.Logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
j.Encoder = x264enc
|
||||
case encode_utils.EncoderAOM:
|
||||
aomenc, err := libaom.NewEncoder(w, j.Config.Properties, settings)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
j.Encoder = aomenc
|
||||
default:
|
||||
var err error
|
||||
|
||||
if e := GetEncoder(j.Config.Encoder.Name); e == nil {
|
||||
return errors.New("encoder not found")
|
||||
} else {
|
||||
j.Encoder, err = e.New(w, j.Config.Properties, settings, j.Logger)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if j.Encoder == nil {
|
||||
return errors.New("encoder not supported")
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
//go:build cgo && !disable_library_libaom && !disable_library_libx264
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
encode_utils "git.gammaspectra.live/S.O.N.G/Ignite/cli/encode-utils"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder/libaom"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/encoder/libx264"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/utilities"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
|
@ -52,14 +48,12 @@ func main() {
|
|||
|
||||
var statusData encode_utils.StatusData
|
||||
|
||||
statusData.Encoders = append(statusData.Encoders, encode_utils.StatusEncoderData{
|
||||
Name: encode_utils.EncoderX264,
|
||||
Version: libx264.Version(),
|
||||
})
|
||||
statusData.Encoders = append(statusData.Encoders, encode_utils.StatusEncoderData{
|
||||
Name: encode_utils.EncoderAOM,
|
||||
Version: libaom.Version(),
|
||||
})
|
||||
for _, e := range Encoders {
|
||||
statusData.Encoders = append(statusData.Encoders, encode_utils.StatusEncoderData{
|
||||
Name: e.Name,
|
||||
Version: e.Version(),
|
||||
})
|
||||
}
|
||||
|
||||
cpuInfo, err := cpu.Info()
|
||||
if err != nil {
|
||||
|
@ -200,11 +194,6 @@ func main() {
|
|||
}
|
||||
defer job.Unlock()
|
||||
|
||||
if r.Header.Get("Content-Type") != "video/x-yuv4mpeg2" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
reader, err := handleDecompress(r.Header.Get("Content-Encoding"), r.Body)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
|
@ -214,7 +203,7 @@ func main() {
|
|||
defer r.Body.Close()
|
||||
|
||||
log.Printf("[job %s] started POST", job.Id)
|
||||
encodeFromReader(reader, job, w)
|
||||
encodeFromReader(reader, job, r.Header.Get("Content-Type"), w)
|
||||
})
|
||||
|
||||
serveMux.HandleFunc("/startURL", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -276,21 +265,21 @@ func main() {
|
|||
|
||||
// Handle filenames
|
||||
switch strings.ToLower(path.Ext(urlVal.Path)) {
|
||||
case "gz":
|
||||
case ".gz":
|
||||
reader, err = handleDecompress("gz", reader)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
case "bz2", "bzip2":
|
||||
case ".bz2", ".bzip2":
|
||||
reader, err = handleDecompress("bz2", reader)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
case "xz":
|
||||
case ".xz":
|
||||
reader, err = handleDecompress("xz", reader)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
|
@ -299,8 +288,19 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
fname := strings.TrimSuffix(urlVal.Path, path.Ext(urlVal.Path))
|
||||
inputMimeType := response.Header.Get("Content-Type")
|
||||
switch strings.ToLower(path.Ext(fname)) {
|
||||
case ".y4m":
|
||||
inputMimeType = "video/x-yuv4mpeg2"
|
||||
case ".av1":
|
||||
inputMimeType = "video/x-ivf"
|
||||
case ".h264", ".x264":
|
||||
inputMimeType = "video/h264"
|
||||
}
|
||||
|
||||
log.Printf("[job %s] started URL", job.Id)
|
||||
encodeFromReader(reader, job, w)
|
||||
encodeFromReader(reader, job, inputMimeType, w)
|
||||
})
|
||||
|
||||
serveMux.HandleFunc("/job", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -16,8 +16,3 @@ type JobConfig struct {
|
|||
TimecodesV1 string `json:"timecodes_v1" yaml:"timecodes_v1"`
|
||||
Timecodes utilities.Timecodes `json:"timecodes" yaml:"timecodes"`
|
||||
}
|
||||
|
||||
const (
|
||||
EncoderX264 = "libx264"
|
||||
EncoderAOM = "libaom"
|
||||
)
|
||||
|
|
|
@ -5,6 +5,7 @@ import "git.gammaspectra.live/S.O.N.G/Ignite/frame"
|
|||
type Decoder interface {
|
||||
Decode() (frame.Frame, error)
|
||||
DecodeStream() *frame.Stream
|
||||
Properties() frame.StreamProperties
|
||||
Close()
|
||||
Version() string
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"fmt"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/color"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/frame"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/utilities"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/utilities/obuwriter"
|
||||
"golang.org/x/exp/constraints"
|
||||
"io"
|
||||
|
@ -19,6 +20,7 @@ import (
|
|||
"maps"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -33,6 +35,7 @@ type Encoder struct {
|
|||
framesIn, framesOut int
|
||||
frameStatistics frame.FrameStatistics
|
||||
resourcePinner runtime.Pinner
|
||||
logger utilities.Logger
|
||||
}
|
||||
|
||||
var libaomVersion = "libaom-av1 " + C.GoString(C.aom_codec_version_str()) + " ABI " + strconv.FormatUint(C.AOM_ENCODER_ABI_VERSION, 10)
|
||||
|
@ -47,9 +50,10 @@ const (
|
|||
UsageAllIntra = C.AOM_USAGE_ALL_INTRA
|
||||
)
|
||||
|
||||
func NewEncoder(w io.Writer, properties frame.StreamProperties, settings map[string]any) (*Encoder, error) {
|
||||
func NewEncoder(w io.Writer, properties frame.StreamProperties, settings map[string]any, logger utilities.Logger) (*Encoder, error) {
|
||||
e := &Encoder{
|
||||
frameStatistics: make(frame.FrameStatistics),
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
clonedSettings := maps.Clone(settings)
|
||||
|
@ -475,6 +479,7 @@ func (e *Encoder) encodeFrame(pts, nextPts int64, raw *C.aom_image_t) (pkts int,
|
|||
|
||||
var quant64 C.int
|
||||
if e.framesIn >= int(e.cfg.g_lag_in_frames) {
|
||||
//TODO: maybe call this on new packets?
|
||||
if aomErr = C.aom_codec_control_intptr(&e.codec, C.AOME_GET_LAST_QUANTIZER_64, &quant64); aomErr != C.AOM_CODEC_OK {
|
||||
return 0, errors.New("error getting LAST_QUANTIZER_64")
|
||||
}
|
||||
|
@ -505,12 +510,31 @@ func (e *Encoder) encodeFrame(pts, nextPts int64, raw *C.aom_image_t) (pkts int,
|
|||
e.frameStatistics[frame.FrameStatisticsKeyIsKeyFrame] = false
|
||||
e.frameStatistics[frame.FrameStatisticsKeyIsIntraFrame] = false
|
||||
|
||||
var flagStr []string
|
||||
if flags&C.AOM_FRAME_IS_KEY > 0 {
|
||||
e.frameStatistics[frame.FrameStatisticsKeyIsKeyFrame] = true
|
||||
flagStr = append(flagStr, "K-Frame")
|
||||
}
|
||||
if flags&C.AOM_FRAME_IS_DROPPABLE > 0 {
|
||||
flagStr = append(flagStr, "droppable")
|
||||
}
|
||||
if flags&C.AOM_FRAME_IS_INTRAONLY > 0 {
|
||||
e.frameStatistics[frame.FrameStatisticsKeyIsIntraFrame] = true
|
||||
flagStr = append(flagStr, "I-Frame")
|
||||
}
|
||||
if flags&C.AOM_FRAME_IS_SWITCH > 0 {
|
||||
flagStr = append(flagStr, "S-Frame")
|
||||
}
|
||||
if flags&C.AOM_FRAME_IS_ERROR_RESILIENT > 0 {
|
||||
flagStr = append(flagStr, "resilient")
|
||||
}
|
||||
if flags&C.AOM_FRAME_IS_DELAYED_RANDOM_ACCESS_POINT > 0 {
|
||||
//Forward keyframe
|
||||
e.frameStatistics[frame.FrameStatisticsKeyIsKeyFrame] = true
|
||||
flagStr = append(flagStr, "delayedrandom")
|
||||
}
|
||||
|
||||
e.logger.Printf("libaom: partition = %d, n = %d, pts = %d, quant64 = %d, bytes = %d, flags = %s", partitionId, e.framesOut, packetPts, quant64, len(buf), strings.Join(flagStr, ", "))
|
||||
if err = e.w.WriteFrameBytes(packetPts, buf); err != nil {
|
||||
return pkts, err
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ package libaom
|
|||
import (
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/decoder/y4m"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/testdata"
|
||||
"git.gammaspectra.live/S.O.N.G/Ignite/utilities/testingutils"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
@ -62,7 +63,7 @@ func testEncode(sample testdata.TestSample, t *testing.T) {
|
|||
settings["tile-columns"] = 1
|
||||
settings["tile-rows"] = 4
|
||||
|
||||
if encoder, err := NewEncoder(target, stream.Properties(), settings); err != nil {
|
||||
if encoder, err := NewEncoder(target, stream.Properties(), settings, testingutils.TestLogger(t)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
defer encoder.Close()
|
||||
|
|
Loading…
Reference in a new issue