Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fork gst-d3d11 to gst-d3d12 support #647

Merged
merged 1 commit into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/gstreamer/d3d12/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###
89 changes: 89 additions & 0 deletions lib/gstreamer/d3d12/decoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###

import os
import slash

from ....lib import platform
from ....lib.codecs import Codec
from ....lib.common import get_media
from ....lib.formats import PixelFormat
from ....lib.gstreamer.decoderbase import BaseDecoderTest, Decoder as GstDecoder
from ....lib.gstreamer.util import have_gst_element
from ....lib.gstreamer.d3d12.util import mapformat, mapformatu

class Decoder(GstDecoder):
format = property(lambda s: mapformatu(super().format))
pformat = property(lambda s: mapformat(super().format))

@slash.requires(*have_gst_element("d3d12"))
class DecoderTest(BaseDecoderTest):
DecoderClass = Decoder

def decode_test_class(codec, bitdepth, **kwargs):
# caps lookup translation
capcodec = codec
if codec in [Codec.HEVC, Codec.VP9, Codec.AV1]:
capcodec = f"{codec}_{bitdepth}"

# gst element codec translation
gstcodec = {
Codec.AVC : "h264",
Codec.HEVC : "h265",
}.get(codec, codec)

gstparser = {
Codec.MPEG2 : "mpegvideoparse",
Codec.VP8 : None,
}.get(codec, f"{gstcodec}parse")

hwdevice = get_media().render_device.split('/')[-1]
hw = hwdevice if hwdevice not in ['renderD128', '0'] else ""

@slash.requires(*have_gst_element(f"d3d12{hw}{gstcodec}dec"))
@slash.requires(*platform.have_caps("decode", capcodec))
class CodecDecoderTest(DecoderTest):
def before(self):
super().before()
vars(self).update(
caps = platform.get_caps("decode", capcodec),
codec = codec,
gstdecoder = f"d3d12{hw}{gstcodec}dec",
gstparser = gstparser,
**kwargs,
)

def validate_caps(self):
assert PixelFormat(self.format).bitdepth == bitdepth
super().validate_caps()

return CodecDecoderTest

## AVC ##
AVCDecoderTest = decode_test_class(codec = Codec.AVC, bitdepth = 8)

## HEVC ##
HEVC_8DecoderTest = decode_test_class(codec = Codec.HEVC, bitdepth = 8)
HEVC_10DecoderTest = decode_test_class(codec = Codec.HEVC, bitdepth = 10)
HEVC_12DecoderTest = decode_test_class(codec = Codec.HEVC, bitdepth = 12)

## AV1 ##
AV1_8DecoderTest = decode_test_class(codec = Codec.AV1, bitdepth = 8)
AV1_10DecoderTest = decode_test_class(codec = Codec.AV1, bitdepth = 10)

## VP9 ##
VP9_8DecoderTest = decode_test_class(codec = Codec.VP9, bitdepth = 8)
VP9_10DecoderTest = decode_test_class(codec = Codec.VP9, bitdepth = 10)
VP9_12DecoderTest = decode_test_class(codec = Codec.VP9, bitdepth = 12)

## VP8 ##
VP8DecoderTest = decode_test_class(codec = Codec.VP8, bitdepth = 8)

## JPEG/MJPEG ##
JPEGDecoderTest = decode_test_class(codec = Codec.JPEG, bitdepth = 8)

## MPEG2 ##
MPEG2DecoderTest = decode_test_class(codec = Codec.MPEG2, bitdepth = 8)
96 changes: 96 additions & 0 deletions lib/gstreamer/d3d12/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###

from ....lib.codecs import Codec
from ....lib.common import memoize
from ....lib.formats import match_best_format
from ....lib.gstreamer.util import *

def get_supported_format_map():
#The map first entry is for gst element properties;the second entry is for gst caps filters
#for example:
# i420 is entry for gst properties such as vaapipostproc
# I420: is entry for gst caps filter
return {
"I420" : ("i420", "I420"),
"NV12" : ("nv12", "NV12"),
"YV12" : ("yv12", "YV12"),
"AYUV" : ("vuya", "VUYA"), #we use microsoft's definition of AYUV,https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#ayuv
"YUY2" : ("yuy2", "YUY2"),
"ARGB" : ("argb", "ARGB"),
"BGRA" : ("bgra", "BGRA"),
"422H" : ("y42b", "Y42B"),
"444P" : ("y444", "Y444"),
"P010" : ("p010-10le", "P010_10LE"),
"P012" : ("p012-le", "P012_LE"),
"I010" : ("i420-10le", "I420_10LE"),
"Y210" : ("y210", "Y210"),
"Y212" : ("y212-le", "Y212_LE"),
"Y410" : ("y410", "Y410"),
"Y412" : ("y412-le", "Y412_LE"),
}

@memoize
def mapformat(format):
return get_supported_format_map().get(format, (None, None))[0]

@memoize
def mapformatu(format):
return get_supported_format_map().get(format, (None, None))[1]

def map_best_hw_format(format, hwformats):
return mapformatu(
match_best_format(
format, set(hwformats) & set(get_supported_format_map().keys())))

@memoize
def map_transpose_direction(degrees, method):
return {
( 0, None) : "identity",
( 0, "vertical") : "vert",
( 0, "horizontal") : "horiz",
( 90, None) : "90r",
( 90, "vertical") : "ur-ll",
( 90, "horizontal") : "ul-lr",
(180, None) : "180",
(180, "vertical") : "horiz",
(180, "horizontal") : "vert",
(270, None) : "90l",
(270, "vertical") : "ul-lr",
(270, "horizontal") : "ur-ll",
}.get((degrees, method), None)

@memoize
def mapprofile(codec, profile):
return {
Codec.AVC : {
"high" : "high",
"main" : "main",
"baseline" : "baseline",
"constrained-baseline" : "constrained-baseline",
"multiview-high" : "multiview-high",
"stereo-high" : "stereo-high",
},
Codec.HEVC : {
"main" : "main",
"scc" : "screen-extended-main",
"scc-444" : "screen-extended-main-444",
"main444" : "main-444",
#profile of "hevc-8bit 422" is mapped to main-422-10 based on
#https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding#Profiles
"main422" : "main-422-10",
"main10" : "main-10",
"main444-10" : "main-444-10",
"main12" : "main-12",
},
Codec.VP9 : {
"profile3" : "profile3",
},
}.get(codec, {}).get(profile, None)

def load_test_spec(*ctx):
from ....lib import util as libutil
return libutil.load_test_spec("gst-d3d12", *ctx)
5 changes: 5 additions & 0 deletions test/gst-d3d12/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###
5 changes: 5 additions & 0 deletions test/gst-d3d12/decode/10bit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###
34 changes: 34 additions & 0 deletions test/gst-d3d12/decode/10bit/av1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###

from .....lib import *
from .....lib.gstreamer.d3d12.util import *
from .....lib.gstreamer.d3d12.decoder import AV1_10DecoderTest as DecoderTest

spec = load_test_spec("av1", "decode", "10bit")

class default(DecoderTest):
def before(self):
super().before()
vars(self).update(
# default metric
metric = dict(type = "ssim", miny = 1.0, minu = 1.0, minv = 1.0),
)

@slash.parametrize(("case"), sorted(spec.keys()))
def test(self, case):
vars(self).update(spec[case].copy())

dxmap = {".ivf" : "ivfparse", ".webm" : "matroskademux", ".mkv" : "matroskademux", ".obu" : "av1parse"}
ext = os.path.splitext(self.source)[1]
dx = dxmap.get(ext, None)
assert dx is not None, "Unrecognized source file extension {}".format(ext)

vars(self).update(
case = case,
gstdemuxer = dx if self.gstparser not in dx else None,
)
self.decode()
25 changes: 25 additions & 0 deletions test/gst-d3d12/decode/10bit/hevc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###

from .....lib import *
from .....lib.gstreamer.d3d12.util import *
from .....lib.gstreamer.d3d12.decoder import HEVC_10DecoderTest as DecoderTest

spec = load_test_spec("hevc", "decode", "10bit")

class default(DecoderTest):
def before(self):
super().before()
vars(self).update(
# default metric
metric = dict(type = "ssim", miny = 1.0, minu = 1.0, minv = 1.0),
)

@slash.parametrize(("case"), sorted(spec.keys()))
def test(self, case):
vars(self).update(spec[case].copy())
vars(self).update(case = case)
self.decode()
33 changes: 33 additions & 0 deletions test/gst-d3d12/decode/10bit/vp9.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###

from .....lib import *
from .....lib.gstreamer.d3d12.util import *
from .....lib.gstreamer.d3d12.decoder import VP9_10DecoderTest as DecoderTest

spec = load_test_spec("vp9", "decode", "10bit")

class default(DecoderTest):
def before(self):
super().before()
vars(self).update(
# default metric
metric = dict(type = "ssim", miny = 1.0, minu = 1.0, minv = 1.0),
)

@slash.parametrize(("case"), sorted(spec.keys()))
def test(self, case):
vars(self).update(spec[case].copy())

dxmap = {".ivf" : "ivfparse", ".webm" : "matroskademux", ".mkv" : "matroskademux"}
ext = os.path.splitext(self.source)[1]
assert ext in dxmap.keys(), "Unrecognized source file extension {}".format(ext)

vars(self).update(
case = case,
gstdemuxer = dxmap[ext],
)
self.decode()
5 changes: 5 additions & 0 deletions test/gst-d3d12/decode/12bit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###
25 changes: 25 additions & 0 deletions test/gst-d3d12/decode/12bit/hevc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###

from .....lib import *
from .....lib.gstreamer.d3d12.util import *
from .....lib.gstreamer.d3d12.decoder import HEVC_12DecoderTest as DecoderTest

spec = load_test_spec("hevc", "decode", "12bit")

class default(DecoderTest):
def before(self):
super().before()
vars(self).update(
# default metric
metric = dict(type = "ssim", miny = 1.0, minu = 1.0, minv = 1.0),
)

@slash.parametrize(("case"), sorted(spec.keys()))
def test(self, case):
vars(self).update(spec[case].copy())
vars(self).update(case = case)
self.decode()
33 changes: 33 additions & 0 deletions test/gst-d3d12/decode/12bit/vp9.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###

from .....lib import *
from .....lib.gstreamer.d3d12.util import *
from .....lib.gstreamer.d3d12.decoder import VP9_12DecoderTest as DecoderTest

spec = load_test_spec("vp9", "decode", "12bit")

class default(DecoderTest):
def before(self):
super().before()
vars(self).update(
# default metric
metric = dict(type = "ssim", miny = 1.0, minu = 1.0, minv = 1.0),
)

@slash.parametrize(("case"), sorted(spec.keys()))
def test(self, case):
vars(self).update(spec[case].copy())

dxmap = {".ivf" : "ivfparse", ".webm" : "matroskademux", ".mkv" : "matroskademux"}
ext = os.path.splitext(self.source)[1]
assert ext in dxmap.keys(), "Unrecognized source file extension {}".format(ext)

vars(self).update(
case = case,
gstdemuxer = dxmap[ext],
)
self.decode()
5 changes: 5 additions & 0 deletions test/gst-d3d12/decode/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
###
### Copyright (C) 2024 Intel Corporation
###
### SPDX-License-Identifier: BSD-3-Clause
###
Loading