Compare commits

...

5 commits

Author SHA1 Message Date
DataHoarder a14500af6a
Change libaom compile flags
Some checks are pending
continuous-integration/drone/push Build is running
2023-11-03 05:59:02 +01:00
DataHoarder b8f21ea1f3
Allow AV1 input on encode server 2023-11-03 05:56:47 +01:00
DataHoarder 53fd0c93f2
Changed Docker builds, add static and shared debian 2023-11-03 05:43:29 +01:00
DataHoarder 9ae28eedaa
Proper mime type for encode server 2023-11-03 05:43:04 +01:00
DataHoarder 6c20429b0d
encode-server properly uses build flags 2023-11-03 05:31:37 +01:00
18 changed files with 376 additions and 61 deletions

View file

@ -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 ../..

View file

@ -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

View 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
View 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 /

View file

@ -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()

View 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)
},
})
}

View 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)
},
})
}

View 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
}

View file

@ -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)

View 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)
},
})
}

View 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)
},
})
}

View 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
}

View file

@ -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")
}

View file

@ -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) {

View file

@ -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"
)

View file

@ -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
}

View file

@ -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
}

View file

@ -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()