From 433ca988ec16b6011ab70692e0f20c251ed254d1 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Tue, 25 Feb 2020 14:29:43 +0800 Subject: [PATCH 1/5] Update AMF files to support Linux --- libavcodec/amfenc.c | 19 ++++++++++++++++--- libavcodec/amfenc_h264.c | 1 + libavcodec/amfenc_hevc.c | 10 +++++----- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 384d8efc92c..876fddd2b6e 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -213,6 +213,7 @@ static int amf_init_from_dxva2_device(AVCodecContext *avctx, AVDXVA2DeviceContex static int amf_init_context(AVCodecContext *avctx) { AmfContext *ctx = avctx->priv_data; + AMFContext1 *context1 = NULL; AMF_RESULT res; av_unused int ret; @@ -311,8 +312,20 @@ static int amf_init_context(AVCodecContext *avctx) if (res == AMF_OK) { av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n"); } else { - av_log(avctx, AV_LOG_ERROR, "AMF initialisation failed via D3D9: error %d.\n", res); - return AVERROR(ENOSYS); + AMFGuid guid = IID_AMFContext1(); + res = ctx->context->pVtbl->QueryInterface(ctx->context, &guid, (void**)&context1); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res); + + res = context1->pVtbl->InitVulkan(context1, NULL); + context1->pVtbl->Release(context1); + if (res != AMF_OK) { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n"); + else + av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res); + return AVERROR(ENOSYS); + } + av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n"); } } } @@ -438,7 +451,7 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff int64_t timestamp = AV_NOPTS_VALUE; int64_t size = buffer->pVtbl->GetSize(buffer); - if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) { + if ((ret = av_new_packet(pkt, size)) < 0) { return ret; } memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size); diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c index 2c082e93bd9..7f2817f1157 100644 --- a/libavcodec/amfenc_h264.c +++ b/libavcodec/amfenc_h264.c @@ -366,6 +366,7 @@ static const AVCodecDefault defaults[] = { { "b", "2M" }, { "g", "250" }, { "slices", "1" }, + { "flags", "+loop"}, { NULL }, }; diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c index 7c9a33ab335..b0cb57cb960 100644 --- a/libavcodec/amfenc_hevc.c +++ b/libavcodec/amfenc_hevc.c @@ -69,7 +69,7 @@ static const AVOption options[] = { { "gop", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, { "idr", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, "hdrmode" }, - { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 60 }, 0, INT_MAX, VE }, + { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, VE }, { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, @@ -136,7 +136,7 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier); profile_level = avctx->level; - if (profile_level == 0) { + if (profile_level == FF_LEVEL_UNKNOWN) { profile_level = ctx->level; } if (profile_level != 0) { @@ -144,7 +144,7 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) } AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality); // Maximum Reference Frames - if (avctx->refs != 0) { + if (avctx->refs != -1) { AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES, avctx->refs); } // Aspect Ratio @@ -254,10 +254,10 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) } if (ctx->qp_p != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_p); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_p); } if (ctx->qp_i != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_i); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_i); } AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame); From 3b4ab246dc3c1ccf5ad5dfd7c35cd1b22d60cd4b Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Tue, 25 Feb 2020 17:20:41 +0800 Subject: [PATCH 2/5] Download only the necessary AMF headers --- docker-build.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docker-build.sh b/docker-build.sh index b9a6eff464a..5e24028b67f 100755 --- a/docker-build.sh +++ b/docker-build.sh @@ -114,10 +114,12 @@ popd # Download and setup AMD AMF headers from AMD official github repo # https://www.ffmpeg.org/general.html#AMD-AMF_002fVCE -wget -O amf_headers.zip https://github.com/GPUOpen-LibrariesAndSDKs/AMF/archive/master.zip -unzip amf_headers.zip -d amf_headers -cd "amf_headers/AMF-master/amf/public/include/" -mkdir -p "/usr/include/AMF/" && cp -r * "/usr/include/AMF/" +apt-get update +yes | apt-get install subversion +svn checkout https://github.com/GPUOpen-LibrariesAndSDKs/AMF/trunk/amf/public/include +pushd include +mkdir -p /usr/include/AMF && mv * /usr/include/AMF +popd # Move to source directory pushd ${SOURCE_DIR} From ebe76455bf66d360d943b94f5691c9e956e13ed7 Mon Sep 17 00:00:00 2001 From: Nyanmisaka Date: Tue, 25 Feb 2020 17:33:16 +0800 Subject: [PATCH 3/5] Bump version for AMF on Linux --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 33fd77db4b2..a37de80e31c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +jellyfin-ffmpeg (4.2.1-6) unstable; urgency=medium + + * Update AMD AMF files to support Linux + + -- nyanmisaka Tue, 25 Feb 2020 17:33:28 +0800 + jellyfin-ffmpeg (4.2.1-5) unstable; urgency=medium * Add support for Debian Bullseye (testing) From 5b873e4fa2e58217fc773c4880b23110982a5d39 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Thu, 27 Feb 2020 00:31:00 +0800 Subject: [PATCH 4/5] Revert "Update AMF files to support Linux" This reverts commit 433ca988ec16b6011ab70692e0f20c251ed254d1. --- libavcodec/amfenc.c | 19 +++---------------- libavcodec/amfenc_h264.c | 1 - libavcodec/amfenc_hevc.c | 10 +++++----- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 876fddd2b6e..384d8efc92c 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -213,7 +213,6 @@ static int amf_init_from_dxva2_device(AVCodecContext *avctx, AVDXVA2DeviceContex static int amf_init_context(AVCodecContext *avctx) { AmfContext *ctx = avctx->priv_data; - AMFContext1 *context1 = NULL; AMF_RESULT res; av_unused int ret; @@ -312,20 +311,8 @@ static int amf_init_context(AVCodecContext *avctx) if (res == AMF_OK) { av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n"); } else { - AMFGuid guid = IID_AMFContext1(); - res = ctx->context->pVtbl->QueryInterface(ctx->context, &guid, (void**)&context1); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res); - - res = context1->pVtbl->InitVulkan(context1, NULL); - context1->pVtbl->Release(context1); - if (res != AMF_OK) { - if (res == AMF_NOT_SUPPORTED) - av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n"); - else - av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res); - return AVERROR(ENOSYS); - } - av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n"); + av_log(avctx, AV_LOG_ERROR, "AMF initialisation failed via D3D9: error %d.\n", res); + return AVERROR(ENOSYS); } } } @@ -451,7 +438,7 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff int64_t timestamp = AV_NOPTS_VALUE; int64_t size = buffer->pVtbl->GetSize(buffer); - if ((ret = av_new_packet(pkt, size)) < 0) { + if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) { return ret; } memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size); diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c index 7f2817f1157..2c082e93bd9 100644 --- a/libavcodec/amfenc_h264.c +++ b/libavcodec/amfenc_h264.c @@ -366,7 +366,6 @@ static const AVCodecDefault defaults[] = { { "b", "2M" }, { "g", "250" }, { "slices", "1" }, - { "flags", "+loop"}, { NULL }, }; diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c index b0cb57cb960..7c9a33ab335 100644 --- a/libavcodec/amfenc_hevc.c +++ b/libavcodec/amfenc_hevc.c @@ -69,7 +69,7 @@ static const AVOption options[] = { { "gop", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, { "idr", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, "hdrmode" }, - { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, VE }, + { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 60 }, 0, INT_MAX, VE }, { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, @@ -136,7 +136,7 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier); profile_level = avctx->level; - if (profile_level == FF_LEVEL_UNKNOWN) { + if (profile_level == 0) { profile_level = ctx->level; } if (profile_level != 0) { @@ -144,7 +144,7 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) } AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality); // Maximum Reference Frames - if (avctx->refs != -1) { + if (avctx->refs != 0) { AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES, avctx->refs); } // Aspect Ratio @@ -254,10 +254,10 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) } if (ctx->qp_p != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_p); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_p); } if (ctx->qp_i != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_i); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_i); } AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame); From 6b2eb2cc97bcbe22cc384865557cd59d866ac08e Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Thu, 27 Feb 2020 00:37:10 +0800 Subject: [PATCH 5/5] Include as a patch --- ...02-Update-AMF-files-to-support-Linux.patch | 100 ++++++++++++++++++ debian/patches/series | 1 + 2 files changed, 101 insertions(+) create mode 100644 debian/patches/0002-Update-AMF-files-to-support-Linux.patch diff --git a/debian/patches/0002-Update-AMF-files-to-support-Linux.patch b/debian/patches/0002-Update-AMF-files-to-support-Linux.patch new file mode 100644 index 00000000000..58dc1d135ef --- /dev/null +++ b/debian/patches/0002-Update-AMF-files-to-support-Linux.patch @@ -0,0 +1,100 @@ +Index: jellyfin-ffmpeg/libavcodec/amfenc.c +=================================================================== +--- jellyfin-ffmpeg.orig/libavcodec/amfenc.c ++++ jellyfin-ffmpeg/libavcodec/amfenc.c +@@ -213,6 +213,7 @@ static int amf_init_from_dxva2_device(AV + static int amf_init_context(AVCodecContext *avctx) + { + AmfContext *ctx = avctx->priv_data; ++ AMFContext1 *context1 = NULL; + AMF_RESULT res; + av_unused int ret; + +@@ -311,8 +312,20 @@ static int amf_init_context(AVCodecConte + if (res == AMF_OK) { + av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n"); + } else { +- av_log(avctx, AV_LOG_ERROR, "AMF initialisation failed via D3D9: error %d.\n", res); +- return AVERROR(ENOSYS); ++ AMFGuid guid = IID_AMFContext1(); ++ res = ctx->context->pVtbl->QueryInterface(ctx->context, &guid, (void**)&context1); ++ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res); ++ ++ res = context1->pVtbl->InitVulkan(context1, NULL); ++ context1->pVtbl->Release(context1); ++ if (res != AMF_OK) { ++ if (res == AMF_NOT_SUPPORTED) ++ av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n"); ++ else ++ av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res); ++ return AVERROR(ENOSYS); ++ } ++ av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n"); + } + } + } +@@ -438,7 +451,7 @@ static int amf_copy_buffer(AVCodecContex + int64_t timestamp = AV_NOPTS_VALUE; + int64_t size = buffer->pVtbl->GetSize(buffer); + +- if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) { ++ if ((ret = av_new_packet(pkt, size)) < 0) { + return ret; + } + memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size); +Index: jellyfin-ffmpeg/libavcodec/amfenc_h264.c +=================================================================== +--- jellyfin-ffmpeg.orig/libavcodec/amfenc_h264.c ++++ jellyfin-ffmpeg/libavcodec/amfenc_h264.c +@@ -366,6 +366,7 @@ static const AVCodecDefault defaults[] = + { "b", "2M" }, + { "g", "250" }, + { "slices", "1" }, ++ { "flags", "+loop"}, + { NULL }, + }; + +Index: jellyfin-ffmpeg/libavcodec/amfenc_hevc.c +=================================================================== +--- jellyfin-ffmpeg.orig/libavcodec/amfenc_hevc.c ++++ jellyfin-ffmpeg/libavcodec/amfenc_hevc.c +@@ -69,7 +69,7 @@ static const AVOption options[] = { + { "gop", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, + { "idr", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, "hdrmode" }, + +- { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 60 }, 0, INT_MAX, VE }, ++ { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, VE }, + { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, + { "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, + { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, +@@ -136,7 +136,7 @@ static av_cold int amf_encode_init_hevc( + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier); + + profile_level = avctx->level; +- if (profile_level == 0) { ++ if (profile_level == FF_LEVEL_UNKNOWN) { + profile_level = ctx->level; + } + if (profile_level != 0) { +@@ -144,7 +144,7 @@ static av_cold int amf_encode_init_hevc( + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality); + // Maximum Reference Frames +- if (avctx->refs != 0) { ++ if (avctx->refs != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES, avctx->refs); + } + // Aspect Ratio +@@ -254,10 +254,10 @@ static av_cold int amf_encode_init_hevc( + } + + if (ctx->qp_p != -1) { +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_p); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_p); + } + if (ctx->qp_i != -1) { +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_i); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_i); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame); + diff --git a/debian/patches/series b/debian/patches/series index 736c9d4354d..6c56c1f60b4 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1 +1,2 @@ 0001_fix-segment-muxer.patch +0002-Update-AMF-files-to-support-Linux.patch