~emersion/go-kdf

c6debf6e448cce6376ae88a4b5da0c9b1992e393 — Simon Ser 1 year, 4 months ago 79a7724
ffmpeg: add a few packed RGBA formats
1 files changed, 117 insertions(+), 0 deletions(-)

M ffmpeg/ffmpeg.go
M ffmpeg/ffmpeg.go => ffmpeg/ffmpeg.go +117 -0
@@ 4,6 4,7 @@ package ffmpeg

import (
	"git.sr.ht/~emersion/go-kdf"
	"git.sr.ht/~emersion/go-kdf/internal"
)

type Format int


@@ 12,6 13,122 @@ const FormatNone Format = -1

var FormatTable map[string]Format = formatTable

var channelMap = map[rune]kdf.Channel{
	'R': kdf.ChannelRGBSDA_R,
	'G': kdf.ChannelRGBSDA_G,
	'B': kdf.ChannelRGBSDA_B,
	'A': kdf.ChannelRGBSDA_A,
}

type packedFormatInfo struct {
	channels       string
	bitsPerChannel []int
	endianness     kdf.Endianness
}

var packedRGBAFormats = map[Format]packedFormatInfo{
	FormatRGB24: {
		channels:       "RGB",
		bitsPerChannel: []int{8, 8, 8},
		endianness:     kdf.BigEndian,
	},
	FormatBGR24: {
		channels:       "BGR",
		bitsPerChannel: []int{8, 8, 8},
		endianness:     kdf.BigEndian,
	},
	FormatBGR8: {
		channels:       "BGR",
		bitsPerChannel: []int{2, 3, 3},
		endianness:     kdf.BigEndian,
	},
	FormatRGB8: {
		channels:       "RGB",
		bitsPerChannel: []int{2, 3, 3},
		endianness:     kdf.BigEndian,
	},
	FormatARGB: {
		channels:       "ARGB",
		bitsPerChannel: []int{8, 8, 8, 8},
		endianness:     kdf.BigEndian,
	},
	FormatRGBA: {
		channels:       "RGBA",
		bitsPerChannel: []int{8, 8, 8, 8},
		endianness:     kdf.BigEndian,
	},
	FormatABGR: {
		channels:       "ABGR",
		bitsPerChannel: []int{8, 8, 8, 8},
		endianness:     kdf.BigEndian,
	},
	FormatBGRA: {
		channels:       "BGRA",
		bitsPerChannel: []int{8, 8, 8, 8},
		endianness:     kdf.BigEndian,
	},
	FormatRGB48BE: {
		channels:       "RGB",
		bitsPerChannel: []int{16, 16, 16},
		endianness:     kdf.BigEndian,
	},
	FormatRGB48LE: {
		channels:       "BGR",
		bitsPerChannel: []int{16, 16, 16},
		endianness:     kdf.LittleEndian,
	},
}

func GetBlock(format Format) *kdf.Block {
	if packed, ok := packedRGBAFormats[format]; ok {
		return genRGBAPacked(&packed)
	}
	return nil
}

func genRGBAPacked(info *packedFormatInfo) *kdf.Block {
	if len(info.channels) != len(info.bitsPerChannel) {
		panic("mismatch between channels and bits per channel")
	}

	channels := genChannels(info.channels)

	var sampleInfo []kdf.SampleInfo
	for _, sample := range internal.PackedSamples(channels, info.bitsPerChannel, info.endianness) {
		sample.SampleLower = 0
		sample.SampleUpper = (1 << sample.BitLength) - 1
		sampleInfo = append(sampleInfo, sample)
	}

	return kdf.NewBlockBasic(&kdf.BlockBasic{
		ColorModel:          kdf.ColorModelRGBSDA,
		TexelBlockDimension: [4]int{1, 1, 1, 1},
		BytesPlane:          []uint8{getBytesPerPixel(info.bitsPerChannel)},
		SampleInfo:          sampleInfo,
	})
	return nil
}

func getBytesPerPixel(bitsPerChannel []int) uint8 {
	totalBits := 0
	for _, n := range bitsPerChannel {
		totalBits += n
	}
	totalBytes := totalBits / 8
	if totalBits%8 != 0 {
		totalBytes++
	}
	return uint8(totalBytes)
}

func genChannels(channels string) []kdf.Channel {
	var l []kdf.Channel
	for _, c := range channels {
		ch, ok := channelMap[c]
		if !ok {
			panic("unknown channel")
		}
		l = append(l, ch)
	}
	return l
}