diff mbox

[FFmpeg-devel] Added HW H.264 and HEVC encoding for AMD GPUs based on AMF SDK

Message ID 65773b32-8665-442e-8d11-493cd3387782@mmironov-dev.local
State New
Headers show

Commit Message

mmironov Nov. 27, 2017, 2:36 a.m. UTC
From 21d99252fad543d3d27a015912c0458b6ae11e08 Mon Sep 17 00:00:00 2001
From: mmironov <mikhail.mironov@amd.com>
Date: Tue, 14 Nov 2017 17:54:24 -0500
Subject: [PATCH] Added HW H.264 and HEVC encoding for AMD GPUs based on AMF
 SDK

Signed-off-by: mmironov <mikhail.mironov@amd.com>
---
 Changelog                |    1 +
 compat/amd/amfsdkenc.h   | 1755 ++++++++++++++++++++++++++++++++++++++++++++++
 configure                |   20 +-
 libavcodec/Makefile      |    4 +
 libavcodec/allcodecs.c   |    2 +
 libavcodec/amfenc.c      |  602 ++++++++++++++++
 libavcodec/amfenc.h      |  143 ++++
 libavcodec/amfenc_h264.c |  397 +++++++++++
 libavcodec/amfenc_hevc.c |  327 +++++++++
 9 files changed, 3249 insertions(+), 2 deletions(-)
 create mode 100644 compat/amd/amfsdkenc.h
 create mode 100644 libavcodec/amfenc.c
 create mode 100644 libavcodec/amfenc.h
 create mode 100644 libavcodec/amfenc_h264.c
 create mode 100644 libavcodec/amfenc_hevc.c

Comments

James Almer Nov. 27, 2017, 2:42 a.m. UTC | #1
On 11/26/2017 11:36 PM, mmironov wrote:
> From 21d99252fad543d3d27a015912c0458b6ae11e08 Mon Sep 17 00:00:00 2001
> From: mmironov <mikhail.mironov@amd.com>
> Date: Tue, 14 Nov 2017 17:54:24 -0500
> Subject: [PATCH] Added HW H.264 and HEVC encoding for AMD GPUs based on AMF
>  SDK
> 
> Signed-off-by: mmironov <mikhail.mironov@amd.com>
> ---
>  Changelog                |    1 +
>  compat/amd/amfsdkenc.h   | 1755 ++++++++++++++++++++++++++++++++++++++++++++++
>  configure                |   20 +-
>  libavcodec/Makefile      |    4 +
>  libavcodec/allcodecs.c   |    2 +
>  libavcodec/amfenc.c      |  602 ++++++++++++++++
>  libavcodec/amfenc.h      |  143 ++++
>  libavcodec/amfenc_h264.c |  397 +++++++++++
>  libavcodec/amfenc_hevc.c |  327 +++++++++
>  9 files changed, 3249 insertions(+), 2 deletions(-)
>  create mode 100644 compat/amd/amfsdkenc.h
>  create mode 100644 libavcodec/amfenc.c
>  create mode 100644 libavcodec/amfenc.h
>  create mode 100644 libavcodec/amfenc_h264.c
>  create mode 100644 libavcodec/amfenc_hevc.c

No comments about the code, but given this patchset has started a policy
controversy I'll state I'm in favor of including this external header.

Not shipping this one for having a working external version but shipping
the Nvidia one for being a custom working version of the unusable shit
they made public is rewarding them for said user unfriendliness, as Mark
clearly stated in a previous thread.
So lets add this one, then figure out if we want any of them at all or
not at a later point. They all can be moved to some external repository
if needed.
Carl Eugen Hoyos Nov. 27, 2017, 2:57 a.m. UTC | #2
2017-11-27 3:42 GMT+01:00 James Almer <jamrial@gmail.com>:

> No comments about the code, but given this patchset has started a policy
> controversy I'll state I'm in favor of including this external header.

Will the header work for operating systems other than Windows?

Carl Eugen
James Almer Nov. 27, 2017, 3 a.m. UTC | #3
On 11/26/2017 11:57 PM, Carl Eugen Hoyos wrote:
> 2017-11-27 3:42 GMT+01:00 James Almer <jamrial@gmail.com>:
> 
>> No comments about the code, but given this patchset has started a policy
>> controversy I'll state I'm in favor of including this external header.
> 
> Will the header work for operating systems other than Windows?

Why are you asking me? I'm not the author of the patch.

And a quick look at the configure change should answer your question.
mmironov Nov. 27, 2017, 3:06 a.m. UTC | #4
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf

> Of Carl Eugen Hoyos

> Sent: November 26, 2017 9:57 PM

> To: FFmpeg development discussions and patches <ffmpeg-

> devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] Added HW H.264 and HEVC encoding for AMD

> GPUs based on AMF SDK

> 

> 2017-11-27 3:42 GMT+01:00 James Almer <jamrial@gmail.com>:

> 

> > No comments about the code, but given this patchset has started a

> > policy controversy I'll state I'm in favor of including this external header.

> 

> Will the header work for operating systems other than Windows?


We are working on Linux version. Before I started FFmpeg integration 
I convinced the management to allocate resources.
It will come in two phases: 
1. AMF via Vulkan on Windows
2. AMF via Vulkan on Linux
I think as a side affect we can help integrate Vulkan acceleration to FFmpeg. 
It is much better then OpenCL for multimedia from performance perspective.

Thank,
Mikhail
Carl Eugen Hoyos Nov. 27, 2017, 3:17 a.m. UTC | #5
2017-11-27 4:00 GMT+01:00 James Almer <jamrial@gmail.com>:
> On 11/26/2017 11:57 PM, Carl Eugen Hoyos wrote:
>> 2017-11-27 3:42 GMT+01:00 James Almer <jamrial@gmail.com>:
>>
>>> No comments about the code, but given this patchset has started a policy
>>> controversy I'll state I'm in favor of including this external header.
>>
>> Will the header work for operating systems other than Windows?
>
> Why are you asking me? I'm not the author of the patch.
>
> And a quick look at the configure change should answer your question.

What I meant was:
The header currently does not help a relevant number of users
(it would make Zeranoe's and Hendrik's life a little easier, that's
all). In the future, it will be useful because AMD plans to provide
a Linux driver. But I have a feeling that the current header will
not work for this future driver, meaning adding the header now
may be counter-productive.

That's completely apart from the fact that this header file does
not comply with any style guide while Nvidia's does (from a
very quick look at both files).

Carl Eugen
Carl Eugen Hoyos Nov. 27, 2017, 3:19 a.m. UTC | #6
2017-11-27 4:06 GMT+01:00 Mironov, Mikhail <Mikhail.Mironov@amd.com>:

> I think as a side affect we can help integrate Vulkan acceleration to FFmpeg.
> It is much better then OpenCL for multimedia from performance perspective.

Why did I so strongly expect this argument?
(I have neither ever used OpenCL nor Vulkan.)

Others may (and hopefully do) disagree but I believe
you should really change your argumentation.

Sorry, Carl Eugen
mmironov Nov. 27, 2017, 3:24 a.m. UTC | #7
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf

> Of Carl Eugen Hoyos

> Sent: November 26, 2017 10:20 PM

> To: FFmpeg development discussions and patches <ffmpeg-

> devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] Added HW H.264 and HEVC encoding for AMD

> GPUs based on AMF SDK

> 

> 2017-11-27 4:06 GMT+01:00 Mironov, Mikhail

> <Mikhail.Mironov@amd.com>:

> 

> > I think as a side affect we can help integrate Vulkan acceleration to FFmpeg.

> > It is much better then OpenCL for multimedia from performance

> perspective.

> 

> Why did I so strongly expect this argument?

> (I have neither ever used OpenCL nor Vulkan.)

> 

> Others may (and hopefully do) disagree but I believe you should really

> change your argumentation.

> 


I stated that this is a side note, not an argument.
Thank,
Mikhail
James Almer Nov. 27, 2017, 3:24 a.m. UTC | #8
On 11/27/2017 12:17 AM, Carl Eugen Hoyos wrote:
> 2017-11-27 4:00 GMT+01:00 James Almer <jamrial@gmail.com>:
>> On 11/26/2017 11:57 PM, Carl Eugen Hoyos wrote:
>>> 2017-11-27 3:42 GMT+01:00 James Almer <jamrial@gmail.com>:
>>>
>>>> No comments about the code, but given this patchset has started a policy
>>>> controversy I'll state I'm in favor of including this external header.
>>>
>>> Will the header work for operating systems other than Windows?
>>
>> Why are you asking me? I'm not the author of the patch.
>>
>> And a quick look at the configure change should answer your question.
> 
> What I meant was:
> The header currently does not help a relevant number of users
> (it would make Zeranoe's and Hendrik's life a little easier, that's
> all). In the future, it will be useful because AMD plans to provide
> a Linux driver. But I have a feeling that the current header will
> not work for this future driver, meaning adding the header now
> may be counter-productive.

It can easily be adapted for that alongside the configure checks, I'm
sure, much like the Nvidia one was for different needs.

> 
> That's completely apart from the fact that this header file does
> not comply with any style guide while Nvidia's does (from a
> very quick look at both files).

That would be because the Nvidia one was written/adapted by a ffmpeg
developer, who probably paid attention to that.
We can ask Mironov to improve the style in the header he submitted if
that's important.

The avxsynth headers don't follow any style guide either, for that
matter. Indentation is all over the place.
Carl Eugen Hoyos Nov. 27, 2017, 3:29 a.m. UTC | #9
2017-11-27 4:24 GMT+01:00 James Almer <jamrial@gmail.com>:
> On 11/27/2017 12:17 AM, Carl Eugen Hoyos wrote:

>> That's completely apart from the fact that this header file does
>> not comply with any style guide while Nvidia's does (from a
>> very quick look at both files).
>
> That would be because the Nvidia one was written/adapted by
> a ffmpeg developer, who probably paid attention to that.

(How is that related?)

> We can ask Mironov to improve the style in the header he
> submitted if that's important.

Not if you feel it is not important.

If everybody wants this header, I will try hard to abstain from
this discussion from now on.

Sorry, Carl Eugen
diff mbox

Patch

diff --git a/Changelog b/Changelog
index 68829f2..e5e5ffd 100644
--- a/Changelog
+++ b/Changelog
@@ -15,6 +15,7 @@  version <next>:
 - Raw aptX muxer and demuxer
 - NVIDIA NVDEC-accelerated H.264, HEVC and VP9 hwaccel decoding
 - Intel QSV-accelerated overlay filter
+- AMD NW H.264 and HEVC encoders
 
 
 version 3.4:
diff --git a/compat/amd/amfsdkenc.h b/compat/amd/amfsdkenc.h
new file mode 100644
index 0000000..282656d
--- /dev/null
+++ b/compat/amd/amfsdkenc.h
@@ -0,0 +1,1755 @@ 
+// 
+// MIT license 
+// 
+// Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+// Reduced AMF API
+//
+// Full version of AMF SDK and the latest version of this file 
+// can be found at https://github.com/GPUOpen-LibrariesAndSDKs/AMF
+
+#ifndef __AMF_SDK_Enc_h__
+#define __AMF_SDK_Enc_h__
+#pragma once
+
+//-----------------------------------------------------------------------------
+// Platform.h
+//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------
+// export declaration
+//----------------------------------------------------------------------------------------------
+#ifdef _WIN32
+#if defined(AMF_CORE_STATIC)
+#define AMF_CORE_LINK
+#else
+#if defined(AMF_CORE_EXPORTS)
+#define AMF_CORE_LINK __declspec(dllexport)
+#else
+#define AMF_CORE_LINK __declspec(dllimport)
+#endif
+#endif
+#else // #ifdef _WIN32
+#define AMF_CORE_LINK
+#endif // #ifdef _WIN32
+
+#define AMF_MACRO_STRING2(x) #x
+#define AMF_MACRO_STRING(x) AMF_MACRO_STRING2(x)
+
+#define AMF_TODO(_todo) (__FILE__ "(" AMF_MACRO_STRING(__LINE__) "): TODO: "_todo)
+
+
+#if defined(__GNUC__) || defined(__clang__)
+#define AMF_ALIGN(n) __attribute__((aligned(n)))
+#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
+#define AMF_ALIGN(n) __declspec(align(n))
+#else
+#define AMF_ALIGN(n)
+//     #error Need to define AMF_ALIGN
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+
+#if defined(_WIN32)
+
+
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#define AMF_STD_CALL            __stdcall
+#define AMF_CDECL_CALL          __cdecl
+#define AMF_FAST_CALL           __fastcall
+#if defined(__GNUC__) || defined(__clang__)
+#define AMF_INLINE              inline
+#define AMF_FORCEINLINE         inline
+#else
+#define AMF_INLINE              __inline
+#define AMF_FORCEINLINE         __forceinline
+#endif
+#define AMF_NO_VTABLE           __declspec(novtable)
+
+#define AMFPRId64   "I64d"
+#define LPRId64    L"I64d"
+
+#define AMFPRIud64   "Iu64d"
+#define LPRIud64    L"Iu64d"
+
+#define AMFPRIx64   "I64x"
+#define LPRIx64    L"I64x"
+
+#else // !WIN32 - Linux and Mac
+
+#define AMF_STD_CALL
+#define AMF_CDECL_CALL
+#define AMF_FAST_CALL
+#if defined(__GNUC__) || defined(__clang__)
+#define AMF_INLINE              inline
+#define AMF_FORCEINLINE         inline
+#else
+#define AMF_INLINE              __inline__
+#define AMF_FORCEINLINE         __inline__
+#endif
+#define AMF_NO_VTABLE
+
+#if !defined(AMFPRId64)
+#define AMFPRId64    "lld"
+#define LPRId64     L"lld"
+
+#define AMFPRIud64    "ulld"
+#define LPRIud64     L"ulld"
+
+#define AMFPRIx64    "llx"
+#define LPRIx64     L"llx"
+#endif
+
+#endif // WIN32
+
+
+#if defined(_MSC_VER)
+#define AMF_WEAK __declspec( selectany ) 
+#elif defined (__GCC__) || defined(__clang__)//GCC or CLANG
+#define AMF_WEAK __attribute__((weak))
+#endif
+
+#define amf_countof(x) (sizeof(x) / sizeof(x[0]))
+
+//-------------------------------------------------------------------------------------------------
+// basic data types
+//-------------------------------------------------------------------------------------------------
+typedef     int64_t             amf_int64;
+typedef     int32_t             amf_int32;
+typedef     int16_t             amf_int16;
+typedef     int8_t              amf_int8;
+
+typedef     uint64_t            amf_uint64;
+typedef     uint32_t            amf_uint32;
+typedef     uint16_t            amf_uint16;
+typedef     uint8_t             amf_uint8;
+typedef     size_t              amf_size;
+
+typedef     void*               amf_handle;
+typedef     double              amf_double;
+typedef     float               amf_float;
+
+typedef     void                amf_void;
+
+#if defined(__cplusplus)
+typedef     bool                amf_bool;
+#else
+typedef     amf_uint8           amf_bool;
+#define     true                1 
+#define     false               0 
+#endif
+
+typedef     long                amf_long;
+typedef     int                 amf_int;
+typedef     unsigned long       amf_ulong;
+typedef     unsigned int        amf_uint;
+
+typedef     amf_int64           amf_pts;     // in 100 nanosecs
+
+#define AMF_SECOND          10000000L    // 1 second in 100 nanoseconds
+
+#define AMF_MIN(a, b) ((a) < (b) ? (a) : (b))
+#define AMF_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#if defined(_WIN32)
+#define PATH_SEPARATOR_WSTR         L"\\"
+#define PATH_SEPARATOR_WCHAR        L'\\'
+#elif defined(__linux) // Linux
+#define PATH_SEPARATOR_WSTR          L"/"
+#define PATH_SEPARATOR_WCHAR         L'/'
+#endif
+
+typedef struct AMFRect
+{
+    amf_int32 left;
+    amf_int32 top;
+    amf_int32 right;
+    amf_int32 bottom;
+} AMFRect;
+
+static AMF_INLINE struct AMFRect AMFConstructRect(amf_int32 left, amf_int32 top, amf_int32 right, amf_int32 bottom)
+{
+    struct AMFRect object = { left, top, right, bottom };
+    return object;
+}
+
+typedef struct AMFSize
+{
+    amf_int32 width;
+    amf_int32 height;
+} AMFSize;
+
+static AMF_INLINE struct AMFSize AMFConstructSize(amf_int32 width, amf_int32 height)
+{
+    struct AMFSize object = { width, height };
+    return object;
+}
+
+typedef struct AMFPoint
+{
+    amf_int32 x;
+    amf_int32 y;
+} AMFPoint;
+
+static AMF_INLINE struct AMFPoint AMFConstructPoint(amf_int32 x, amf_int32 y)
+{
+    struct AMFPoint object = { x, y };
+    return object;
+}
+
+typedef struct AMFRate
+{
+    amf_uint32 num;
+    amf_uint32 den;
+} AMFRate;
+
+static AMF_INLINE struct AMFRate AMFConstructRate(amf_uint32 num, amf_uint32 den)
+{
+    struct AMFRate object = { num, den };
+    return object;
+}
+
+typedef struct AMFRatio
+{
+    amf_uint32 num;
+    amf_uint32 den;
+} AMFRatio;
+
+static AMF_INLINE struct AMFRatio AMFConstructRatio(amf_uint32 num, amf_uint32 den)
+{
+    struct AMFRatio object = { num, den };
+    return object;
+}
+
+#pragma pack(push, 1)
+#if defined(_MSC_VER)
+#pragma warning( push )
+#endif
+#if defined(WIN32)
+#if defined(_MSC_VER)
+#pragma warning(disable : 4200)
+#pragma warning(disable : 4201)
+#endif
+#endif
+typedef struct AMFColor
+{
+    union
+    {
+        struct
+        {
+            amf_uint8 r;
+            amf_uint8 g;
+            amf_uint8 b;
+            amf_uint8 a;
+        };
+        amf_uint32 rgba;
+    };
+} AMFColor;
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+#pragma pack(pop)
+
+
+static AMF_INLINE struct AMFColor AMFConstructColor(amf_uint8 r, amf_uint8 g, amf_uint8 b, amf_uint8 a)
+{
+    struct AMFColor object;
+    object.r = r;
+    object.g = g;
+    object.b = b;
+    object.a = a;
+    return object;
+}
+
+#if defined(_WIN32)
+#include <combaseapi.h>
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+    // allocator
+    static AMF_INLINE void* AMF_CDECL_CALL amf_variant_alloc(amf_size count)
+    {
+        return CoTaskMemAlloc(count);
+    }
+    static AMF_INLINE void AMF_CDECL_CALL amf_variant_free(void* ptr)
+    {
+        CoTaskMemFree(ptr);
+    }
+#if defined(__cplusplus)
+}
+#endif
+
+#else // defined(_WIN32)
+#include <stdlib.h>
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+    // allocator
+    static AMF_INLINE void* AMF_CDECL_CALL amf_variant_alloc(amf_size count)
+    {
+        return malloc(count);
+    }
+    static AMF_INLINE void AMF_CDECL_CALL amf_variant_free(void* ptr)
+    {
+        free(ptr);
+    }
+#if defined(__cplusplus)
+}
+#endif
+#endif // defined(_WIN32)
+
+
+typedef struct AMFGuid
+{
+    amf_uint32 data1;
+    amf_uint16 data2;
+    amf_uint16 data3;
+    amf_uint8 data41;
+    amf_uint8 data42;
+    amf_uint8 data43;
+    amf_uint8 data44;
+    amf_uint8 data45;
+    amf_uint8 data46;
+    amf_uint8 data47;
+    amf_uint8 data48;
+} AMFGuid;
+
+//-----------------------------------------------------------------------------
+// Version.h
+//-----------------------------------------------------------------------------
+#define AMF_MAKE_FULL_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE, VERSION_BUILD_NUM)    ( ((amf_uint64)(VERSION_MAJOR) << 48ull) | ((amf_uint64)(VERSION_MINOR) << 32ull) | ((amf_uint64)(VERSION_RELEASE) << 16ull)  | (amf_uint64)(VERSION_BUILD_NUM))
+
+#define AMF_GET_MAJOR_VERSION(x)      ((x >> 48ull) & 0xFFFF)
+#define AMF_GET_MINOR_VERSION(x)      ((x >> 32ull) & 0xFFFF)
+#define AMF_GET_SUBMINOR_VERSION(x)   ((x >> 16ull) & 0xFFFF)
+#define AMF_GET_BUILD_VERSION(x)      ((x >>  0ull) & 0xFFFF)
+
+#define AMF_VERSION_MAJOR       1
+#define AMF_VERSION_MINOR       4
+#define AMF_VERSION_RELEASE     4
+#define AMF_VERSION_BUILD_NUM   0
+
+#define AMF_FULL_VERSION AMF_MAKE_FULL_VERSION(AMF_VERSION_MAJOR, AMF_VERSION_MINOR, AMF_VERSION_RELEASE, AMF_VERSION_BUILD_NUM)
+
+//-----------------------------------------------------------------------------
+// Result.h
+//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------
+// result codes
+//----------------------------------------------------------------------------------------------
+
+typedef enum AMF_RESULT
+{
+    AMF_OK                                   = 0,
+    AMF_FAIL                                    ,
+
+// common errors
+    AMF_UNEXPECTED                              ,
+
+    AMF_ACCESS_DENIED                           ,
+    AMF_INVALID_ARG                             ,
+    AMF_OUT_OF_RANGE                            ,
+
+    AMF_OUT_OF_MEMORY                           ,
+    AMF_INVALID_POINTER                         ,
+
+    AMF_NO_INTERFACE                            ,
+    AMF_NOT_IMPLEMENTED                         ,
+    AMF_NOT_SUPPORTED                           ,
+    AMF_NOT_FOUND                               ,
+
+    AMF_ALREADY_INITIALIZED                     ,
+    AMF_NOT_INITIALIZED                         ,
+
+    AMF_INVALID_FORMAT                          ,// invalid data format
+
+    AMF_WRONG_STATE                             ,
+    AMF_FILE_NOT_OPEN                           ,// cannot open file
+
+// device common codes
+    AMF_NO_DEVICE                               ,
+
+// device directx
+    AMF_DIRECTX_FAILED                          ,
+// device opencl 
+    AMF_OPENCL_FAILED                           ,
+// device opengl 
+    AMF_GLX_FAILED                              ,//failed to use GLX
+// device XV 
+    AMF_XV_FAILED                               , //failed to use Xv extension
+// device alsa
+    AMF_ALSA_FAILED                             ,//failed to use ALSA
+
+// component common codes
+
+    //result codes
+    AMF_EOF                                     ,
+    AMF_REPEAT                                  ,
+    AMF_INPUT_FULL                              ,//returned by AMFComponent::SubmitInput if input queue is full
+    AMF_RESOLUTION_CHANGED                      ,//resolution changed client needs to Drain/Terminate/Init
+    AMF_RESOLUTION_UPDATED                      ,//resolution changed in adaptive mode. New ROI will be set on output on newly decoded frames
+
+    //error codes
+    AMF_INVALID_DATA_TYPE                       ,//invalid data type
+    AMF_INVALID_RESOLUTION                      ,//invalid resolution (width or height)
+    AMF_CODEC_NOT_SUPPORTED                     ,//codec not supported
+    AMF_SURFACE_FORMAT_NOT_SUPPORTED            ,//surface format not supported
+    AMF_SURFACE_MUST_BE_SHARED                  ,//surface should be shared (DX11: (MiscFlags & D3D11_RESOURCE_MISC_SHARED) == 0, DX9: No shared handle found)
+
+// component video decoder
+    AMF_DECODER_NOT_PRESENT                     ,//failed to create the decoder
+    AMF_DECODER_SURFACE_ALLOCATION_FAILED       ,//failed to create the surface for decoding
+    AMF_DECODER_NO_FREE_SURFACES                ,
+
+// component video encoder
+    AMF_ENCODER_NOT_PRESENT                     ,//failed to create the encoder
+
+// component video processor
+
+// component video conveter
+
+// component dem
+    AMF_DEM_ERROR                               ,
+    AMF_DEM_PROPERTY_READONLY                   ,
+    AMF_DEM_REMOTE_DISPLAY_CREATE_FAILED        ,
+    AMF_DEM_START_ENCODING_FAILED               ,
+    AMF_DEM_QUERY_OUTPUT_FAILED                 ,
+
+// component TAN
+    AMF_TAN_CLIPPING_WAS_REQUIRED               , // Resulting data was truncated to meet output type's value limits.
+    AMF_TAN_UNSUPPORTED_VERSION                 , // Not supported version requested, solely for TANCreateContext().
+
+    AMF_NEED_MORE_INPUT                         ,//returned by AMFComponent::SubmitInput did not produce buffer
+} AMF_RESULT;
+
+
+//-----------------------------------------------------------------------------
+// Interface.h
+//-----------------------------------------------------------------------------
+#define AMF_DECLARE_IID(name, _data1, _data2, _data3, _data41, _data42, _data43, _data44, _data45, _data46, _data47, _data48) \
+        static AMF_INLINE const AMFGuid IID_##name(void) \
+        { \
+            AMFGuid uid = {_data1, _data2, _data3, _data41, _data42, _data43, _data44, _data45, _data46, _data47, _data48}; \
+            return uid; \
+        }
+AMF_DECLARE_IID(AMFInterface, 0x9d872f34, 0x90dc, 0x4b93, 0xb6, 0xb2, 0x6c, 0xa3, 0x7c, 0x85, 0x25, 0xdb)
+typedef struct AMFInterface AMFInterface;
+
+typedef struct AMFInterfaceVtbl
+{
+    // AMFInterface interface
+    amf_long(AMF_STD_CALL *Acquire)(AMFInterface* pThis);
+    amf_long(AMF_STD_CALL *Release)(AMFInterface* pThis);
+    enum AMF_RESULT(AMF_STD_CALL *QueryInterface)(AMFInterface* pThis, const struct AMFGuid *interfaceID, void** ppInterface);
+} AMFInterfaceVtbl;
+
+struct AMFInterface
+{
+    const AMFInterfaceVtbl *pVtbl;
+};
+
+//-----------------------------------------------------------------------------
+// Variant.h
+//-----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------------
+// variant types
+//----------------------------------------------------------------------------------------------
+typedef enum AMF_VARIANT_TYPE
+{
+    AMF_VARIANT_EMPTY = 0,
+
+    AMF_VARIANT_BOOL = 1,
+    AMF_VARIANT_INT64 = 2,
+    AMF_VARIANT_DOUBLE = 3,
+
+    AMF_VARIANT_RECT = 4,
+    AMF_VARIANT_SIZE = 5,
+    AMF_VARIANT_POINT = 6,
+    AMF_VARIANT_RATE = 7,
+    AMF_VARIANT_RATIO = 8,
+    AMF_VARIANT_COLOR = 9,
+
+    AMF_VARIANT_STRING = 10,  // value is char*
+    AMF_VARIANT_WSTRING = 11,  // value is wchar_t*
+    AMF_VARIANT_INTERFACE = 12,  // value is AMFInterface*
+} AMF_VARIANT_TYPE;
+//----------------------------------------------------------------------------------------------
+// variant struct
+//----------------------------------------------------------------------------------------------
+typedef struct AMFVariantStruct
+{
+    AMF_VARIANT_TYPE            type;
+    union
+    {
+        amf_bool                boolValue;
+        amf_int64               int64Value;
+        amf_double              doubleValue;
+        char*                   stringValue;
+        wchar_t*                wstringValue;
+        AMFInterface*           pInterface;
+        struct AMFRect          rectValue;
+        struct AMFSize          sizeValue;
+        struct AMFPoint         pointValue;
+        struct AMFRate          rateValue;
+        struct AMFRatio         ratioValue;
+        struct AMFColor         colorValue;
+    };
+} AMFVariantStruct;
+
+#define AMF_VARIANT_RETURN_IF_INVALID_POINTER(p) \
+       { \
+            if(p == NULL) \
+                    { \
+                 return AMF_INVALID_POINTER; \
+            } \
+       }
+
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantInit(AMFVariantStruct* pVariant)
+{
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pVariant);
+    pVariant->type = AMF_VARIANT_EMPTY;
+    return AMF_OK;
+}
+
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantClear(AMFVariantStruct* pVariant)
+{
+    AMF_RESULT errRet = AMF_OK;
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pVariant);
+
+    switch (pVariant->type)
+    {
+    case AMF_VARIANT_STRING:
+        amf_variant_free(pVariant->stringValue);
+        pVariant->type = AMF_VARIANT_EMPTY;
+        break;
+
+    case AMF_VARIANT_WSTRING:
+        amf_variant_free(pVariant->wstringValue);
+        pVariant->type = AMF_VARIANT_EMPTY;
+        break;
+
+    case AMF_VARIANT_INTERFACE:
+        if (pVariant->pInterface != NULL)
+        {
+#if defined(__cplusplus)
+            pVariant->pInterface->Release();
+#else
+            pVariant->pInterface->pVtbl->Release(pVariant->pInterface);
+#endif
+            pVariant->pInterface = NULL;
+        }
+        pVariant->type = AMF_VARIANT_EMPTY;
+        break;
+
+    default:
+        pVariant->type = AMF_VARIANT_EMPTY;
+        break;
+    }
+    return errRet;
+}
+//-------------------------------------------------------------------------------------------------
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantAssignBool(AMFVariantStruct* pDest, amf_bool value)
+{
+    AMF_RESULT errRet = AMF_OK;
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pDest);
+
+    errRet = AMFVariantClear(pDest);
+    if (errRet == AMF_OK)
+    {
+        pDest->type = AMF_VARIANT_BOOL;
+        pDest->boolValue = value;
+    }
+    return errRet;
+}
+//-------------------------------------------------------------------------------------------------
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantAssignInt64(AMFVariantStruct* pDest, amf_int64 value)
+{
+    AMF_RESULT errRet = AMF_OK;
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pDest);
+
+    errRet = AMFVariantClear(pDest);
+    if (errRet == AMF_OK)
+    {
+        pDest->type = AMF_VARIANT_INT64;
+        pDest->int64Value = value;
+    }
+    return errRet;
+}
+//-------------------------------------------------------------------------------------------------
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantAssignDouble(AMFVariantStruct* pDest, amf_double value)
+{
+    AMF_RESULT errRet = AMF_OK;
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pDest);
+
+    errRet = AMFVariantClear(pDest);
+    if (errRet == AMF_OK)
+    {
+        pDest->type = AMF_VARIANT_DOUBLE;
+        pDest->doubleValue = value;
+    }
+    return errRet;
+}
+//-------------------------------------------------------------------------------------------------
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantAssignSize(AMFVariantStruct* pDest, const AMFSize* value)
+{
+    AMF_RESULT errRet = AMF_OK;
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pDest);
+
+    errRet = AMFVariantClear(pDest);
+    if (errRet == AMF_OK)
+    {
+        pDest->type = AMF_VARIANT_SIZE;
+        pDest->sizeValue = *value;
+    }
+    return errRet;
+}
+//-------------------------------------------------------------------------------------------------
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantAssignPoint(AMFVariantStruct* pDest, const AMFPoint* value)
+{
+    AMF_RESULT errRet = AMF_OK;
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pDest);
+
+    errRet = AMFVariantClear(pDest);
+    if (errRet == AMF_OK)
+    {
+        pDest->type = AMF_VARIANT_POINT;
+        pDest->pointValue = *value;
+    }
+    return errRet;
+}
+//-------------------------------------------------------------------------------------------------
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantAssignRate(AMFVariantStruct* pDest, const AMFRate* value)
+{
+    AMF_RESULT errRet = AMF_OK;
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pDest);
+
+    errRet = AMFVariantClear(pDest);
+    if (errRet == AMF_OK)
+    {
+        pDest->type = AMF_VARIANT_RATE;
+        pDest->rateValue = *value;
+    }
+    return errRet;
+}
+//-------------------------------------------------------------------------------------------------
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantAssignRatio(AMFVariantStruct* pDest, const AMFRatio* value)
+{
+    AMF_RESULT errRet = AMF_OK;
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pDest);
+
+    errRet = AMFVariantClear(pDest);
+    if (errRet == AMF_OK)
+    {
+        pDest->type = AMF_VARIANT_RATIO;
+        pDest->ratioValue = *value;
+    }
+    return errRet;
+}
+//-------------------------------------------------------------------------------------------------
+static AMF_INLINE AMF_RESULT AMF_CDECL_CALL AMFVariantAssignColor(AMFVariantStruct* pDest, const AMFColor* value)
+{
+    AMF_RESULT errRet = AMF_OK;
+    AMF_VARIANT_RETURN_IF_INVALID_POINTER(pDest);
+
+    errRet = AMFVariantClear(pDest);
+    if (errRet == AMF_OK)
+    {
+        pDest->type = AMF_VARIANT_COLOR;
+        pDest->colorValue = *value;
+    }
+    return errRet;
+}
+
+//-----------------------------------------------------------------------------
+// PropertyStorage.h
+//-----------------------------------------------------------------------------
+typedef struct AMFPropertyStorageObserver AMFPropertyStorageObserver;
+typedef struct AMFPropertyStorage AMFPropertyStorage;
+
+#define AMF_ASSIGN_PROPERTY_DATA(res, varType, pThis, name, val ) \
+    { \
+        AMFVariantStruct var = {0}; \
+        AMFVariantAssign##varType(&var, val); \
+        res = pThis->pVtbl->SetProperty(pThis, name, var ); \
+    }
+#define AMF_ASSIGN_PROPERTY_TYPE(res, varType, dataType , pThis, name, val )  AMF_ASSIGN_PROPERTY_DATA(res, varType, pThis, name, (dataType)val)
+
+#define AMF_ASSIGN_PROPERTY_INT64(res, pThis, name, val ) AMF_ASSIGN_PROPERTY_TYPE(res, Int64, amf_int64, pThis, name, val)
+#define AMF_ASSIGN_PROPERTY_DOUBLE(res, pThis, name, val ) AMF_ASSIGN_PROPERTY_TYPE(res, Double, amf_double, pThis, name, val)
+#define AMF_ASSIGN_PROPERTY_BOOL(res, pThis, name, val ) AMF_ASSIGN_PROPERTY_TYPE(res, Bool, amf_bool, pThis, name, val)
+#define AMF_ASSIGN_PROPERTY_RECT(res, pThis, name, val ) AMF_ASSIGN_PROPERTY_DATA(res, Rect, pThis, name, &val)
+#define AMF_ASSIGN_PROPERTY_SIZE(res, pThis, name, val ) AMF_ASSIGN_PROPERTY_DATA(res, Size, pThis, name, &val)
+#define AMF_ASSIGN_PROPERTY_POINT(res, pThis, name, val ) AMF_ASSIGN_PROPERTY_DATA(res, Point, pThis, name, &val)
+#define AMF_ASSIGN_PROPERTY_RATE(res, pThis, name, val ) AMF_ASSIGN_PROPERTY_DATA(res, Rate, pThis, name, &val)
+#define AMF_ASSIGN_PROPERTY_RATIO(res, pThis, name, val ) AMF_ASSIGN_PROPERTY_DATA(res, Ratio, pThis, name, &val)
+#define AMF_ASSIGN_PROPERTY_COLOR(res, pThis, name, val ) AMF_ASSIGN_PROPERTY_DATA(res, Color, pThis, name, &val)
+
+//-----------------------------------------------------------------------------
+// PropertyStorageEx.h
+//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------
+typedef enum AMF_PROPERTY_CONTENT_ENUM
+{
+    AMF_PROPERTY_CONTENT_DEFAULT = 0,
+    AMF_PROPERTY_CONTENT_XML,               // m_eType is AMF_VARIANT_STRING
+
+    AMF_PROPERTY_CONTENT_FILE_OPEN_PATH,    // m_eType AMF_VARIANT_WSTRING
+    AMF_PROPERTY_CONTENT_FILE_SAVE_PATH     // m_eType AMF_VARIANT_WSTRING
+} AMF_PROPERTY_CONTENT_ENUM;
+//----------------------------------------------------------------------------------------------
+typedef enum AMF_PROPERTY_ACCESS_TYPE
+{
+    AMF_PROPERTY_ACCESS_PRIVATE = 0,
+    AMF_PROPERTY_ACCESS_READ = 0x1,
+    AMF_PROPERTY_ACCESS_WRITE = 0x2,
+    AMF_PROPERTY_ACCESS_READ_WRITE = (AMF_PROPERTY_ACCESS_READ | AMF_PROPERTY_ACCESS_WRITE),
+    AMF_PROPERTY_ACCESS_WRITE_RUNTIME = 0x4,
+    AMF_PROPERTY_ACCESS_FULL = 0xFF,
+} AMF_PROPERTY_ACCESS_TYPE;
+//----------------------------------------------------------------------------------------------
+typedef struct AMFEnumDescriptionEntry
+{
+    amf_int             value;
+    const wchar_t*      name;
+} AMFEnumDescriptionEntry;
+//----------------------------------------------------------------------------------------------
+typedef amf_uint32 AMF_PROPERTY_CONTENT_TYPE;
+
+typedef struct AMFPropertyInfo
+{
+    const wchar_t*                  name;
+    const wchar_t*                  desc;
+    AMF_VARIANT_TYPE                type;
+    AMF_PROPERTY_CONTENT_TYPE       contentType;
+
+    AMFVariantStruct                defaultValue;
+    AMFVariantStruct                minValue;
+    AMFVariantStruct                maxValue;
+    AMF_PROPERTY_ACCESS_TYPE        accessType;
+    const AMFEnumDescriptionEntry*  pEnumDescription;
+} AMFPropertyInfo;
+//-----------------------------------------------------------------------------
+// Data.h
+//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------
+typedef enum AMF_DATA_TYPE
+{
+    AMF_DATA_BUFFER = 0,
+    AMF_DATA_SURFACE = 1,
+    AMF_DATA_AUDIO_BUFFER = 2,
+    AMF_DATA_USER = 1000,
+    // all extensions will be AMF_DATA_USER+i
+} AMF_DATA_TYPE;
+//----------------------------------------------------------------------------------------------
+typedef enum AMF_MEMORY_TYPE
+{
+    AMF_MEMORY_UNKNOWN = 0,
+    AMF_MEMORY_HOST = 1,
+    AMF_MEMORY_DX9 = 2,
+    AMF_MEMORY_DX11 = 3,
+    AMF_MEMORY_OPENCL = 4,
+    AMF_MEMORY_OPENGL = 5,
+    AMF_MEMORY_XV = 6,
+    AMF_MEMORY_GRALLOC = 7,
+    AMF_MEMORY_COMPUTE_FOR_DX9 = 8,
+    AMF_MEMORY_COMPUTE_FOR_DX11 = 9,
+} AMF_MEMORY_TYPE;
+
+//----------------------------------------------------------------------------------------------
+typedef enum AMF_DX_VERSION
+{
+    AMF_DX9 = 90,
+    AMF_DX9_EX = 91,
+    AMF_DX11_0 = 110,
+    AMF_DX11_1 = 111
+} AMF_DX_VERSION;
+
+typedef struct AMFData AMFData;
+AMF_DECLARE_IID(AMFData, 0xa1159bf6, 0x9104, 0x4107, 0x8e, 0xaa, 0xc5, 0x3d, 0x5d, 0xba, 0xc5, 0x11)
+
+typedef struct AMFDataVtbl
+{
+    // AMFInterface interface
+    amf_long(AMF_STD_CALL *Acquire)(AMFData* pThis);
+    amf_long(AMF_STD_CALL *Release)(AMFData* pThis);
+    enum AMF_RESULT(AMF_STD_CALL *QueryInterface)(AMFData* pThis, const struct AMFGuid *interfaceID, void** ppInterface);
+
+    // AMFPropertyStorage interface
+    AMF_RESULT(AMF_STD_CALL *SetProperty)(AMFData* pThis, const wchar_t* name, AMFVariantStruct value);
+    AMF_RESULT(AMF_STD_CALL *GetProperty)(AMFData* pThis, const wchar_t* name, AMFVariantStruct* pValue);
+    amf_bool(AMF_STD_CALL *HasProperty)(AMFData* pThis, const wchar_t* name);
+    amf_size(AMF_STD_CALL *GetPropertyCount)(AMFData* pThis);
+    AMF_RESULT(AMF_STD_CALL *GetPropertyAt)(AMFData* pThis, amf_size index, wchar_t* name, amf_size nameSize, AMFVariantStruct* pValue);
+    AMF_RESULT(AMF_STD_CALL *Clear)(AMFData* pThis);
+    AMF_RESULT(AMF_STD_CALL *AddTo)(AMFData* pThis, AMFPropertyStorage* pDest, amf_bool overwrite, amf_bool deep);
+    AMF_RESULT(AMF_STD_CALL *CopyTo)(AMFData* pThis, AMFPropertyStorage* pDest, amf_bool deep);
+    void                (AMF_STD_CALL *AddObserver)(AMFData* pThis, AMFPropertyStorageObserver* pObserver);
+    void                (AMF_STD_CALL *RemoveObserver)(AMFData* pThis, AMFPropertyStorageObserver* pObserver);
+
+    // AMFData interface
+
+    AMF_MEMORY_TYPE(AMF_STD_CALL *GetMemoryType)(AMFData* pThis);
+
+    AMF_RESULT(AMF_STD_CALL *Duplicate)(AMFData* pThis, AMF_MEMORY_TYPE type, AMFData** ppData);
+    AMF_RESULT(AMF_STD_CALL *Convert)(AMFData* pThis, AMF_MEMORY_TYPE type); // optimal interop if possilble. Copy through host memory if needed
+    AMF_RESULT(AMF_STD_CALL *Interop)(AMFData* pThis, AMF_MEMORY_TYPE type); // only optimal interop if possilble. No copy through host memory for GPU objects
+
+    AMF_DATA_TYPE(AMF_STD_CALL *GetDataType)(AMFData* pThis);
+
+    amf_bool(AMF_STD_CALL *IsReusable)(AMFData* pThis);
+
+    void                (AMF_STD_CALL *SetPts)(AMFData* pThis, amf_pts pts);
+    amf_pts(AMF_STD_CALL *GetPts)(AMFData* pThis);
+    void                (AMF_STD_CALL *SetDuration)(AMFData* pThis, amf_pts duration);
+    amf_pts(AMF_STD_CALL *GetDuration)(AMFData* pThis);
+
+} AMFDataVtbl;
+
+struct AMFData
+{
+    const AMFDataVtbl *pVtbl;
+};
+//-----------------------------------------------------------------------------
+// Plane.h
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+typedef enum AMF_PLANE_TYPE
+{
+    AMF_PLANE_UNKNOWN = 0,
+    AMF_PLANE_PACKED = 1,             // for all packed formats: BGRA, YUY2, etc
+    AMF_PLANE_Y = 2,
+    AMF_PLANE_UV = 3,
+    AMF_PLANE_U = 4,
+    AMF_PLANE_V = 5,
+} AMF_PLANE_TYPE;
+
+//---------------------------------------------------------------------------------------------
+// AMFPlane interface
+//---------------------------------------------------------------------------------------------
+AMF_DECLARE_IID(AMFPlane, 0xbede1aa6, 0xd8fa, 0x4625, 0x94, 0x65, 0x6c, 0x82, 0xc4, 0x37, 0x71, 0x2e)
+typedef struct AMFPlane AMFPlane;
+typedef struct AMFPlaneVtbl
+{
+    // AMFInterface interface
+    amf_long(AMF_STD_CALL *Acquire)(AMFPlane* pThis);
+    amf_long(AMF_STD_CALL *Release)(AMFPlane* pThis);
+    enum AMF_RESULT(AMF_STD_CALL *QueryInterface)(AMFPlane* pThis, const struct AMFGuid *interfaceID, void** ppInterface);
+
+    // AMFPlane interface
+    AMF_PLANE_TYPE(AMF_STD_CALL *GetType)(AMFPlane* pThis);
+    void*               (AMF_STD_CALL *GetNative)(AMFPlane* pThis);
+    amf_int32(AMF_STD_CALL *GetPixelSizeInBytes)(AMFPlane* pThis);
+    amf_int32(AMF_STD_CALL *GetOffsetX)(AMFPlane* pThis);
+    amf_int32(AMF_STD_CALL *GetOffsetY)(AMFPlane* pThis);
+    amf_int32(AMF_STD_CALL *GetWidth)(AMFPlane* pThis);
+    amf_int32(AMF_STD_CALL *GetHeight)(AMFPlane* pThis);
+    amf_int32(AMF_STD_CALL *GetHPitch)(AMFPlane* pThis);
+    amf_int32(AMF_STD_CALL *GetVPitch)(AMFPlane* pThis);
+    amf_bool(AMF_STD_CALL *IsTiled)(AMFPlane* pThis);
+
+} AMFPlaneVtbl;
+
+struct AMFPlane
+{
+    const AMFPlaneVtbl *pVtbl;
+};
+//-----------------------------------------------------------------------------
+// Buffer.h
+//-----------------------------------------------------------------------------
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning(disable : 4263)
+#pragma warning(disable : 4264)
+#endif
+
+typedef struct AMFBuffer AMFBuffer;
+typedef struct AMFBufferObserver AMFBufferObserver;
+
+AMF_DECLARE_IID(AMFBuffer, 0xb04b7248, 0xb6f0, 0x4321, 0xb6, 0x91, 0xba, 0xa4, 0x74, 0xf, 0x9f, 0xcb)
+
+typedef struct AMFBufferVtbl
+{
+    // AMFInterface interface
+    amf_long(AMF_STD_CALL *Acquire)(AMFBuffer* pThis);
+    amf_long(AMF_STD_CALL *Release)(AMFBuffer* pThis);
+    enum AMF_RESULT(AMF_STD_CALL *QueryInterface)(AMFBuffer* pThis, const struct AMFGuid *interfaceID, void** ppInterface);
+
+    // AMFPropertyStorage interface
+    AMF_RESULT(AMF_STD_CALL *SetProperty)(AMFBuffer* pThis, const wchar_t* name, AMFVariantStruct value);
+    AMF_RESULT(AMF_STD_CALL *GetProperty)(AMFBuffer* pThis, const wchar_t* name, AMFVariantStruct* pValue);
+    amf_bool(AMF_STD_CALL *HasProperty)(AMFBuffer* pThis, const wchar_t* name);
+    amf_size(AMF_STD_CALL *GetPropertyCount)(AMFBuffer* pThis);
+    AMF_RESULT(AMF_STD_CALL *GetPropertyAt)(AMFBuffer* pThis, amf_size index, wchar_t* name, amf_size nameSize, AMFVariantStruct* pValue);
+    AMF_RESULT(AMF_STD_CALL *Clear)(AMFBuffer* pThis);
+    AMF_RESULT(AMF_STD_CALL *AddTo)(AMFBuffer* pThis, AMFPropertyStorage* pDest, amf_bool overwrite, amf_bool deep);
+    AMF_RESULT(AMF_STD_CALL *CopyTo)(AMFBuffer* pThis, AMFPropertyStorage* pDest, amf_bool deep);
+    void                (AMF_STD_CALL *AddObserver)(AMFBuffer* pThis, AMFPropertyStorageObserver* pObserver);
+    void                (AMF_STD_CALL *RemoveObserver)(AMFBuffer* pThis, AMFPropertyStorageObserver* pObserver);
+
+    // AMFData interface
+
+    AMF_MEMORY_TYPE(AMF_STD_CALL *GetMemoryType)(AMFBuffer* pThis);
+
+    AMF_RESULT(AMF_STD_CALL *Duplicate)(AMFBuffer* pThis, AMF_MEMORY_TYPE type, AMFData** ppData);
+    AMF_RESULT(AMF_STD_CALL *Convert)(AMFBuffer* pThis, AMF_MEMORY_TYPE type); // optimal interop if possilble. Copy through host memory if needed
+    AMF_RESULT(AMF_STD_CALL *Interop)(AMFBuffer* pThis, AMF_MEMORY_TYPE type); // only optimal interop if possilble. No copy through host memory for GPU objects
+
+    AMF_DATA_TYPE(AMF_STD_CALL *GetDataType)(AMFBuffer* pThis);
+
+    amf_bool(AMF_STD_CALL *IsReusable)(AMFBuffer* pThis);
+
+    void                (AMF_STD_CALL *SetPts)(AMFBuffer* pThis, amf_pts pts);
+    amf_pts(AMF_STD_CALL *GetPts)(AMFBuffer* pThis);
+    void                (AMF_STD_CALL *SetDuration)(AMFBuffer* pThis, amf_pts duration);
+    amf_pts(AMF_STD_CALL *GetDuration)(AMFBuffer* pThis);
+
+    // AMFBuffer interface
+
+    AMF_RESULT(AMF_STD_CALL *SetSize)(AMFBuffer* pThis, amf_size newSize);
+    amf_size(AMF_STD_CALL *GetSize)(AMFBuffer* pThis);
+    void*               (AMF_STD_CALL *GetNative)(AMFBuffer* pThis);
+
+    // Observer management
+    void                (AMF_STD_CALL *AddObserver_Buffer)(AMFBuffer* pThis, AMFBufferObserver* pObserver);
+    void                (AMF_STD_CALL *RemoveObserver_Buffer)(AMFBuffer* pThis, AMFBufferObserver* pObserver);
+
+} AMFBufferVtbl;
+
+struct AMFBuffer
+{
+    const AMFBufferVtbl *pVtbl;
+};
+
+//-----------------------------------------------------------------------------
+// AudioBuffer.h
+//-----------------------------------------------------------------------------
+typedef enum AMF_AUDIO_FORMAT
+{
+    AMFAF_UNKNOWN = -1,
+    AMFAF_U8 = 0,               // amf_uint8
+    AMFAF_S16 = 1,               // amf_int16
+    AMFAF_S32 = 2,               // amf_int32
+    AMFAF_FLT = 3,               // amf_float
+    AMFAF_DBL = 4,               // amf_double
+
+    AMFAF_U8P = 5,               // amf_uint8
+    AMFAF_S16P = 6,               // amf_int16
+    AMFAF_S32P = 7,               // amf_int32
+    AMFAF_FLTP = 8,               // amf_float
+    AMFAF_DBLP = 9,               // amf_double
+    AMFAF_FIRST = AMFAF_U8,
+    AMFAF_LAST = AMFAF_DBLP,
+} AMF_AUDIO_FORMAT;
+
+typedef struct AMFAudioBuffer AMFAudioBuffer;
+typedef struct AMFAudioBufferObserver AMFAudioBufferObserver;
+//-----------------------------------------------------------------------------
+// Surface.h
+//-----------------------------------------------------------------------------
+
+typedef enum AMF_SURFACE_FORMAT
+{
+    AMF_SURFACE_UNKNOWN = 0,
+    AMF_SURFACE_NV12,               ///< 1 - planar Y width x height + packed UV width/2 x height/2 - 8 bit per component
+    AMF_SURFACE_YV12,               ///< 2 - planar Y width x height + V width/2 x height/2 + U width/2 x height/2 - 8 bit per component
+    AMF_SURFACE_BGRA,               ///< 3 - packed - 8 bit per component
+    AMF_SURFACE_ARGB,               ///< 4 - packed - 8 bit per component
+    AMF_SURFACE_RGBA,               ///< 5 - packed - 8 bit per component
+    AMF_SURFACE_GRAY8,              ///< 6 - single component - 8 bit
+    AMF_SURFACE_YUV420P,            ///< 7 - planar Y width x height + U width/2 x height/2 + V width/2 x height/2 - 8 bit per component
+    AMF_SURFACE_U8V8,               ///< 8 - double component - 8 bit per component
+    AMF_SURFACE_YUY2,               ///< 9 - YUY2: Byte 0=8-bit Y'0; Byte 1=8-bit Cb; Byte 2=8-bit Y'1; Byte 3=8-bit Cr
+    AMF_SURFACE_P010,               ///< 10- planar Y width x height + packed UV width/2 x height/2 - 10 bit per component (16 allocated, upper 10 bits are used)
+    AMF_SURFACE_RGBA_F16,           ///< 11 - packed - 16 bit per component float
+
+    AMF_SURFACE_FIRST = AMF_SURFACE_NV12,
+    AMF_SURFACE_LAST = AMF_SURFACE_RGBA_F16
+} AMF_SURFACE_FORMAT;
+
+//----------------------------------------------------------------------------------------------
+// frame type
+//----------------------------------------------------------------------------------------------
+typedef enum AMF_FRAME_TYPE
+{
+    // flags
+    AMF_FRAME_STEREO_FLAG = 0x10000000,
+    AMF_FRAME_LEFT_FLAG = AMF_FRAME_STEREO_FLAG | 0x20000000,
+    AMF_FRAME_RIGHT_FLAG = AMF_FRAME_STEREO_FLAG | 0x40000000,
+    AMF_FRAME_BOTH_FLAG = AMF_FRAME_LEFT_FLAG | AMF_FRAME_RIGHT_FLAG,
+    AMF_FRAME_INTERLEAVED_FLAG = 0x01000000,
+    AMF_FRAME_FIELD_FLAG = 0x02000000,
+    AMF_FRAME_EVEN_FLAG = 0x04000000,
+    AMF_FRAME_ODD_FLAG = 0x08000000,
+
+    // values
+    AMF_FRAME_UNKNOWN = -1,
+    AMF_FRAME_PROGRESSIVE = 0,
+
+    AMF_FRAME_INTERLEAVED_EVEN_FIRST = AMF_FRAME_INTERLEAVED_FLAG | AMF_FRAME_EVEN_FLAG,
+    AMF_FRAME_INTERLEAVED_ODD_FIRST = AMF_FRAME_INTERLEAVED_FLAG | AMF_FRAME_ODD_FLAG,
+    AMF_FRAME_FIELD_SINGLE_EVEN = AMF_FRAME_FIELD_FLAG | AMF_FRAME_EVEN_FLAG,
+    AMF_FRAME_FIELD_SINGLE_ODD = AMF_FRAME_FIELD_FLAG | AMF_FRAME_ODD_FLAG,
+
+    AMF_FRAME_STEREO_LEFT = AMF_FRAME_LEFT_FLAG,
+    AMF_FRAME_STEREO_RIGHT = AMF_FRAME_RIGHT_FLAG,
+    AMF_FRAME_STEREO_BOTH = AMF_FRAME_BOTH_FLAG,
+
+    AMF_FRAME_INTERLEAVED_EVEN_FIRST_STEREO_LEFT = AMF_FRAME_INTERLEAVED_FLAG | AMF_FRAME_EVEN_FLAG | AMF_FRAME_LEFT_FLAG,
+    AMF_FRAME_INTERLEAVED_EVEN_FIRST_STEREO_RIGHT = AMF_FRAME_INTERLEAVED_FLAG | AMF_FRAME_EVEN_FLAG | AMF_FRAME_RIGHT_FLAG,
+    AMF_FRAME_INTERLEAVED_EVEN_FIRST_STEREO_BOTH = AMF_FRAME_INTERLEAVED_FLAG | AMF_FRAME_EVEN_FLAG | AMF_FRAME_BOTH_FLAG,
+
+    AMF_FRAME_INTERLEAVED_ODD_FIRST_STEREO_LEFT = AMF_FRAME_INTERLEAVED_FLAG | AMF_FRAME_ODD_FLAG | AMF_FRAME_LEFT_FLAG,
+    AMF_FRAME_INTERLEAVED_ODD_FIRST_STEREO_RIGHT = AMF_FRAME_INTERLEAVED_FLAG | AMF_FRAME_ODD_FLAG | AMF_FRAME_RIGHT_FLAG,
+    AMF_FRAME_INTERLEAVED_ODD_FIRST_STEREO_BOTH = AMF_FRAME_INTERLEAVED_FLAG | AMF_FRAME_ODD_FLAG | AMF_FRAME_BOTH_FLAG,
+} AMF_FRAME_TYPE;
+
+typedef struct AMFSurface AMFSurface;
+typedef struct AMFSurfaceObserver AMFSurfaceObserver;
+
+typedef struct AMFSurfaceObserverVtbl
+{
+    void                (AMF_STD_CALL *OnSurfaceDataRelease)(AMFSurfaceObserver* pThis, AMFSurface* pSurface);
+} AMFSurfaceObserverVtbl;
+
+struct AMFSurfaceObserver
+{
+    const AMFSurfaceObserverVtbl *pVtbl;
+};
+
+AMF_DECLARE_IID(AMFSurface, 0x3075dbe3, 0x8718, 0x4cfa, 0x86, 0xfb, 0x21, 0x14, 0xc0, 0xa5, 0xa4, 0x51)
+typedef struct AMFSurfaceVtbl
+{
+    // AMFInterface interface
+    amf_long(AMF_STD_CALL *Acquire)(AMFSurface* pThis);
+    amf_long(AMF_STD_CALL *Release)(AMFSurface* pThis);
+    enum AMF_RESULT(AMF_STD_CALL *QueryInterface)(AMFSurface* pThis, const struct AMFGuid *interfaceID, void** ppInterface);
+
+    // AMFPropertyStorage interface
+    AMF_RESULT(AMF_STD_CALL *SetProperty)(AMFSurface* pThis, const wchar_t* name, AMFVariantStruct value);
+    AMF_RESULT(AMF_STD_CALL *GetProperty)(AMFSurface* pThis, const wchar_t* name, AMFVariantStruct* pValue);
+    amf_bool(AMF_STD_CALL *HasProperty)(AMFSurface* pThis, const wchar_t* name);
+    amf_size(AMF_STD_CALL *GetPropertyCount)(AMFSurface* pThis);
+    AMF_RESULT(AMF_STD_CALL *GetPropertyAt)(AMFSurface* pThis, amf_size index, wchar_t* name, amf_size nameSize, AMFVariantStruct* pValue);
+    AMF_RESULT(AMF_STD_CALL *Clear)(AMFSurface* pThis);
+    AMF_RESULT(AMF_STD_CALL *AddTo)(AMFSurface* pThis, AMFPropertyStorage* pDest, amf_bool overwrite, amf_bool deep);
+    AMF_RESULT(AMF_STD_CALL *CopyTo)(AMFSurface* pThis, AMFPropertyStorage* pDest, amf_bool deep);
+    void                (AMF_STD_CALL *AddObserver)(AMFSurface* pThis, AMFPropertyStorageObserver* pObserver);
+    void                (AMF_STD_CALL *RemoveObserver)(AMFSurface* pThis, AMFPropertyStorageObserver* pObserver);
+
+    // AMFData interface
+
+    AMF_MEMORY_TYPE(AMF_STD_CALL *GetMemoryType)(AMFSurface* pThis);
+
+    AMF_RESULT(AMF_STD_CALL *Duplicate)(AMFSurface* pThis, AMF_MEMORY_TYPE type, AMFData** ppData);
+    AMF_RESULT(AMF_STD_CALL *Convert)(AMFSurface* pThis, AMF_MEMORY_TYPE type); // optimal interop if possilble. Copy through host memory if needed
+    AMF_RESULT(AMF_STD_CALL *Interop)(AMFSurface* pThis, AMF_MEMORY_TYPE type); // only optimal interop if possilble. No copy through host memory for GPU objects
+
+    AMF_DATA_TYPE(AMF_STD_CALL *GetDataType)(AMFSurface* pThis);
+
+    amf_bool(AMF_STD_CALL *IsReusable)(AMFSurface* pThis);
+
+    void                (AMF_STD_CALL *SetPts)(AMFSurface* pThis, amf_pts pts);
+    amf_pts(AMF_STD_CALL *GetPts)(AMFSurface* pThis);
+    void                (AMF_STD_CALL *SetDuration)(AMFSurface* pThis, amf_pts duration);
+    amf_pts(AMF_STD_CALL *GetDuration)(AMFSurface* pThis);
+
+    // AMFSurface interface
+
+    AMF_SURFACE_FORMAT(AMF_STD_CALL *GetFormat)(AMFSurface* pThis);
+
+    // do not store planes outside. should be used together with Surface
+    amf_size(AMF_STD_CALL *GetPlanesCount)(AMFSurface* pThis);
+    AMFPlane*           (AMF_STD_CALL *GetPlaneAt)(AMFSurface* pThis, amf_size index);
+    AMFPlane*           (AMF_STD_CALL *GetPlane)(AMFSurface* pThis, AMF_PLANE_TYPE type);
+
+    AMF_FRAME_TYPE(AMF_STD_CALL *GetFrameType)(AMFSurface* pThis);
+    void                (AMF_STD_CALL *SetFrameType)(AMFSurface* pThis, AMF_FRAME_TYPE type);
+
+    AMF_RESULT(AMF_STD_CALL *SetCrop)(AMFSurface* pThis, amf_int32 x, amf_int32 y, amf_int32 width, amf_int32 height);
+    AMF_RESULT(AMF_STD_CALL *CopySurfaceRegion)(AMFSurface* pThis, AMFSurface* pDest, amf_int32 dstX, amf_int32 dstY, amf_int32 srcX, amf_int32 srcY, amf_int32 width, amf_int32 height);
+
+
+    // Observer management
+    void                (AMF_STD_CALL *AddObserver_Surface)(AMFSurface* pThis, AMFSurfaceObserver* pObserver);
+    void                (AMF_STD_CALL *RemoveObserver_Surface)(AMFSurface* pThis, AMFSurfaceObserver* pObserver);
+
+} AMFSurfaceVtbl;
+
+struct AMFSurface
+{
+    const AMFSurfaceVtbl *pVtbl;
+};
+
+#define   AMFTextureArrayIndexGUIDDef { 0x28115527, 0xe7c3, 0x4b66,{ 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } }
+
+//-----------------------------------------------------------------------------
+// Component.h
+//-----------------------------------------------------------------------------
+AMF_DECLARE_IID(AMFComponent, 0x8b51e5e4, 0x455d, 0x4034, 0xa7, 0x46, 0xde, 0x1b, 0xed, 0xc3, 0xc4, 0x6)
+typedef struct AMFComponent AMFComponent;
+typedef struct AMFContext AMFContext;
+typedef struct AMFIOCaps AMFIOCaps;
+typedef struct AMFCaps AMFCaps;
+
+typedef struct AMFDataAllocatorCB AMFDataAllocatorCB;
+typedef struct AMFComponentOptimizationCallback AMFComponentOptimizationCallback;
+
+typedef struct AMFComponentVtbl
+{
+    // AMFInterface interface
+    amf_long(AMF_STD_CALL *Acquire)(AMFComponent* pThis);
+    amf_long(AMF_STD_CALL *Release)(AMFComponent* pThis);
+    enum AMF_RESULT(AMF_STD_CALL *QueryInterface)(AMFComponent* pThis, const struct AMFGuid *interfaceID, void** ppInterface);
+
+    // AMFPropertyStorage interface
+    AMF_RESULT(AMF_STD_CALL *SetProperty)(AMFComponent* pThis, const wchar_t* name, AMFVariantStruct value);
+    AMF_RESULT(AMF_STD_CALL *GetProperty)(AMFComponent* pThis, const wchar_t* name, AMFVariantStruct* pValue);
+    amf_bool(AMF_STD_CALL *HasProperty)(AMFComponent* pThis, const wchar_t* name);
+    amf_size(AMF_STD_CALL *GetPropertyCount)(AMFComponent* pThis);
+    AMF_RESULT(AMF_STD_CALL *GetPropertyAt)(AMFComponent* pThis, amf_size index, wchar_t* name, amf_size nameSize, AMFVariantStruct* pValue);
+    AMF_RESULT(AMF_STD_CALL *Clear)(AMFComponent* pThis);
+    AMF_RESULT(AMF_STD_CALL *AddTo)(AMFComponent* pThis, AMFPropertyStorage* pDest, amf_bool overwrite, amf_bool deep);
+    AMF_RESULT(AMF_STD_CALL *CopyTo)(AMFComponent* pThis, AMFPropertyStorage* pDest, amf_bool deep);
+    void                (AMF_STD_CALL *AddObserver)(AMFComponent* pThis, AMFPropertyStorageObserver* pObserver);
+    void                (AMF_STD_CALL *RemoveObserver)(AMFComponent* pThis, AMFPropertyStorageObserver* pObserver);
+
+    // AMFPropertyStorageEx interface
+
+    amf_size(AMF_STD_CALL *GetPropertiesInfoCount)(AMFComponent* pThis);
+    AMF_RESULT(AMF_STD_CALL *GetPropertyInfoAt)(AMFComponent* pThis, amf_size index, const AMFPropertyInfo** ppInfo);
+    AMF_RESULT(AMF_STD_CALL *GetPropertyInfo)(AMFComponent* pThis, const wchar_t* name, const AMFPropertyInfo** ppInfo);
+    AMF_RESULT(AMF_STD_CALL *ValidateProperty)(AMFComponent* pThis, const wchar_t* name, AMFVariantStruct value, AMFVariantStruct* pOutValidated);
+
+    // AMFComponent interface
+
+    AMF_RESULT(AMF_STD_CALL *Init)(AMFComponent* pThis, AMF_SURFACE_FORMAT format, amf_int32 width, amf_int32 height);
+    AMF_RESULT(AMF_STD_CALL *ReInit)(AMFComponent* pThis, amf_int32 width, amf_int32 height);
+    AMF_RESULT(AMF_STD_CALL *Terminate)(AMFComponent* pThis);
+    AMF_RESULT(AMF_STD_CALL *Drain)(AMFComponent* pThis);
+    AMF_RESULT(AMF_STD_CALL *Flush)(AMFComponent* pThis);
+
+    AMF_RESULT(AMF_STD_CALL *SubmitInput)(AMFComponent* pThis, AMFData* pData);
+    AMF_RESULT(AMF_STD_CALL *QueryOutput)(AMFComponent* pThis, AMFData** ppData);
+    AMFContext* (AMF_STD_CALL *GetContext)(AMFComponent* pThis);
+    AMF_RESULT(AMF_STD_CALL *SetOutputDataAllocatorCB)(AMFComponent* pThis, AMFDataAllocatorCB* callback);
+
+    AMF_RESULT(AMF_STD_CALL *GetCaps)(AMFComponent* pThis, AMFCaps** ppCaps);
+    AMF_RESULT(AMF_STD_CALL *Optimize)(AMFComponent* pThis, AMFComponentOptimizationCallback* pCallback);
+} AMFComponentVtbl;
+
+struct AMFComponent
+{
+    const AMFComponentVtbl *pVtbl;
+};
+
+//-----------------------------------------------------------------------------
+// Context.h
+//-----------------------------------------------------------------------------
+typedef struct AMFCompute AMFCompute;
+typedef struct AMFComputeFactory AMFComputeFactory;
+typedef struct AMFComputeDevice AMFComputeDevice;
+typedef struct AMFContext AMFContext;
+AMF_DECLARE_IID(AMFContext, 0xa76a13f0, 0xd80e, 0x4fcc, 0xb5, 0x8, 0x65, 0xd0, 0xb5, 0x2e, 0xd9, 0xee)
+
+typedef struct AMFContextVtbl
+{
+    // AMFInterface interface
+    amf_long(AMF_STD_CALL *Acquire)(AMFContext* pThis);
+    amf_long(AMF_STD_CALL *Release)(AMFContext* pThis);
+    enum AMF_RESULT(AMF_STD_CALL *QueryInterface)(AMFContext* pThis, const struct AMFGuid *interfaceID, void** ppInterface);
+
+    // AMFInterface AMFPropertyStorage
+
+    AMF_RESULT(AMF_STD_CALL *SetProperty)(AMFContext* pThis, const wchar_t* name, AMFVariantStruct value);
+    AMF_RESULT(AMF_STD_CALL *GetProperty)(AMFContext* pThis, const wchar_t* name, AMFVariantStruct* pValue);
+    amf_bool(AMF_STD_CALL *HasProperty)(AMFContext* pThis, const wchar_t* name);
+    amf_size(AMF_STD_CALL *GetPropertyCount)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *GetPropertyAt)(AMFContext* pThis, amf_size index, wchar_t* name, amf_size nameSize, AMFVariantStruct* pValue);
+    AMF_RESULT(AMF_STD_CALL *Clear)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *AddTo)(AMFContext* pThis, AMFPropertyStorage* pDest, amf_bool overwrite, amf_bool deep);
+    AMF_RESULT(AMF_STD_CALL *CopyTo)(AMFContext* pThis, AMFPropertyStorage* pDest, amf_bool deep);
+    void                (AMF_STD_CALL *AddObserver)(AMFContext* pThis, AMFPropertyStorageObserver* pObserver);
+    void                (AMF_STD_CALL *RemoveObserver)(AMFContext* pThis, AMFPropertyStorageObserver* pObserver);
+
+    // AMFContext interface
+
+    // Cleanup
+    AMF_RESULT(AMF_STD_CALL *Terminate)(AMFContext* pThis);
+
+    // DX9
+    AMF_RESULT(AMF_STD_CALL *InitDX9)(AMFContext* pThis, void* pDX9Device);
+    void*               (AMF_STD_CALL *GetDX9Device)(AMFContext* pThis, AMF_DX_VERSION dxVersionRequired);
+    AMF_RESULT(AMF_STD_CALL *LockDX9)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *UnlockDX9)(AMFContext* pThis);
+    // DX11
+    AMF_RESULT(AMF_STD_CALL *InitDX11)(AMFContext* pThis, void* pDX11Device, AMF_DX_VERSION dxVersionRequired);
+    void*               (AMF_STD_CALL *GetDX11Device)(AMFContext* pThis, AMF_DX_VERSION dxVersionRequired);
+    AMF_RESULT(AMF_STD_CALL *LockDX11)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *UnlockDX11)(AMFContext* pThis);
+
+    // OpenCL
+    AMF_RESULT(AMF_STD_CALL *InitOpenCL)(AMFContext* pThis, void* pCommandQueue);
+    void*               (AMF_STD_CALL *GetOpenCLContext)(AMFContext* pThis);
+    void*               (AMF_STD_CALL *GetOpenCLCommandQueue)(AMFContext* pThis);
+    void*               (AMF_STD_CALL *GetOpenCLDeviceID)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *GetOpenCLComputeFactory)(AMFContext* pThis, AMFComputeFactory **ppFactory); // advanced compute - multiple queries
+    AMF_RESULT(AMF_STD_CALL *InitOpenCLEx)(AMFContext* pThis, AMFComputeDevice *pDevice);
+    AMF_RESULT(AMF_STD_CALL *LockOpenCL)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *UnlockOpenCL)(AMFContext* pThis);
+
+    // OpenGL
+    AMF_RESULT(AMF_STD_CALL *InitOpenGL)(AMFContext* pThis, amf_handle hOpenGLContext, amf_handle hWindow, amf_handle hDC);
+    amf_handle(AMF_STD_CALL *GetOpenGLContext)(AMFContext* pThis);
+    amf_handle(AMF_STD_CALL *GetOpenGLDrawable)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *LockOpenGL)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *UnlockOpenGL)(AMFContext* pThis);
+    // XV - Linux
+    AMF_RESULT(AMF_STD_CALL *InitXV)(AMFContext* pThis, void* pXVDevice);
+    void*               (AMF_STD_CALL *GetXVDevice)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *LockXV)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *UnlockXV)(AMFContext* pThis);
+
+    // Gralloc - Android
+    AMF_RESULT(AMF_STD_CALL *InitGralloc)(AMFContext* pThis, void* pGrallocDevice);
+    void*               (AMF_STD_CALL *GetGrallocDevice)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *LockGralloc)(AMFContext* pThis);
+    AMF_RESULT(AMF_STD_CALL *UnlockGralloc)(AMFContext* pThis);
+    // Allocation
+    AMF_RESULT(AMF_STD_CALL *AllocBuffer)(AMFContext* pThis, AMF_MEMORY_TYPE type, amf_size size, AMFBuffer** ppBuffer);
+    AMF_RESULT(AMF_STD_CALL *AllocSurface)(AMFContext* pThis, AMF_MEMORY_TYPE type, AMF_SURFACE_FORMAT format, amf_int32 width, amf_int32 height, AMFSurface** ppSurface);
+    AMF_RESULT(AMF_STD_CALL *AllocAudioBuffer)(AMFContext* pThis, AMF_MEMORY_TYPE type, AMF_AUDIO_FORMAT format, amf_int32 samples, amf_int32 sampleRate, amf_int32 channels,
+        AMFAudioBuffer** ppAudioBuffer);
+
+    // Wrap existing objects
+    AMF_RESULT(AMF_STD_CALL *CreateBufferFromHostNative)(AMFContext* pThis, void* pHostBuffer, amf_size size, AMFBuffer** ppBuffer, AMFBufferObserver* pObserver);
+    AMF_RESULT(AMF_STD_CALL *CreateSurfaceFromHostNative)(AMFContext* pThis, AMF_SURFACE_FORMAT format, amf_int32 width, amf_int32 height, amf_int32 hPitch, amf_int32 vPitch, void* pData,
+        AMFSurface** ppSurface, AMFSurfaceObserver* pObserver);
+    AMF_RESULT(AMF_STD_CALL *CreateSurfaceFromDX9Native)(AMFContext* pThis, void* pDX9Surface, AMFSurface** ppSurface, AMFSurfaceObserver* pObserver);
+    AMF_RESULT(AMF_STD_CALL *CreateSurfaceFromDX11Native)(AMFContext* pThis, void* pDX11Surface, AMFSurface** ppSurface, AMFSurfaceObserver* pObserver);
+    AMF_RESULT(AMF_STD_CALL *CreateSurfaceFromOpenGLNative)(AMFContext* pThis, AMF_SURFACE_FORMAT format, amf_handle hGLTextureID, AMFSurface** ppSurface, AMFSurfaceObserver* pObserver);
+    AMF_RESULT(AMF_STD_CALL *CreateSurfaceFromGrallocNative)(AMFContext* pThis, amf_handle hGrallocSurface, AMFSurface** ppSurface, AMFSurfaceObserver* pObserver);
+    AMF_RESULT(AMF_STD_CALL *CreateSurfaceFromOpenCLNative)(AMFContext* pThis, AMF_SURFACE_FORMAT format, amf_int32 width, amf_int32 height, void** pClPlanes,
+        AMFSurface** ppSurface, AMFSurfaceObserver* pObserver);
+    AMF_RESULT(AMF_STD_CALL *CreateBufferFromOpenCLNative)(AMFContext* pThis, void* pCLBuffer, amf_size size, AMFBuffer** ppBuffer);
+
+    // Access to AMFCompute interface - AMF_MEMORY_OPENCL, AMF_MEMORY_COMPUTE_FOR_DX9, AMF_MEMORY_COMPUTE_FOR_DX11 are currently supported
+    AMF_RESULT(AMF_STD_CALL *GetCompute)(AMFContext* pThis, AMF_MEMORY_TYPE eMemType, AMFCompute** ppCompute);
+
+} AMFContextVtbl;
+
+struct AMFContext
+{
+    const AMFContextVtbl *pVtbl;
+};
+
+//-----------------------------------------------------------------------------
+// Debug.h 
+//-----------------------------------------------------------------------------
+
+typedef struct AMFDebug AMFDebug;
+typedef struct AMFDebugVtbl
+{
+    // AMFDebug interface
+    void               (AMF_STD_CALL *EnablePerformanceMonitor)(AMFDebug* pThis, amf_bool enable);
+    amf_bool(AMF_STD_CALL *PerformanceMonitorEnabled)(AMFDebug* pThis);
+    void               (AMF_STD_CALL *AssertsEnable)(AMFDebug* pThis, amf_bool enable);
+    amf_bool(AMF_STD_CALL *AssertsEnabled)(AMFDebug* pThis);
+} AMFDebugVtbl;
+
+struct AMFDebug
+{
+    const AMFDebugVtbl *pVtbl;
+};
+
+//-----------------------------------------------------------------------------
+// Trace.h 
+//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------
+// trace levels
+//----------------------------------------------------------------------------------------------
+#define AMF_TRACE_ERROR     0
+#define AMF_TRACE_WARNING   1
+#define AMF_TRACE_INFO      2 // default in sdk
+#define AMF_TRACE_DEBUG     3
+#define AMF_TRACE_TRACE     4
+
+#define AMF_TRACE_TEST      5
+#define AMF_TRACE_NOLOG     100
+
+//----------------------------------------------------------------------------------------------
+// available trace writers
+//----------------------------------------------------------------------------------------------
+#define AMF_TRACE_WRITER_CONSOLE            L"Console"
+#define AMF_TRACE_WRITER_DEBUG_OUTPUT       L"DebugOutput"
+#define AMF_TRACE_WRITER_FILE               L"File"
+
+
+typedef struct AMFTraceWriter AMFTraceWriter;
+
+typedef struct AMFTraceWriterVtbl
+{
+    // AMFTraceWriter interface
+    void (AMF_CDECL_CALL *Write)(AMFTraceWriter* pThis, const wchar_t* scope, const wchar_t* message);
+    void (AMF_CDECL_CALL *Flush)(AMFTraceWriter* pThis);
+} AMFTraceWriterVtbl;
+
+struct AMFTraceWriter
+{
+    const AMFTraceWriterVtbl *pVtbl;
+};
+typedef struct AMFTrace AMFTrace;
+
+typedef struct AMFTraceVtbl
+{
+    // AMFTrace interface
+    void               (AMF_STD_CALL *TraceW)(AMFTrace* pThis, const wchar_t* src_path, amf_int32 line, amf_int32 level, const wchar_t* scope, amf_int32 countArgs, const wchar_t* format, ...);
+    void               (AMF_STD_CALL *Trace)(AMFTrace* pThis, const wchar_t* src_path, amf_int32 line, amf_int32 level, const wchar_t* scope, const wchar_t* message, va_list* pArglist);
+
+    amf_int32(AMF_STD_CALL *SetGlobalLevel)(AMFTrace* pThis, amf_int32 level);
+    amf_int32(AMF_STD_CALL *GetGlobalLevel)(AMFTrace* pThis);
+
+    amf_bool(AMF_STD_CALL *EnableWriter)(AMFTrace* pThis, const wchar_t* writerID, amf_bool enable);
+    amf_bool(AMF_STD_CALL *WriterEnabled)(AMFTrace* pThis, const wchar_t* writerID);
+    AMF_RESULT(AMF_STD_CALL *TraceEnableAsync)(AMFTrace* pThis, amf_bool enable);
+    AMF_RESULT(AMF_STD_CALL *TraceFlush)(AMFTrace* pThis);
+    AMF_RESULT(AMF_STD_CALL *SetPath)(AMFTrace* pThis, const wchar_t* path);
+    AMF_RESULT(AMF_STD_CALL *GetPath)(AMFTrace* pThis, wchar_t* path, amf_size* pSize);
+    amf_int32(AMF_STD_CALL *SetWriterLevel)(AMFTrace* pThis, const wchar_t* writerID, amf_int32 level);
+    amf_int32(AMF_STD_CALL *GetWriterLevel)(AMFTrace* pThis, const wchar_t* writerID);
+    amf_int32(AMF_STD_CALL *SetWriterLevelForScope)(AMFTrace* pThis, const wchar_t* writerID, const wchar_t* scope, amf_int32 level);
+    amf_int32(AMF_STD_CALL *GetWriterLevelForScope)(AMFTrace* pThis, const wchar_t* writerID, const wchar_t* scope);
+
+    amf_int32(AMF_STD_CALL *GetIndentation)(AMFTrace* pThis);
+    void                (AMF_STD_CALL *Indent)(AMFTrace* pThis, amf_int32 addIndent);
+
+    void                (AMF_STD_CALL *RegisterWriter)(AMFTrace* pThis, const wchar_t* writerID, AMFTraceWriter* pWriter, amf_bool enable);
+    void                (AMF_STD_CALL *UnregisterWriter)(AMFTrace* pThis, const wchar_t* writerID);
+
+    const wchar_t*      (AMF_STD_CALL *GetResultText)(AMFTrace* pThis, AMF_RESULT res);
+    const wchar_t*      (AMF_STD_CALL *SurfaceGetFormatName)(AMFTrace* pThis, const AMF_SURFACE_FORMAT eSurfaceFormat);
+    AMF_SURFACE_FORMAT(AMF_STD_CALL *SurfaceGetFormatByName)(AMFTrace* pThis, const wchar_t* name);
+
+    const wchar_t* const (AMF_STD_CALL *GetMemoryTypeName)(AMFTrace* pThis, const AMF_MEMORY_TYPE memoryType);
+    AMF_MEMORY_TYPE(AMF_STD_CALL *GetMemoryTypeByName)(AMFTrace* pThis, const wchar_t* name);
+
+    const wchar_t* const (AMF_STD_CALL *GetSampleFormatName)(AMFTrace* pThis, const AMF_AUDIO_FORMAT eFormat);
+    AMF_AUDIO_FORMAT(AMF_STD_CALL *GetSampleFormatByName)(AMFTrace* pThis, const wchar_t* name);
+} AMFTraceVtbl;
+
+struct AMFTrace
+{
+    const AMFTraceVtbl *pVtbl;
+};
+//-----------------------------------------------------------------------------
+// Factory.h
+//-----------------------------------------------------------------------------
+typedef struct AMFPrograms AMFPrograms;
+
+typedef struct AMFFactory AMFFactory;
+
+typedef struct AMFFactoryVtbl
+{
+    AMF_RESULT(AMF_STD_CALL *CreateContext)(AMFFactory* pThis, AMFContext** ppContext);
+    AMF_RESULT(AMF_STD_CALL *CreateComponent)(AMFFactory* pThis, AMFContext* pContext, const wchar_t* id, AMFComponent** ppComponent);
+    AMF_RESULT(AMF_STD_CALL *SetCacheFolder)(AMFFactory* pThis, const wchar_t* path);
+    const wchar_t*      (AMF_STD_CALL *GetCacheFolder)(AMFFactory* pThis);
+    AMF_RESULT(AMF_STD_CALL *GetDebug)(AMFFactory* pThis, AMFDebug** ppDebug);
+    AMF_RESULT(AMF_STD_CALL *GetTrace)(AMFFactory* pThis, AMFTrace** ppTrace);
+    AMF_RESULT(AMF_STD_CALL *GetPrograms)(AMFFactory* pThis, AMFPrograms** ppPrograms);
+} AMFFactoryVtbl;
+
+struct AMFFactory
+{
+    const AMFFactoryVtbl *pVtbl;
+};
+
+#define AMF_INIT_FUNCTION_NAME             "AMFInit"
+#define AMF_QUERY_VERSION_FUNCTION_NAME    "AMFQueryVersion"
+
+typedef AMF_RESULT(AMF_CDECL_CALL *AMFInit_Fn)(amf_uint64 version, AMFFactory **ppFactory);
+typedef AMF_RESULT(AMF_CDECL_CALL *AMFQueryVersion_Fn)(amf_uint64 *pVersion);
+
+#if defined(_M_AMD64)
+#define AMF_DLL_NAME    L"amfrt64.dll"
+#define AMF_DLL_NAMEA   "amfrt64.dll"
+#else
+#define AMF_DLL_NAME    L"amfrt32.dll"
+#define AMF_DLL_NAMEA   "amfrt32.dll"
+#endif
+
+
+//-----------------------------------------------------------------------------
+// VideoEncoderVCE.h
+//-----------------------------------------------------------------------------
+#define AMFVideoEncoderVCE_AVC L"AMFVideoEncoderVCE_AVC"
+#define AMFVideoEncoderVCE_SVC L"AMFVideoEncoderVCE_SVC"
+
+enum AMF_VIDEO_ENCODER_USAGE_ENUM
+{
+    AMF_VIDEO_ENCODER_USAGE_TRANSCONDING = 0,
+    AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY,
+    AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY,
+    AMF_VIDEO_ENCODER_USAGE_WEBCAM
+};
+
+enum AMF_VIDEO_ENCODER_PROFILE_ENUM
+{
+    AMF_VIDEO_ENCODER_PROFILE_UNKNOWN = 0,
+    AMF_VIDEO_ENCODER_PROFILE_BASELINE = 66,
+    AMF_VIDEO_ENCODER_PROFILE_MAIN = 77,
+    AMF_VIDEO_ENCODER_PROFILE_HIGH = 100,
+    AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_BASELINE = 256,
+    AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH = 257,
+};
+
+enum AMF_VIDEO_ENCODER_SCANTYPE_ENUM
+{
+    AMF_VIDEO_ENCODER_SCANTYPE_PROGRESSIVE = 0,
+    AMF_VIDEO_ENCODER_SCANTYPE_INTERLACED
+};
+
+enum AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_ENUM
+{
+    AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN = -1,
+    AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP = 0,
+    AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR,
+    AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR,
+    AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR
+};
+
+enum AMF_VIDEO_ENCODER_QUALITY_PRESET_ENUM
+{
+    AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED = 0,
+    AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED,
+    AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY
+};
+
+enum AMF_VIDEO_ENCODER_PICTURE_STRUCTURE_ENUM
+{
+    AMF_VIDEO_ENCODER_PICTURE_STRUCTURE_NONE = 0,
+    AMF_VIDEO_ENCODER_PICTURE_STRUCTURE_FRAME,
+    AMF_VIDEO_ENCODER_PICTURE_STRUCTURE_TOP_FIELD,
+    AMF_VIDEO_ENCODER_PICTURE_STRUCTURE_BOTTOM_FIELD
+};
+
+enum AMF_VIDEO_ENCODER_PICTURE_TYPE_ENUM
+{
+    AMF_VIDEO_ENCODER_PICTURE_TYPE_NONE = 0,
+    AMF_VIDEO_ENCODER_PICTURE_TYPE_SKIP,
+    AMF_VIDEO_ENCODER_PICTURE_TYPE_IDR,
+    AMF_VIDEO_ENCODER_PICTURE_TYPE_I,
+    AMF_VIDEO_ENCODER_PICTURE_TYPE_P,
+    AMF_VIDEO_ENCODER_PICTURE_TYPE_B
+};
+
+enum AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_ENUM
+{
+    AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR,
+    AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_I,
+    AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_P,
+    AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_B
+};
+
+enum AMF_VIDEO_ENCODER_PREENCODE_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_PREENCODE_DISABLED = 0,
+    AMF_VIDEO_ENCODER_PREENCODE_ENABLED = 1,
+};
+
+enum AMF_VIDEO_ENCODER_CODING_ENUM
+{
+    AMF_VIDEO_ENCODER_UNDEFINED = 0, // BASELINE = CALV; MAIN, HIGH = CABAC
+    AMF_VIDEO_ENCODER_CABAC,
+    AMF_VIDEO_ENCODER_CALV,
+
+};
+
+
+// Static properties - can be set before Init()
+
+#define AMF_VIDEO_ENCODER_FRAMESIZE                             L"FrameSize"                // AMFSize; default = 0,0; Frame size
+#define AMF_VIDEO_ENCODER_FRAMERATE                             L"FrameRate"                // AMFRate; default = depends on usage; Frame Rate 
+
+#define AMF_VIDEO_ENCODER_EXTRADATA                             L"ExtraData"                // AMFInterface* - > AMFBuffer*; SPS/PPS buffer in Annex B format - read-only
+#define AMF_VIDEO_ENCODER_USAGE                                 L"Usage"                    // amf_int64(AMF_VIDEO_ENCODER_USAGE_ENUM); default = N/A; Encoder usage type. fully configures parameter set. 
+#define AMF_VIDEO_ENCODER_PROFILE                               L"Profile"                  // amf_int64(AMF_VIDEO_ENCODER_PROFILE_ENUM) ; default = AMF_VIDEO_ENCODER_PROFILE_MAIN;  H264 profile
+#define AMF_VIDEO_ENCODER_PROFILE_LEVEL                         L"ProfileLevel"             // amf_int64; default = 42; H264 profile level
+#define AMF_VIDEO_ENCODER_MAX_LTR_FRAMES                        L"MaxOfLTRFrames"           // amf_int64; default = 0; Max number of LTR frames
+#define AMF_VIDEO_ENCODER_SCANTYPE                              L"ScanType"                 // amf_int64(AMF_VIDEO_ENCODER_SCANTYPE_ENUM); default = AMF_VIDEO_ENCODER_SCANTYPE_PROGRESSIVE; indicates input stream type
+#define AMF_VIDEO_ENCODER_MAX_NUM_REFRAMES                      L"MaxNumRefFrames"          // amf_int64; Maximum number of reference frames
+#define AMF_VIDEO_ENCODER_ASPECT_RATIO                          L"AspectRatio"              // AMFRatio; default = 1, 1
+#define AMF_VIDEO_ENCODER_FULL_RANGE_COLOR                      L"FullRangeColor"           // bool; default = false; inidicates that YUV input is (0,255) 
+#define AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE       L"RateControlPreanalysisEnable"     // amf_int64(AMF_VIDEO_ENCODER_PREENCODE_MODE_ENUM); default =  AMF_VIDEO_ENCODER_PREENCODE_DISABLED; controls Pre-analysis assisted rate control 
+
+// Quality preset property
+#define AMF_VIDEO_ENCODER_QUALITY_PRESET                        L"QualityPreset"            // amf_int64(AMF_VIDEO_ENCODER_QUALITY_PRESET_ENUM); default = depends on USAGE; Quality Preset 
+
+
+// Dynamic properties - can be set at any time
+
+// Rate control properties
+#define AMF_VIDEO_ENCODER_B_PIC_DELTA_QP                        L"BPicturesDeltaQP"         // amf_int64; default = depends on USAGE; B-picture Delta
+#define AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP                    L"ReferenceBPicturesDeltaQP"// amf_int64; default = depends on USAGE; Reference B-picture Delta
+
+#define AMF_VIDEO_ENCODER_ENFORCE_HRD                           L"EnforceHRD"               // bool; default = depends on USAGE; Enforce HRD
+#define AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE                    L"FillerDataEnable"         // bool; default = false; Filler Data Enable
+#define AMF_VIDEO_ENCODER_ENABLE_VBAQ                           L"EnableVBAQ"               // bool; default = depends on USAGE; Enable VBAQ
+
+
+#define AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE                       L"VBVBufferSize"            // amf_int64; default = depends on USAGE; VBV Buffer Size in bits
+#define AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS           L"InitialVBVBufferFullness" // amf_int64; default =  64; Initial VBV Buffer Fullness 0=0% 64=100%
+
+#define AMF_VIDEO_ENCODER_MAX_AU_SIZE                           L"MaxAUSize"                // amf_int64; default = 60; Max AU Size in bits
+
+#define AMF_VIDEO_ENCODER_MIN_QP                                L"MinQP"                    // amf_int64; default = depends on USAGE; Min QP; range = 0-51
+#define AMF_VIDEO_ENCODER_MAX_QP                                L"MaxQP"                    // amf_int64; default = depends on USAGE; Max QP; range = 0-51
+#define AMF_VIDEO_ENCODER_QP_I                                  L"QPI"                      // amf_int64; default = 22; I-frame QP; range = 0-51
+#define AMF_VIDEO_ENCODER_QP_P                                  L"QPP"                      // amf_int64; default = 22; P-frame QP; range = 0-51
+#define AMF_VIDEO_ENCODER_QP_B                                  L"QPB"                      // amf_int64; default = 22; B-frame QP; range = 0-51
+#define AMF_VIDEO_ENCODER_TARGET_BITRATE                        L"TargetBitrate"            // amf_int64; default = depends on USAGE; Target bit rate in bits
+#define AMF_VIDEO_ENCODER_PEAK_BITRATE                          L"PeakBitrate"              // amf_int64; default = depends on USAGE; Peak bit rate in bits
+#define AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE        L"RateControlSkipFrameEnable"   // bool; default =  depends on USAGE; Rate Control Based Frame Skip 
+#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD                   L"RateControlMethod"        // amf_int64(AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_ENUM); default = depends on USAGE; Rate Control Method 
+
+// Picture control properties
+#define AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING              L"HeaderInsertionSpacing"   // amf_int64; default = depends on USAGE; Header Insertion Spacing; range 0-1000
+#define AMF_VIDEO_ENCODER_B_PIC_PATTERN                         L"BPicturesPattern"         // amf_int64; default = 3; B-picture Pattern (number of B-Frames)
+#define AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER                    L"DeBlockingFilter"         // bool; default = depends on USAGE; De-blocking Filter
+#define AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE                    L"BReferenceEnable"         // bool; default = true; Enable Refrence to B-frames
+#define AMF_VIDEO_ENCODER_IDR_PERIOD                            L"IDRPeriod"                // amf_int64; default = depends on USAGE; IDR Period in frames
+#define AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT        L"IntraRefreshMBsNumberPerSlot" // amf_int64; default = depends on USAGE; Intra Refresh MBs Number Per Slot in Macroblocks
+#define AMF_VIDEO_ENCODER_SLICES_PER_FRAME                      L"SlicesPerFrame"           // amf_int64; default = 1; Number of slices Per Frame 
+#define AMF_VIDEO_ENCODER_CABAC_ENABLE                          L"CABACEnable"              // amf_int64(AMF_VIDEO_ENCODER_CODING_ENUM) default = AMF_VIDEO_ENCODER_UNDEFINED
+
+// Motion estimation
+#define AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL                     L"HalfPixel"                // bool; default= true; Half Pixel 
+#define AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL                   L"QuarterPixel"             // bool; default= true; Quarter Pixel
+
+// SVC
+#define AMF_VIDEO_ENCODER_NUM_TEMPORAL_ENHANCMENT_LAYERS        L"NumOfTemporalEnhancmentLayers" // amf_int64; default = 0; range = 0, min(2, caps->GetMaxNumOfTemporalLayers()) number of temporal enhancment Layers (SVC)
+
+// Per-submittion properties - can be set on input surface interface
+#define AMF_VIDEO_ENCODER_END_OF_SEQUENCE                       L"EndOfSequence"            // bool; default = false; generate end of sequence
+#define AMF_VIDEO_ENCODER_END_OF_STREAM                         L"EndOfStream"              // bool; default = false; generate end of stream
+#define AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE                    L"ForcePictureType"         // amf_int64(AMF_VIDEO_ENCODER_PICTURE_TYPE_ENUM); default = AMF_VIDEO_ENCODER_PICTURE_TYPE_NONE; generate particular picture type
+#define AMF_VIDEO_ENCODER_INSERT_AUD                            L"InsertAUD"                // bool; default = false; insert AUD
+#define AMF_VIDEO_ENCODER_INSERT_SPS                            L"InsertSPS"                // bool; default = false; insert SPS
+#define AMF_VIDEO_ENCODER_INSERT_PPS                            L"InsertPPS"                // bool; default = false; insert PPS
+#define AMF_VIDEO_ENCODER_PICTURE_STRUCTURE                     L"PictureStructure"         // amf_int64(AMF_VIDEO_ENCODER_PICTURE_STRUCTURE_ENUM); default = AMF_VIDEO_ENCODER_PICTURE_STRUCTURE_FRAME; indicate picture type
+#define AMF_VIDEO_ENCODER_MARK_CURRENT_WITH_LTR_INDEX           L"MarkCurrentWithLTRIndex"  // //amf_int64; default = N/A; Mark current frame with LTR index
+#define AMF_VIDEO_ENCODER_FORCE_LTR_REFERENCE_BITFIELD          L"ForceLTRReferenceBitfield"// amf_int64; default = 0; force LTR bit-field 
+
+// properties set by encoder on output buffer interface
+#define AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE                      L"OutputDataType"           // amf_int64(AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_ENUM); default = N/A
+#define AMF_VIDEO_ENCODER_OUTPUT_MARKED_LTR_INDEX               L"MarkedLTRIndex"           //amf_int64; default = -1; Marked LTR index
+#define AMF_VIDEO_ENCODER_OUTPUT_REFERENCED_LTR_INDEX_BITFIELD  L"ReferencedLTRIndexBitfield" // amf_int64; default = 0; referenced LTR bit-field 
+
+
+#define AMF_VIDEO_ENCODER_HDCP_COUNTER                          L"HDCPCounter"              //  const void*
+
+// Properties for multi-instance cloud gaming
+#define AMF_VIDEO_ENCODER_MAX_INSTANCES                         L"EncoderMaxInstances"      //  amf_uint32; default = 1; max number of encoder instances
+#define AMF_VIDEO_ENCODER_MULTI_INSTANCE_MODE                   L"MultiInstanceMode"        //  bool; default = false;
+#define AMF_VIDEO_ENCODER_CURRENT_QUEUE                         L"MultiInstanceCurrentQueue"//  amf_uin32; default = 0; 
+
+// VCE Encoder capabilities - exposed in AMFCaps interface
+#define AMF_VIDEO_ENCODER_CAP_MAX_BITRATE                       L"MaxBitrate"               // amf_int64; Maximum bit rate in bits
+#define AMF_VIDEO_ENCODER_CAP_NUM_OF_STREAMS                    L"NumOfStreams"             // amf_int64; maximum number of encode streams supported 
+#define AMF_VIDEO_ENCODER_CAP_MAX_PROFILE                       L"MaxProfile"               // AMF_VIDEO_ENCODER_PROFILE_ENUM
+#define AMF_VIDEO_ENCODER_CAP_MAX_LEVEL                         L"MaxLevel"                 // amf_int64 maximum profile level
+#define AMF_VIDEO_ENCODER_CAP_BFRAMES                           L"BFrames"                  // bool  is B-Frames supported
+#define AMF_VIDEO_ENCODER_CAP_MIN_REFERENCE_FRAMES              L"MinReferenceFrames"       // amf_int64 minimum number of reference frames
+#define AMF_VIDEO_ENCODER_CAP_MAX_REFERENCE_FRAMES              L"MaxReferenceFrames"       // amf_int64 maximum number of reference frames
+#define AMF_VIDEO_ENCODER_CAP_MAX_TEMPORAL_LAYERS               L"MaxTemporalLayers"        // amf_int64 maximum number of temporal layers
+#define AMF_VIDEO_ENCODER_CAP_FIXED_SLICE_MODE                  L"FixedSliceMode"           // bool  is fixed slice mode supported
+#define AMF_VIDEO_ENCODER_CAP_NUM_OF_HW_INSTANCES               L"NumOfHwInstances"         // amf_int64 number of HW encoder instances
+
+//-----------------------------------------------------------------------------
+// VideoEncoderHEVC.h
+//-----------------------------------------------------------------------------
+#define AMFVideoEncoder_HEVC L"AMFVideoEncoderHW_HEVC"
+
+enum AMF_VIDEO_ENCODER_HEVC_USAGE_ENUM
+{
+    AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING = 0,
+    AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY,
+    AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY,
+    AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM
+};
+
+enum AMF_VIDEO_ENCODER_HEVC_PROFILE_ENUM
+{
+    AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN = 1
+};
+
+enum AMF_VIDEO_ENCODER_HEVC_TIER_ENUM
+{
+    AMF_VIDEO_ENCODER_HEVC_TIER_MAIN = 0,
+    AMF_VIDEO_ENCODER_HEVC_TIER_HIGH = 1
+};
+
+enum AMF_VIDEO_ENCODER_LEVEL_ENUM
+{
+    AMF_LEVEL_1 = 30,
+    AMF_LEVEL_2 = 60,
+    AMF_LEVEL_2_1 = 63,
+    AMF_LEVEL_3 = 90,
+    AMF_LEVEL_3_1 = 93,
+    AMF_LEVEL_4 = 120,
+    AMF_LEVEL_4_1 = 123,
+    AMF_LEVEL_5 = 150,
+    AMF_LEVEL_5_1 = 153,
+    AMF_LEVEL_5_2 = 156,
+    AMF_LEVEL_6 = 180,
+    AMF_LEVEL_6_1 = 183,
+    AMF_LEVEL_6_2 = 186
+};
+
+enum AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_ENUM
+{
+    AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN = -1,
+    AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP = 0,
+    AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
+    AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR,
+    AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR
+};
+
+enum AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_ENUM
+{
+    AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_NONE = 0,
+    AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_SKIP,
+    AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_IDR,
+    AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_I,
+    AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_P
+};
+
+enum AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_ENUM
+{
+    AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR,
+    AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_I,
+    AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_P
+};
+
+enum AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_ENUM
+{
+    AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY = 0,
+    AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED = 5,
+    AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED = 10
+};
+
+enum AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE = 0,
+    AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED,
+    AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED
+};
+
+
+
+// Static properties - can be set before Init()
+#define AMF_VIDEO_ENCODER_HEVC_FRAMESIZE                            L"HevcFrameSize"                // AMFSize; default = 0,0; Frame size
+
+#define AMF_VIDEO_ENCODER_HEVC_USAGE                                L"HevcUsage"                    // amf_int64(AMF_VIDEO_ENCODER_HEVC_USAGE_ENUM); default = N/A; Encoder usage type. fully configures parameter set. 
+#define AMF_VIDEO_ENCODER_HEVC_PROFILE                              L"HevcProfile"                  // amf_int64(AMF_VIDEO_ENCODER_HEVC_PROFILE_ENUM) ; default = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN;
+#define AMF_VIDEO_ENCODER_HEVC_TIER                                 L"HevcTier"                     // amf_int64(AMF_VIDEO_ENCODER_HEVC_TIER_ENUM) ; default = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN;
+#define AMF_VIDEO_ENCODER_HEVC_PROFILE_LEVEL                        L"HevcProfileLevel"             // amf_int64 (AMF_VIDEO_ENCODER_LEVEL_ENUM, default depends on HW capabilities); 
+#define AMF_VIDEO_ENCODER_HEVC_MAX_LTR_FRAMES                       L"HevcMaxOfLTRFrames"           // amf_int64; default = 0; Max number of LTR frames
+#define AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES                     L"HevcMaxNumRefFrames"          // amf_int64; default = 1; Maximum number of reference frames
+#define AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET                       L"HevcQualityPreset"            // amf_int64(AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_ENUM); default = depends on USAGE; Quality Preset 
+#define AMF_VIDEO_ENCODER_HEVC_EXTRADATA                            L"HevcExtraData"                // AMFInterface* - > AMFBuffer*; SPS/PPS buffer - read-only
+#define AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO                         L"HevcAspectRatio"              // AMFRatio; default = 1, 1
+
+// Picture control properties
+#define AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR                     L"HevcGOPSPerIDR"               // amf_int64; default = 60; The frequency to insert IDR as start of a GOP. 0 means no IDR will be inserted.
+#define AMF_VIDEO_ENCODER_HEVC_GOP_SIZE                             L"HevcGOPSize"                  // amf_int64; default = 60; GOP Size, in frames
+#define AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE           L"HevcDeBlockingFilter"         // bool; default = depends on USAGE; De-blocking Filter
+#define AMF_VIDEO_ENCODER_HEVC_SLICES_PER_FRAME                     L"HevcSlicesPerFrame"           // amf_int64; default = 1; Number of slices Per Frame 
+#define AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE                L"HevcHeaderInsertionMode"      // amf_int64(AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_ENUM); default = NONE
+
+// Rate control properties
+#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD                  L"HevcRateControlMethod"        // amf_int64(AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_MODE_ENUM); default = depends on USAGE; Rate Control Method 
+#define AMF_VIDEO_ENCODER_HEVC_FRAMERATE                            L"HevcFrameRate"                // AMFRate; default = depends on usage; Frame Rate 
+#define AMF_VIDEO_ENCODER_HEVC_VBV_BUFFER_SIZE                      L"HevcVBVBufferSize"            // amf_int64; default = depends on USAGE; VBV Buffer Size in bits
+#define AMF_VIDEO_ENCODER_HEVC_INITIAL_VBV_BUFFER_FULLNESS          L"HevcInitialVBVBufferFullness" // amf_int64; default =  64; Initial VBV Buffer Fullness 0=0% 64=100%
+#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_PREANALYSIS_ENABLE      L"HevcRateControlPreAnalysisEnable"  // bool; default =  depends on USAGE; enable Pre-analysis assisted rate control 
+#define AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ                          L"HevcEnableVBAQ"               // // bool; default = depends on USAGE; Enable auto VBAQ
+
+// Motion estimation
+#define AMF_VIDEO_ENCODER_HEVC_MOTION_HALF_PIXEL                    L"HevcHalfPixel"                // bool; default= true; Half Pixel 
+#define AMF_VIDEO_ENCODER_HEVC_MOTION_QUARTERPIXEL                  L"HevcQuarterPixel"             // bool; default= true; Quarter Pixel
+
+// Dynamic properties - can be set at any time
+
+// Rate control properties
+#define AMF_VIDEO_ENCODER_HEVC_ENFORCE_HRD                          L"HevcEnforceHRD"               // bool; default = depends on USAGE; Enforce HRD
+#define AMF_VIDEO_ENCODER_HEVC_FILLER_DATA_ENABLE                   L"HevcFillerDataEnable"         // bool; default = depends on USAGE; Enforce HRD
+#define AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE                       L"HevcTargetBitrate"            // amf_int64; default = depends on USAGE; Target bit rate in bits
+#define AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE                         L"HevcPeakBitrate"              // amf_int64; default = depends on USAGE; Peak bit rate in bits
+
+#define AMF_VIDEO_ENCODER_HEVC_MAX_AU_SIZE                          L"HevcMaxAUSize"                // amf_int64; default = 60; Max AU Size in bits
+
+#define AMF_VIDEO_ENCODER_HEVC_MIN_QP_I                             L"HevcMinQP_I"                  // amf_int64; default = depends on USAGE; Min QP; range = 
+#define AMF_VIDEO_ENCODER_HEVC_MAX_QP_I                             L"HevcMaxQP_I"                  // amf_int64; default = depends on USAGE; Max QP; range = 
+#define AMF_VIDEO_ENCODER_HEVC_MIN_QP_P                             L"HevcMinQP_P"                  // amf_int64; default = depends on USAGE; Min QP; range = 
+#define AMF_VIDEO_ENCODER_HEVC_MAX_QP_P                             L"HevcMaxQP_P"                  // amf_int64; default = depends on USAGE; Max QP; range = 
+
+#define AMF_VIDEO_ENCODER_HEVC_QP_I                                 L"HevcQP_I"                     // amf_int64; default = 26; P-frame QP; range = 0-51
+#define AMF_VIDEO_ENCODER_HEVC_QP_P                                 L"HevcQP_P"                     // amf_int64; default = 26; P-frame QP; range = 0-51
+
+#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE       L"HevcRateControlSkipFrameEnable" // bool; default =  depends on USAGE; Rate Control Based Frame Skip 
+
+
+
+// Per-submittion properties - can be set on input surface interface
+#define AMF_VIDEO_ENCODER_HEVC_END_OF_SEQUENCE                      L"HevcEndOfSequence"            // bool; default = false; generate end of sequence
+#define AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE                   L"HevcForcePictureType"         // amf_int64(AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_ENUM); default = AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_NONE; generate particular picture type
+#define AMF_VIDEO_ENCODER_HEVC_INSERT_AUD                           L"HevcInsertAUD"                // bool; default = false; insert AUD
+#define AMF_VIDEO_ENCODER_HEVC_INSERT_HEADER                        L"HevcInsertHeader"             // bool; default = false; insert header(SPS, PPS, VPS)
+
+#define AMF_VIDEO_ENCODER_HEVC_MARK_CURRENT_WITH_LTR_INDEX          L"HevcMarkCurrentWithLTRIndex"  // amf_int64; default = N/A; Mark current frame with LTR index
+#define AMF_VIDEO_ENCODER_HEVC_FORCE_LTR_REFERENCE_BITFIELD         L"HevcForceLTRReferenceBitfield"// amf_int64; default = 0; force LTR bit-field 
+
+// Properties set by encoder on output buffer interface
+#define AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE                     L"HevcOutputDataType"           // amf_int64(AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_ENUM); default = N/A
+#define AMF_VIDEO_ENCODER_HEVC_OUTPUT_MARKED_LTR_INDEX              L"HevcMarkedLTRIndex"           // amf_int64; default = -1; Marked LTR index
+#define AMF_VIDEO_ENCODER_HEVC_OUTPUT_REFERENCED_LTR_INDEX_BITFIELD L"HevcReferencedLTRIndexBitfield"// amf_int64; default = 0; referenced LTR bit-field 
+
+// HEVC Encoder capabilities - exposed in AMFCaps interface
+#define AMF_VIDEO_ENCODER_HEVC_CAP_MAX_BITRATE                      L"HevcMaxBitrate"               // amf_int64; Maximum bit rate in bits
+#define AMF_VIDEO_ENCODER_HEVC_CAP_NUM_OF_STREAMS                   L"HevcNumOfStreams"             // amf_int64; maximum number of encode streams supported 
+#define AMF_VIDEO_ENCODER_HEVC_CAP_MAX_PROFILE                      L"HevcMaxProfile"               // amf_int64(AMF_VIDEO_ENCODER_HEVC_PROFILE_ENUM)
+#define AMF_VIDEO_ENCODER_HEVC_CAP_MAX_TIER                         L"HevcMaxTier"                  // amf_int64(AMF_VIDEO_ENCODER_HEVC_TIER_ENUM) maximum profile tier 
+#define AMF_VIDEO_ENCODER_HEVC_CAP_MAX_LEVEL                        L"HevcMaxLevel"                 // amf_int64 maximum profile level
+#define AMF_VIDEO_ENCODER_HEVC_CAP_MIN_REFERENCE_FRAMES             L"HevcMinReferenceFrames"       // amf_int64 minimum number of reference frames
+#define AMF_VIDEO_ENCODER_HEVC_CAP_MAX_REFERENCE_FRAMES             L"HevcMaxReferenceFrames"       // amf_int64 maximum number of reference frames
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#endif // __AMF_SDK_Enc_h__
diff --git a/configure b/configure
index 3788f26..afdcb1b 100755
--- a/configure
+++ b/configure
@@ -303,6 +303,7 @@  External library support:
   --disable-zlib           disable zlib [autodetect]
 
   The following libraries provide various hardware acceleration features:
+  --disable-amf            disable AMF video encoding code [autodetect]
   --disable-audiotoolbox   disable Apple AudioToolbox code [autodetect]
   --disable-cuda           disable dynamically linked Nvidia CUDA code [autodetect]
   --enable-cuda-sdk        enable CUDA features that require the CUDA SDK [no]
@@ -1639,6 +1640,7 @@  EXTERNAL_LIBRARY_LIST="
 "
 
 HWACCEL_AUTODETECT_LIBRARY_LIST="
+    amf
     audiotoolbox
     crystalhd
     cuda
@@ -2781,12 +2783,15 @@  scale_npp_filter_deps="cuda libnpp"
 scale_cuda_filter_deps="cuda_sdk"
 thumbnail_cuda_filter_deps="cuda_sdk"
 
+amf_deps_any="libdl LoadLibrary"
+
 nvenc_deps="cuda"
 nvenc_deps_any="libdl LoadLibrary"
 nvenc_encoder_deps="nvenc"
 
 h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m"
 h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m"
+h264_amf_encoder_deps="amf"
 h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
 h264_cuvid_decoder_deps="cuvid"
 h264_cuvid_decoder_select="h264_mp4toannexb_bsf"
@@ -2803,6 +2808,7 @@  h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264"
 h264_vaapi_encoder_select="cbs_h264 vaapi_encode"
 h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m"
 h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m"
+hevc_amf_encoder_deps="amf"
 hevc_cuvid_decoder_deps="cuvid"
 hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf"
 hevc_mediacodec_decoder_deps="mediacodec"
@@ -6164,11 +6170,14 @@  if enabled x86; then
         mingw32*|mingw64*|win32|win64|linux|cygwin*)
             ;;
         *)
-            disable cuda cuvid nvdec nvenc
+            disable cuda cuvid nvdec nvenc amf
             ;;
     esac
+    if test $target_os = "linux"; then
+        disable amf
+    fi
 else
-    disable cuda cuvid nvdec nvenc
+    disable cuda cuvid nvdec nvenc amf
 fi
 
 enabled nvenc &&
@@ -6179,6 +6188,13 @@  void f(void) { struct { const GUID guid; } s[] = { { NV_ENC_PRESET_HQ_GUID } };
 int main(void) { return 0; }
 EOF
 
+enabled amf &&
+    check_cc -I$source_path <<EOF || disable amf
+#include "compat/amd/amfsdkenc.h"
+AMFFactory *factory;
+int main(void) { return 0; }
+EOF
+
 # Funny iconv installations are not unusual, so check it after all flags have been set
 if enabled libc_iconv; then
     check_func_headers iconv.h iconv
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 2476aec..9bbb60e 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -55,6 +55,7 @@  OBJS = ac3_parser.o                                                     \
 OBJS-$(CONFIG_AANDCTTABLES)            += aandcttab.o
 OBJS-$(CONFIG_AC3DSP)                  += ac3dsp.o ac3.o ac3tab.o
 OBJS-$(CONFIG_ADTS_HEADER)             += adts_header.o mpeg4audio.o
+OBJS-$(CONFIG_AMF)                     += amfenc.o
 OBJS-$(CONFIG_AUDIO_FRAME_QUEUE)       += audio_frame_queue.o
 OBJS-$(CONFIG_AUDIODSP)                += audiodsp.o
 OBJS-$(CONFIG_BLOCKDSP)                += blockdsp.o
@@ -332,6 +333,7 @@  OBJS-$(CONFIG_H263_ENCODER)            += mpeg4videoenc.o mpeg4video.o  \
                                           h263.o ituh263enc.o flvenc.o h263data.o
 OBJS-$(CONFIG_H263_V4L2M2M_DECODER)    += v4l2_m2m_dec.o
 OBJS-$(CONFIG_H263_V4L2M2M_ENCODER)    += v4l2_m2m_enc.o
+OBJS-$(CONFIG_H264_AMF_ENCODER)        += amfenc_h264.o
 OBJS-$(CONFIG_H264_DECODER)            += h264dec.o h264_cabac.o h264_cavlc.o \
                                           h264_direct.o h264_loopfilter.o  \
                                           h264_mb.o h264_picture.o \
@@ -353,6 +355,7 @@  OBJS-$(CONFIG_H264_V4L2M2M_DECODER)    += v4l2_m2m_dec.o
 OBJS-$(CONFIG_H264_V4L2M2M_ENCODER)    += v4l2_m2m_enc.o
 OBJS-$(CONFIG_HAP_DECODER)             += hapdec.o hap.o
 OBJS-$(CONFIG_HAP_ENCODER)             += hapenc.o hap.o
+OBJS-$(CONFIG_HEVC_AMF_ENCODER)        += amfenc_hevc.o
 OBJS-$(CONFIG_HEVC_DECODER)            += hevcdec.o hevc_mvs.o \
                                           hevc_cabac.o hevc_refs.o hevcpred.o    \
                                           hevcdsp.o hevc_filter.o hevc_data.o
@@ -1059,6 +1062,7 @@  SKIPHEADERS                            += %_tablegen.h                  \
                                           aacenc_quantization_misc.h    \
                                           $(ARCH)/vp56_arith.h          \
 
+SKIPHEADERS-$(CONFIG_AMF)              += amfenc.h
 SKIPHEADERS-$(CONFIG_D3D11VA)          += d3d11va.h dxva2_internal.h
 SKIPHEADERS-$(CONFIG_DXVA2)            += dxva2.h dxva2_internal.h
 SKIPHEADERS-$(CONFIG_JNI)              += ffjni.h
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 0781862..20c19ec 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -653,6 +653,7 @@  static void register_all(void)
      * above is available */
     REGISTER_ENCODER(H263_V4L2M2M,      h263_v4l2m2m);
     REGISTER_ENCDEC (LIBOPENH264,       libopenh264);
+    REGISTER_ENCODER(H264_AMF,          h264_amf);
     REGISTER_DECODER(H264_CUVID,        h264_cuvid);
     REGISTER_ENCODER(H264_NVENC,        h264_nvenc);
     REGISTER_ENCODER(H264_OMX,          h264_omx);
@@ -665,6 +666,7 @@  static void register_all(void)
     REGISTER_ENCODER(NVENC_H264,        nvenc_h264);
     REGISTER_ENCODER(NVENC_HEVC,        nvenc_hevc);
 #endif
+    REGISTER_ENCODER(HEVC_AMF,          hevc_amf);
     REGISTER_DECODER(HEVC_CUVID,        hevc_cuvid);
     REGISTER_DECODER(HEVC_MEDIACODEC,   hevc_mediacodec);
     REGISTER_ENCODER(HEVC_NVENC,        hevc_nvenc);
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
new file mode 100644
index 0000000..267c386
--- /dev/null
+++ b/libavcodec/amfenc.c
@@ -0,0 +1,602 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/hwcontext.h"
+#if CONFIG_D3D11VA
+#include "libavutil/hwcontext_d3d11va.h"
+#endif
+#include "libavutil/mem.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/time.h"
+
+#include "amfenc.h"
+#include "internal.h"
+
+#if CONFIG_D3D11VA
+#include <d3d11.h>
+#endif
+
+#ifdef _WIN32
+#include "compat/w32dlfcn.h"
+#else
+#include <dlfcn.h>
+#endif
+
+#define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf"
+
+#define PTS_PROP L"PtsProp"
+
+const enum AVPixelFormat ff_amf_pix_fmts[] = {
+    AV_PIX_FMT_NV12,
+    AV_PIX_FMT_YUV420P,
+    AV_PIX_FMT_D3D11,
+    AV_PIX_FMT_NONE
+};
+
+typedef struct FormatMap {
+    enum AVPixelFormat       av_format;
+    enum AMF_SURFACE_FORMAT  amf_format;
+} FormatMap;
+
+static const FormatMap format_map[] =
+{
+    { AV_PIX_FMT_NONE,       AMF_SURFACE_UNKNOWN },
+    { AV_PIX_FMT_NV12,       AMF_SURFACE_NV12 },
+    { AV_PIX_FMT_BGR0,       AMF_SURFACE_BGRA },
+    { AV_PIX_FMT_RGB0,       AMF_SURFACE_RGBA },
+    { AV_PIX_FMT_GRAY8,      AMF_SURFACE_GRAY8 },
+    { AV_PIX_FMT_YUV420P,    AMF_SURFACE_YUV420P },
+    { AV_PIX_FMT_YUYV422,    AMF_SURFACE_YUY2 },
+    { AV_PIX_FMT_D3D11,      AMF_SURFACE_NV12 },
+};
+
+
+static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt)
+{
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
+    return desc->flags & AV_PIX_FMT_FLAG_HWACCEL;
+}
+
+
+static enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt)
+{
+    int i;
+    for (i = 0; i < amf_countof(format_map); i++) {
+        if (format_map[i].av_format == fmt) {
+            return format_map[i].amf_format;
+        }
+    }
+    return AMF_SURFACE_UNKNOWN;
+}
+
+static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis,
+    const wchar_t *scope, const wchar_t *message)
+{
+    AmfTraceWriter *tracer = (AmfTraceWriter*)pThis;
+    av_log(tracer->avctx, AV_LOG_DEBUG, "%ls: %ls", scope, message); // \n is provided from AMF
+}
+
+static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis)
+{
+}
+
+static AMFTraceWriterVtbl tracer_vtbl =
+{
+    .Write = AMFTraceWriter_Write,
+    .Flush = AMFTraceWriter_Flush,
+};
+
+static int amf_load_library(AVCodecContext *avctx)
+{
+    AmfContext             *ctx = avctx->priv_data;
+    AMFInit_Fn              init_fun = NULL;
+    AMFQueryVersion_Fn      version_fun = NULL;
+    AMF_RESULT              res = AMF_OK;
+
+    ctx->eof = 0;
+    ctx->delayed_drain = 0;
+    ctx->hw_frames_ctx = NULL;
+    ctx->hw_device_ctx = NULL;
+    ctx->delayed_surface = NULL;
+    ctx->delayed_frame = av_frame_alloc();
+    if (!ctx->delayed_frame) {
+        return AVERROR(ENOMEM);
+    }
+    // hardcoded to current HW queue size - will realloc in timestamp_queue_enqueue() if too small
+    ctx->timestamp_list = av_fifo_alloc((avctx->max_b_frames + 16) * sizeof(int64_t));
+    if (!ctx->timestamp_list) {
+        return AVERROR(ENOMEM);
+    }
+    ctx->dts_delay = 0;
+
+
+    ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL);
+    AMF_RETURN_IF_FALSE(ctx, ctx->library != NULL,
+        AVERROR_UNKNOWN, "DLL %s failed to open\n", AMF_DLL_NAMEA);
+
+    init_fun = (AMFInit_Fn)dlsym(ctx->library, AMF_INIT_FUNCTION_NAME);
+    AMF_RETURN_IF_FALSE(ctx, init_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_INIT_FUNCTION_NAME);
+
+    version_fun = (AMFQueryVersion_Fn)dlsym(ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME);
+    AMF_RETURN_IF_FALSE(ctx, version_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME);
+
+    res = version_fun(&ctx->version);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_QUERY_VERSION_FUNCTION_NAME, res);
+    res = init_fun(AMF_FULL_VERSION, &ctx->factory);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_INIT_FUNCTION_NAME, res);
+    res = ctx->factory->pVtbl->GetTrace(ctx->factory, &ctx->trace);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetTrace() failed with error %d\n", res);
+    res = ctx->factory->pVtbl->GetDebug(ctx->factory, &ctx->debug);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetDebug() failed with error %d\n", res);
+    return 0;
+}
+
+static int amf_init_context(AVCodecContext *avctx)
+{
+    AmfContext         *ctx = avctx->priv_data;
+    AMF_RESULT          res = AMF_OK;
+
+    // confugure AMF logger
+    // the return of these functions indicates old state and do not affect behaviour
+    ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, ctx->log_to_dbg != 0 );
+    if (ctx->log_to_dbg)
+        ctx->trace->pVtbl->SetWriterLevel(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TRACE);
+    ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_CONSOLE, 0);
+    ctx->trace->pVtbl->SetGlobalLevel(ctx->trace, AMF_TRACE_TRACE);
+
+    // connect AMF logger to av_log
+    ctx->tracer.vtbl = &tracer_vtbl;
+    ctx->tracer.avctx = avctx;
+    ctx->trace->pVtbl->RegisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID,(AMFTraceWriter*)&ctx->tracer, 1);
+    ctx->trace->pVtbl->SetWriterLevel(ctx->trace, FFMPEG_AMF_WRITER_ID, AMF_TRACE_TRACE);
+
+    res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res);
+    // try to reuse existing DX device
+#if CONFIG_D3D11VA
+    if (avctx->hw_frames_ctx) {
+        AVHWFramesContext *device_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
+        if (device_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA){
+            if (amf_av_to_amf_format(device_ctx->sw_format) != AMF_SURFACE_UNKNOWN) {
+                if (device_ctx->device_ctx->hwctx) {
+                    AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->device_ctx->hwctx;
+                    res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1);
+                    if (res == AMF_OK) {
+                        ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx);
+                        if (!ctx->hw_frames_ctx) {
+                            return AVERROR(ENOMEM);
+                        }
+                    }else {
+                        if(res == AMF_NOT_SUPPORTED)
+                            av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n");
+                        else
+                            av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has non-AMD device, switching to default\n");
+                    }
+                }
+            }else {
+                av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has format not uspported by AMF, switching to default\n");
+            }
+        }
+    } else if (avctx->hw_device_ctx) {
+        AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data);
+        if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
+            if (device_ctx->hwctx) {
+                AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->hwctx;
+                res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1);
+                if (res == AMF_OK) {
+                    ctx->hw_device_ctx = av_buffer_ref(avctx->hw_device_ctx);
+                    if (!ctx->hw_device_ctx) {
+                        return AVERROR(ENOMEM);
+                    }
+                } else {
+                    if (res == AMF_NOT_SUPPORTED)
+                        av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n");
+                    else
+                        av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has non-AMD device, switching to default\n");
+                }
+            }
+        }
+    }
+#endif
+    if (!ctx->hw_frames_ctx && !ctx->hw_device_ctx) {
+        res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1);
+        if (res != AMF_OK) {
+            res = ctx->context->pVtbl->InitDX9(ctx->context, NULL);
+            AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "InitDX9() failed with error %d\n", res);
+        }
+    }
+    return 0;
+}
+
+static int amf_init_encoder(AVCodecContext *avctx)
+{
+    AmfContext          *ctx = avctx->priv_data;
+    const wchar_t       *codec_id = NULL;
+    AMF_RESULT           res = AMF_OK;
+
+    switch (avctx->codec->id) {
+        case AV_CODEC_ID_H264:
+            codec_id = AMFVideoEncoderVCE_AVC;
+            break;
+        case AV_CODEC_ID_HEVC:
+            codec_id = AMFVideoEncoder_HEVC;
+            break;
+        default:
+            break;
+    }
+    AMF_RETURN_IF_FALSE(ctx, codec_id != NULL, AVERROR(EINVAL), "Codec %d is not supported\n", avctx->codec->id);
+
+    ctx->format = amf_av_to_amf_format(avctx->pix_fmt);
+    AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), "Format %d is not supported\n", avctx->pix_fmt);
+
+    res = ctx->factory->pVtbl->CreateComponent(ctx->factory, ctx->context, codec_id, &ctx->encoder);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res);
+
+    return 0;
+}
+
+int av_cold ff_amf_encode_close(AVCodecContext *avctx)
+{
+    AmfContext      *ctx = avctx->priv_data;
+    if (ctx->delayed_surface)
+    {
+        ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface);
+        ctx->delayed_surface = NULL;
+    }
+
+    if (ctx->encoder) {
+        ctx->encoder->pVtbl->Terminate(ctx->encoder);
+        ctx->encoder->pVtbl->Release(ctx->encoder);
+        ctx->encoder = NULL;
+    }
+
+    if (ctx->context) {
+        ctx->context->pVtbl->Terminate(ctx->context);
+        ctx->context->pVtbl->Release(ctx->context);
+        ctx->context = NULL;
+    }
+    av_buffer_unref(&ctx->hw_device_ctx);
+    av_buffer_unref(&ctx->hw_frames_ctx);
+
+    if (ctx->trace) {
+        ctx->trace->pVtbl->UnregisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID);
+    }
+    if (ctx->library) {
+        dlclose(ctx->library);
+        ctx->library = NULL;
+    }
+    ctx->trace = NULL;
+    ctx->debug = NULL;
+    ctx->factory = NULL;
+    ctx->version = 0;
+    ctx->delayed_drain = 0;
+    av_frame_free(&ctx->delayed_frame);
+    av_fifo_freep(&ctx->timestamp_list);
+
+    return 0;
+}
+
+static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame,
+    AMFSurface* surface)
+{
+    AVFrame        *sw_frame = NULL;
+    AMFPlane       *plane = NULL;
+    uint8_t        *dst_data[4];
+    int             dst_linesize[4];
+    int             ret = 0;
+    int             planes;
+    int             i;
+
+    if (frame->hw_frames_ctx && is_hwaccel_pix_fmt(frame->format)) {
+        if (!(sw_frame = av_frame_alloc())) {
+            av_log(avctx, AV_LOG_ERROR, "Can not alloc frame\n");
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Error transferring the data to system memory\n");
+            goto fail;
+        }
+        frame = sw_frame;
+    }
+    planes = (int)surface->pVtbl->GetPlanesCount(surface);
+    if (planes > amf_countof(dst_data)) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid number of planes %d in surface\n", planes);
+        ret = AVERROR(EINVAL);
+        goto fail;
+    }
+
+    for (i = 0; i < planes; i++) {
+        plane = surface->pVtbl->GetPlaneAt(surface, i);
+        dst_data[i] = plane->pVtbl->GetNative(plane);
+        dst_linesize[i] = plane->pVtbl->GetHPitch(plane);
+    }
+    av_image_copy(dst_data, dst_linesize,
+        (const uint8_t**)frame->data, frame->linesize, frame->format,
+        avctx->width, avctx->height);
+
+fail:
+    if (sw_frame){
+        av_frame_free(&sw_frame);
+    }
+    return ret;
+}
+
+static inline int timestamp_queue_enqueue(AVCodecContext *avctx, int64_t timestamp)
+{
+    AmfContext         *ctx = avctx->priv_data;
+    if (av_fifo_space(ctx->timestamp_list) < sizeof(timestamp)){
+        if (av_fifo_grow(ctx->timestamp_list, sizeof(timestamp)) < 0) {
+            return AVERROR(ENOMEM);
+        }
+    }
+    av_fifo_generic_write(ctx->timestamp_list, &timestamp, sizeof(timestamp), NULL);
+    return 0;
+}
+
+static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buffer)
+{
+    AmfContext             *ctx = avctx->priv_data;
+    int                     ret;
+    AMFVariantStruct        var = {0};
+    int64_t                 timestamp = AV_NOPTS_VALUE;
+    int64_t                 size = buffer->pVtbl->GetSize(buffer);
+
+    if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) {
+        return ret;
+    }
+    memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size);
+
+    switch (avctx->codec->id) {
+        case AV_CODEC_ID_H264:
+            buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &var);
+            if(var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR) {
+                pkt->flags = AV_PKT_FLAG_KEY;
+            }
+            break;
+        case AV_CODEC_ID_HEVC:
+            buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE, &var);
+            if (var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR) {
+                pkt->flags = AV_PKT_FLAG_KEY;
+            }
+            break;
+        default:
+            break;
+    }
+
+    buffer->pVtbl->GetProperty(buffer, PTS_PROP, &var);
+
+    pkt->pts = var.int64Value; // original pts
+
+
+    AMF_RETURN_IF_FALSE(ctx, av_fifo_size(ctx->timestamp_list) > 0, AVERROR_UNKNOWN, "timestamp_list is empty\n");
+
+    av_fifo_generic_read(ctx->timestamp_list, &timestamp, sizeof(timestamp), NULL);
+
+    // calc dts shift if max_b_frames > 0
+    if (avctx->max_b_frames > 0 && ctx->dts_delay == 0){
+        int64_t timestamp_last = AV_NOPTS_VALUE;
+        AMF_RETURN_IF_FALSE(ctx, av_fifo_size(ctx->timestamp_list) > 0, AVERROR_UNKNOWN,
+            "timestamp_list is empty while max_b_frames = %d\n", avctx->max_b_frames);
+        av_fifo_generic_peek_at(
+            ctx->timestamp_list,
+            &timestamp_last,
+            (av_fifo_size(ctx->timestamp_list) / sizeof(timestamp) - 1) * sizeof(timestamp_last),
+            sizeof(timestamp_last),
+            NULL);
+        if (timestamp < 0 || timestamp_last < AV_NOPTS_VALUE) {
+            return AVERROR(ERANGE);
+        }
+        ctx->dts_delay = timestamp_last - timestamp;
+    }
+    pkt->dts = timestamp - ctx->dts_delay;
+    return 0;
+}
+
+// amfenc API implmentation
+int ff_amf_encode_init(AVCodecContext *avctx)
+{
+    AmfContext     *ctx = avctx->priv_data;
+    int             ret;
+
+    ctx->factory = NULL;
+    ctx->debug = NULL;
+    ctx->trace = NULL;
+    ctx->context = NULL;
+    ctx->encoder = NULL;
+    ctx->library = NULL;
+    ctx->version = 0;
+    ctx->eof = 0;
+    ctx->format = 0;
+    ctx->tracer.vtbl = NULL;
+    ctx->tracer.avctx = NULL;
+
+    if ((ret = amf_load_library(avctx)) == 0) {
+        if ((ret = amf_init_context(avctx)) == 0) {
+            if ((ret = amf_init_encoder(avctx)) == 0) {
+                return 0;
+            }
+        }
+    }
+    ff_amf_encode_close(avctx);
+    return ret;
+}
+
+
+int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame)
+{
+    AMF_RESULT      res = AMF_OK;
+    AmfContext     *ctx = avctx->priv_data;
+    AMFSurface     *surface = NULL;
+    int             ret;
+
+    if (!ctx->encoder)
+        return AVERROR(EINVAL);
+
+    if (!frame) { // submit drain
+        if (!ctx->eof) { // submit drain one time only
+            if (ctx->delayed_surface != NULL) {
+                ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet
+            } else if(!ctx->delayed_drain){
+                res = ctx->encoder->pVtbl->Drain(ctx->encoder);
+                if (res == AMF_INPUT_FULL) {
+                    ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet
+                }else {
+                    if (res == AMF_OK) {
+                        ctx->eof = 1; // drain started
+                    }
+                    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed with error %d\n", res);
+                }
+            }
+        }else{
+            return AVERROR_EOF;
+        }
+    } else { // submit frame
+        if (ctx->delayed_surface != NULL) {
+            return AVERROR(EAGAIN); // should not happen when called from ffmpeg, other clients may resubmit
+        }
+        // prepare surface from frame
+        if (frame->hw_frames_ctx && ( // HW frame detected
+            // check if the same hw_frames_ctx as used in initialization
+            (ctx->hw_frames_ctx && frame->hw_frames_ctx->data == ctx->hw_frames_ctx->data) ||
+            // check if the same hw_device_ctx as used in initialization
+            (ctx->hw_device_ctx && ((AVHWFramesContext*)frame->hw_frames_ctx->data)->device_ctx ==
+            (AVHWDeviceContext*)ctx->hw_device_ctx->data)
+        )) {
+#if CONFIG_D3D11VA
+            GUID             AMFTextureArrayIndexGUID = AMFTextureArrayIndexGUIDDef;
+            ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture
+            int index = (int)(size_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use
+            texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index);
+
+            res = ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface
+            AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed  with error %d\n", res);
+
+            // input HW surfaces can be vertically aligned by 16; tell AMF the real size
+            surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height);
+#endif
+        } else {
+            res = ctx->context->pVtbl->AllocSurface(ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface);
+            AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed  with error %d\n", res);
+            amf_copy_surface(avctx, frame, surface);
+        }
+        surface->pVtbl->SetPts(surface, frame->pts);
+        AMF_ASSIGN_PROPERTY_INT64(res, surface, PTS_PROP, frame->pts);
+
+        switch (avctx->codec->id) {
+        case AV_CODEC_ID_H264:
+            AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!ctx->aud);
+            break;
+        case AV_CODEC_ID_HEVC:
+            AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud);
+            break;
+        default:
+            break;
+        }
+
+
+        // submit surface
+        res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)surface);
+        if (res == AMF_INPUT_FULL) { // handle full queue
+            //store surface for later submission
+            ctx->delayed_surface = surface;
+            if (surface->pVtbl->GetMemoryType(surface) == AMF_MEMORY_DX11) {
+                av_frame_ref(ctx->delayed_frame, frame);
+            }
+        } else {
+            surface->pVtbl->Release(surface);
+            AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res);
+
+            if ((ret = timestamp_queue_enqueue(avctx, frame->pts)) < 0) {
+                return ret;
+            }
+
+        }
+    }
+    return 0;
+}
+int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
+{
+    int             ret;
+    AMF_RESULT      res;
+    AMF_RESULT      res_query;
+    AmfContext     *ctx = avctx->priv_data;
+    AMFData        *data = NULL;
+    int             block_and_wait;
+
+    if (!ctx->encoder)
+        return AVERROR(EINVAL);
+
+    do {
+        block_and_wait = 0;
+        // poll data
+        res_query = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data);
+        if (data) {
+            // copy data to packet
+            AMFBuffer* buffer;
+            AMFGuid guid = IID_AMFBuffer();
+            data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // query for buffer interface
+            ret = amf_copy_buffer(avctx, avpkt, buffer);
+
+            buffer->pVtbl->Release(buffer);
+            data->pVtbl->Release(data);
+
+            AMF_RETURN_IF_FALSE(ctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret);
+
+            if (ctx->delayed_surface != NULL) { // try to resubmit frame
+                res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)ctx->delayed_surface);
+                if (res != AMF_INPUT_FULL) {
+                    int64_t pts = ctx->delayed_surface->pVtbl->GetPts(ctx->delayed_surface);
+                    ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface);
+                    ctx->delayed_surface = NULL;
+                    av_frame_unref(ctx->delayed_frame);
+                    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res);
+
+                    if ((ret = timestamp_queue_enqueue(avctx, pts)) < 0) {
+                        return ret;
+                    }
+                }else {
+                    av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed frame submission got AMF_INPUT_FULL- should not happen\n");
+                }
+            }else if (ctx->delayed_drain) { // try to resubmit drain
+                res = ctx->encoder->pVtbl->Drain(ctx->encoder);
+                if (res != AMF_INPUT_FULL) {
+                    ctx->delayed_drain = 0;
+                    ctx->eof = 1; // drain started
+                    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated Drain() failed with error %d\n", res);
+                }else {
+                    av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n");
+                }
+            }
+        }else if (ctx->delayed_surface != NULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF)) {
+            block_and_wait = 1;
+            av_usleep(1000); // wait and poll again
+        }
+    } while (block_and_wait);
+
+    if (res_query == AMF_EOF) {
+        ret = AVERROR_EOF;
+    }else if (data == NULL) {
+        ret = AVERROR(EAGAIN);
+    }else {
+        ret = 0;
+    }
+    return ret;
+}
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
new file mode 100644
index 0000000..fb19ed4
--- /dev/null
+++ b/libavcodec/amfenc.h
@@ -0,0 +1,143 @@ 
+/*
+* This file is part of FFmpeg.
+*
+* FFmpeg is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* FFmpeg is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with FFmpeg; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef AVCODEC_AMFENC_H
+#define AVCODEC_AMFENC_H
+
+#include "config.h"
+#include "avcodec.h"
+#include "compat/amd/amfsdkenc.h"
+#include "libavutil/fifo.h"
+
+
+/**
+* AMF trace writer callback class
+* Used to capture all AMF logging
+*/
+
+typedef struct AmfTraceWriter {
+    AMFTraceWriterVtbl* vtbl;
+    AVCodecContext      *avctx;
+} AmfTraceWriter;
+
+/**
+* AMF encoder context
+*/
+
+typedef struct AmfContext {
+    AVClass            *avclass;
+    // access to AMF runtime
+    amf_handle          library; ///< handle to DLL library
+    AMFFactory         *factory; ///< pointer to AMF factory
+    AMFDebug*           debug;   ///< pointer to AMF debug interface
+    AMFTrace*           trace;   ///< pointer to AMF trace interface
+
+    amf_uint64          version; ///< version of AMF runtime
+    AmfTraceWriter      tracer;  ///< AMF writer registered with AMF
+    AMFContext         *context; ///< AMF context
+    //encoder
+    AMFComponent*       encoder; ///< AMF encoder object
+    amf_bool            eof;     ///< flag indicating EOF happened
+    AMF_SURFACE_FORMAT  format;  ///< AMF surface format
+
+    AVBufferRef        *hw_device_ctx; ///< pointer to HW accelerator (decoder)
+    AVBufferRef        *hw_frames_ctx; ///< pointer to HW accelerator (frame allocator)
+
+    // helpers to handle async calls
+    int                 delayed_drain;
+    AMFSurface         *delayed_surface;
+    AVFrame            *delayed_frame;
+
+    // shift dts back by max_b_frames in timing
+    AVFifoBuffer       *timestamp_list;
+    int64_t             dts_delay;
+
+    // common encoder option options
+
+    int                 log_to_dbg;
+
+    // Static options, have to be set before Init() call
+    int                 usage;
+    int                 profile;
+    int                 level;
+    int                 preanalysis;
+    int                 quality;
+    int                 b_frame_delta_qp;
+    int                 ref_b_frame_delta_qp;
+
+    // Dynamic options, can be set after Init() call
+
+    int                 rate_control_mode;
+    int                 enforce_hrd;
+    int                 filler_data;
+    int                 enable_vbaq;
+    int                 skip_frame;
+    int                 qp_i;
+    int                 qp_p;
+    int                 qp_b;
+    int                 max_au_size;
+    int                 header_spacing;
+    int                 b_frame_ref;
+    int                 intra_refresh_mb;
+    int                 coding_mode;
+    int                 me_half_pel;
+    int                 me_quarter_pel;
+    int                 aud;
+
+    // HEVC - specific options
+
+    int                 gops_per_idr;
+    int                 header_insertion_mode;
+    int                 min_qp_i;
+    int                 max_qp_i;
+    int                 min_qp_p;
+    int                 max_qp_p;
+    int                 tier;
+} AmfContext;
+
+/**
+* Common encoder initization function
+*/
+int ff_amf_encode_init(AVCodecContext *avctx);
+/**
+* Common encoder termination function
+*/
+int ff_amf_encode_close(AVCodecContext *avctx);
+
+/**
+* Ecoding one frame - common function for all AMF encoders
+*/
+
+int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame);
+int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
+
+/**
+* Supported formats
+*/
+extern const enum AVPixelFormat ff_amf_pix_fmts[];
+
+/**
+* Error handling helper
+*/
+#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value, /*message,*/ ...) \
+    if (!(exp)) { \
+        av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \
+        return ret_value; \
+    }
+
+#endif //AVCODEC_AMFENC_H
diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c
new file mode 100644
index 0000000..ae13bba
--- /dev/null
+++ b/libavcodec/amfenc_h264.c
@@ -0,0 +1,397 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "amfenc.h"
+#include "internal.h"
+
+#define OFFSET(x) offsetof(AmfContext, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+
+static const AVOption options[] = {
+    // Static
+    /// Usage
+    { "usage",          "Encoder Usage",        OFFSET(usage),  AV_OPT_TYPE_INT,   { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING      }, AMF_VIDEO_ENCODER_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_USAGE_WEBCAM, VE, "usage" },
+    { "transcoding",    "Generic Transcoding",  0,              AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING      }, 0, 0, VE, "usage" },
+    { "ultralowlatency","",                     0,              AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" },
+    { "lowlatency",     "",                     0,              AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY       }, 0, 0, VE, "usage" },
+    { "webcam",         "Webcam",               0,              AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_WEBCAM            }, 0, 0, VE, "usage" },
+
+    /// Profile,
+    { "profile",        "Profile",              OFFSET(profile),AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN       }, AMF_VIDEO_ENCODER_PROFILE_BASELINE, AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH, VE, "profile" },
+    { "main",           "",                     0,              AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN     }, 0, 0, VE, "profile" },
+    { "high",           "",                     0,              AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_HIGH     }, 0, 0, VE, "profile" },
+    { "constrained_baseline",           "",     0,              AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_BASELINE }, 0, 0, VE, "profile" },
+    { "constrained_high",           "",         0,              AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH }, 0, 0, VE, "profile" },
+
+    /// Profile Level
+    { "level",          "Profile Level",        OFFSET(level),  AV_OPT_TYPE_INT,   { .i64 = 0  }, 0, 62, VE, "level" },
+    { "auto",           "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 0  }, 0, 0,  VE, "level" },
+    { "1.0",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 10 }, 0, 0,  VE, "level" },
+    { "1.1",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 11 }, 0, 0,  VE, "level" },
+    { "1.2",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 12 }, 0, 0,  VE, "level" },
+    { "1.3",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 13 }, 0, 0,  VE, "level" },
+    { "2.0",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 20 }, 0, 0,  VE, "level" },
+    { "2.1",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 21 }, 0, 0,  VE, "level" },
+    { "2.2",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 22 }, 0, 0,  VE, "level" },
+    { "3.0",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 30 }, 0, 0,  VE, "level" },
+    { "3.1",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 31 }, 0, 0,  VE, "level" },
+    { "3.2",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 32 }, 0, 0,  VE, "level" },
+    { "4.0",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 40 }, 0, 0,  VE, "level" },
+    { "4.1",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 41 }, 0, 0,  VE, "level" },
+    { "4.2",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 42 }, 0, 0,  VE, "level" },
+    { "5.0",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 50 }, 0, 0,  VE, "level" },
+    { "5.1",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 51 }, 0, 0,  VE, "level" },
+    { "5.2",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 52 }, 0, 0,  VE, "level" },
+    { "6.0",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 60 }, 0, 0,  VE, "level" },
+    { "6.1",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 61 }, 0, 0,  VE, "level" },
+    { "6.2",            "",                     0,              AV_OPT_TYPE_CONST, { .i64 = 62 }, 0, 0,  VE, "level" },
+
+
+    /// Quality Preset
+    { "quality",        "Quality Preference",                   OFFSET(quality),    AV_OPT_TYPE_INT,   { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED    }, AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED, AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY, VE, "quality" },
+    { "speed",          "Prefer Speed",                         0,                  AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED    },       0, 0, VE, "quality" },
+    { "balanced",       "Balanced",                             0,                  AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED },    0, 0, VE, "quality" },
+    { "quality",        "Prefer Quality",                       0,                  AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY  },     0, 0, VE, "quality" },
+
+    // Dynamic
+    /// Rate Control Method
+    { "rc",             "Rate Control Method",                  OFFSET(rate_control_mode),  AV_OPT_TYPE_INT,   { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, VE, "rc" },
+    { "unknown",        "Unknown",                              0,                          AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN                 }, 0, 0, VE, "rc" },
+    { "cqp",            "Constant Quantization Parameter",      0,                          AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP             }, 0, 0, VE, "rc" },
+    { "cbr",            "Constant Bitrate",                     0,                          AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR                     }, 0, 0, VE, "rc" },
+    { "vbr_peak",       "Peak Contrained Variable Bitrate",     0,                          AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR    }, 0, 0, VE, "rc" },
+    { "vbr_latency",    "Latency Constrained Variable Bitrate", 0,                          AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" },
+
+    /// Enforce HRD, Filler Data, VBAQ, Frame Skipping
+    { "enforce_hrd",    "Enforce HRD",                          OFFSET(enforce_hrd),        AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+    { "filler_data",    "Filler Data Enable",                   OFFSET(filler_data),        AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+    { "vbaq",           "Enable VBAQ",                          OFFSET(enable_vbaq),        AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+    { "frame_skipping", "Rate Control Based Frame Skip",        OFFSET(skip_frame),         AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+
+    /// QP Values
+    { "qp_i",           "Quantization Parameter for I-Frame",   OFFSET(qp_i),               AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
+    { "qp_p",           "Quantization Parameter for P-Frame",   OFFSET(qp_p),               AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
+    { "qp_b",           "Quantization Parameter for B-Frame",   OFFSET(qp_b),               AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
+
+    /// Pre-Pass, Pre-Analysis, Two-Pass
+    { "preanalysis",    "Pre-Analysis Mode",                    OFFSET(preanalysis),        AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE, NULL },
+
+    /// Maximum Access Unit Size
+    { "max_au_size",    "Maximum Access Unit Size for rate control (in bits)",   OFFSET(max_au_size),        AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
+
+    /// Header Insertion Spacing
+    { "header_spacing", "Header Insertion Spacing",             OFFSET(header_spacing),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE },
+
+    /// B-Frames
+    // BPicturesPattern=bf
+    { "bf_delta_qp",    "B-Picture Delta QP",                   OFFSET(b_frame_delta_qp),   AV_OPT_TYPE_INT,  { .i64 = 4 }, -10, 10, VE },
+    { "bf_ref",         "Enable Reference to B-Frames",         OFFSET(b_frame_ref),        AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
+    { "bf_ref_delta_qp","Reference B-Picture Delta QP",         OFFSET(ref_b_frame_delta_qp), AV_OPT_TYPE_INT,  { .i64 = 4 }, -10, 10, VE },
+
+    /// Intra-Refresh
+    { "intra_refresh_mb","Intra Refresh MBs Number Per Slot in Macroblocks",       OFFSET(intra_refresh_mb),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
+
+    /// coder
+    { "coder",          "Coding Type",                          OFFSET(coding_mode),   AV_OPT_TYPE_INT,   { .i64 = AMF_VIDEO_ENCODER_UNDEFINED }, AMF_VIDEO_ENCODER_UNDEFINED, AMF_VIDEO_ENCODER_CALV, VE, "coder" },
+    { "auto",           "Automatic",                            0,                     AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_UNDEFINED }, 0, 0, VE, "coder" },
+    { "cavlc",          "Context Adaptive Variable-Length Coding", 0,                  AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CALV },      0, 0, VE, "coder" },
+    { "cabac",          "Context Adaptive Binary Arithmetic Coding", 0,                AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CABAC },     0, 0, VE, "coder" },
+
+    { "me_half_pel",    "Enable ME Half Pixel",                 OFFSET(me_half_pel),   AV_OPT_TYPE_BOOL,  { .i64 = 1 }, 0, 1, VE },
+    { "me_quarter_pel", "Enable ME Quarter Pixel",              OFFSET(me_quarter_pel),AV_OPT_TYPE_BOOL,  { .i64 = 1 }, 0, 1, VE },
+
+    { "aud",            "Inserts AU Delimiter NAL unit",         OFFSET(aud)          ,AV_OPT_TYPE_BOOL,  { .i64 = 0 }, 0, 1, VE },
+
+    { "log_to_dbg",     "Enable AMF logging to debug output",   OFFSET(log_to_dbg)    , AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+
+    
+    { NULL }
+};
+
+static av_cold int amf_encode_init_h264(AVCodecContext *avctx)
+{
+    int                              ret = 0;
+    AMF_RESULT                       res = AMF_OK;
+    AmfContext                      *ctx = avctx->priv_data;
+    AMFVariantStruct                 var = { 0 };
+    amf_int64                        profile = 0;
+    amf_int64                        profile_level = 0;
+    AMFBuffer                       *buffer;
+    AMFGuid                          guid;
+    AMFRate                          framerate;
+    AMFSize                          framesize = AMFConstructSize(avctx->width, avctx->height);
+    int                              deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
+
+    if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
+        framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den);
+    }else {
+        framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame);
+    }
+
+    if ((ret = ff_amf_encode_init(avctx)) != 0)
+        return ret;
+
+    // Static parameters
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_USAGE, ctx->usage);
+
+    AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMESIZE, framesize);
+
+    AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMERATE, framerate);
+
+    switch (avctx->profile) {
+    case FF_PROFILE_H264_BASELINE:
+        profile = AMF_VIDEO_ENCODER_PROFILE_BASELINE;
+        break;
+    case FF_PROFILE_H264_MAIN:
+        profile = AMF_VIDEO_ENCODER_PROFILE_MAIN;
+        break;
+    case FF_PROFILE_H264_HIGH:
+        profile = AMF_VIDEO_ENCODER_PROFILE_HIGH;
+        break;
+    case FF_PROFILE_H264_CONSTRAINED_BASELINE:
+        profile = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_BASELINE;
+        break;
+    case (FF_PROFILE_H264_HIGH | FF_PROFILE_H264_CONSTRAINED):
+        profile = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH;
+        break;
+    }
+    if (profile == 0) {
+        profile = ctx->profile;
+    }
+
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE, profile);
+
+    profile_level = avctx->level;
+    if (profile_level == FF_LEVEL_UNKNOWN) {
+        profile_level = ctx->level;
+    }
+    if (profile_level != 0) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE_LEVEL, profile_level);
+    }
+
+    // Maximum Reference Frames
+    if (avctx->refs != -1) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_NUM_REFRAMES, avctx->refs);
+    }
+    if (avctx->sample_aspect_ratio.den && avctx->sample_aspect_ratio.num) {
+        AMFRatio ratio = AMFConstructRatio(avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
+        AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio);
+    }
+
+    /// Color Range (Partial/TV/MPEG or Full/PC/JPEG)
+    if (avctx->color_range == AVCOL_RANGE_JPEG) {
+        AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1);
+    }
+
+    // autodetect rate control method
+    if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN) { 
+        if (ctx->qp_i != -1 || ctx->qp_p != -1 || ctx->qp_b != -1) {
+            ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP;
+            av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n");
+        }else if (avctx->rc_max_rate > 0 ) {
+            ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR;
+            av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n");
+        } else {
+            ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR;
+            av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n");
+        }
+    }
+
+
+    if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, AMF_VIDEO_ENCODER_PREENCODE_DISABLED);
+        if (ctx->preanalysis)
+            av_log(ctx, AV_LOG_WARNING, "Pre-Analysis is not supported by cqp Rate Control Method, automatically disabled\n");
+    } else {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis);
+    }
+
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUALITY_PRESET, ctx->quality);
+
+    // Initialize Encoder
+    res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res);
+
+    // Dynamic parmaters
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, ctx->rate_control_mode);
+
+    /// VBV Buffer
+    if (avctx->rc_buffer_size != 0) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, avctx->rc_buffer_size);
+        if (avctx->rc_initial_buffer_occupancy != 0) {
+            int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size;
+            if (amf_buffer_fullness > 64)
+                amf_buffer_fullness = 64;
+            AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness);
+        }
+    }
+    /// Maximum Access Unit Size
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_AU_SIZE, ctx->max_au_size);
+
+    if (ctx->max_au_size)
+        ctx->enforce_hrd = 1;
+
+    // QP Minimum / Maximum
+    if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 0);
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 51);
+    } else {
+        if (avctx->qmin != -1) {
+            int qval = avctx->qmin > 51 ? 51 : avctx->qmin;
+            AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, qval);
+        }
+        if (avctx->qmax != -1) {
+            int qval = avctx->qmax > 51 ? 51 : avctx->qmax;
+            AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, qval);
+        }
+    }
+    // QP Values
+    if (ctx->qp_i != -1)
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_I, ctx->qp_i);
+    if (ctx->qp_p != -1)
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_P, ctx->qp_p);
+    if (ctx->qp_b != -1)
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_B, ctx->qp_b);
+
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_TARGET_BITRATE, avctx->bit_rate);
+
+    if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->bit_rate);
+    }
+    if (avctx->rc_max_rate) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->rc_max_rate);
+    }else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) {
+        av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n");
+    }
+    // Enforce HRD, Filler Data, VBAQ, Frame Skipping, Deblocking Filter
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENFORCE_HRD, !!ctx->enforce_hrd);
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, !!ctx->filler_data);
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, !!ctx->skip_frame);
+    if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) {
+        AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, 0);
+        if (ctx->enable_vbaq)
+            av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n");
+    } else {
+        AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, !!ctx->enable_vbaq);
+    }
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, !!deblocking_filter);
+
+    // B-Frames
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, avctx->max_b_frames);
+    if (res != AMF_OK) {
+        res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var);
+        av_log(ctx, AV_LOG_WARNING, "B-frames=%d is not supported by this GPU, switched to %d\n", 
+            avctx->max_b_frames, (int)var.int64Value);
+        avctx->max_b_frames = (int)var.int64Value;
+    }
+    if (avctx->max_b_frames) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, ctx->b_frame_delta_qp);
+        AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, !!ctx->b_frame_ref);
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, ctx->ref_b_frame_delta_qp);
+    }
+
+    // Keyframe Interval
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_IDR_PERIOD, avctx->gop_size);
+
+    // Header Insertion Spacing
+    if (ctx->header_spacing >= 0)
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, ctx->header_spacing);
+
+    // Intra-Refresh, Slicing
+    if (ctx->intra_refresh_mb > 0)
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, ctx->intra_refresh_mb);
+    if (avctx->slices > 1)
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_SLICES_PER_FRAME, avctx->slices);
+
+    // Coding
+    if (ctx->coding_mode != 0)
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_CABAC_ENABLE, ctx->coding_mode);
+
+    // Motion Estimation
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, !!ctx->me_half_pel);
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, !!ctx->me_quarter_pel);
+
+    // fill extradata
+    res = AMFVariantInit(&var);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res);
+
+    res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_EXTRADATA, &var);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res);
+    AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n");
+
+    guid = IID_AMFBuffer();
+
+    res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface
+    if (res != AMF_OK) {
+        var.pInterface->pVtbl->Release(var.pInterface);
+    }
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res);
+
+    avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer);
+    avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!avctx->extradata) {
+        buffer->pVtbl->Release(buffer);
+        var.pInterface->pVtbl->Release(var.pInterface);
+        return AVERROR(ENOMEM);
+    }
+    memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size);
+
+    buffer->pVtbl->Release(buffer);
+    var.pInterface->pVtbl->Release(var.pInterface);
+    
+    return 0;
+}
+
+static const AVCodecDefault defaults[] = {
+    { "refs",       "-1"  },
+    { "aspect",     "0"   },
+    { "sar",        "0"   },
+    { "qmin",       "-1"  },
+    { "qmax",       "-1"  },
+    { "b",          "2M"  },
+    { "g",          "250" },
+    { "slices",     "1"   },
+    { NULL                },
+};
+
+static const AVClass h264_amf_class = {
+    .class_name = "h264_amf",
+    .item_name = av_default_item_name,
+    .option = options,
+    .version = LIBAVUTIL_VERSION_INT,
+};
+//TODO declare as HW encoder when available
+AVCodec ff_h264_amf_encoder = {
+    .name           = "h264_amf",
+    .long_name      = NULL_IF_CONFIG_SMALL("AMD AMF H.264 Encoder"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .init           = amf_encode_init_h264,
+    .send_frame     = ff_amf_send_frame,
+    .receive_packet = ff_amf_receive_packet,
+    .close          = ff_amf_encode_close,
+    .priv_data_size = sizeof(AmfContext),
+    .priv_class     = &h264_amf_class,
+    .defaults       = defaults,
+    .capabilities   = AV_CODEC_CAP_DELAY,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .pix_fmts       = ff_amf_pix_fmts,
+};
diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c
new file mode 100644
index 0000000..b6536b3
--- /dev/null
+++ b/libavcodec/amfenc_hevc.c
@@ -0,0 +1,327 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "amfenc.h"
+#include "internal.h"
+
+#define OFFSET(x) offsetof(AmfContext, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "usage",          "Set the encoding usage",             OFFSET(usage),          AV_OPT_TYPE_INT,   { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING }, AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM, VE, "usage" },
+    { "transcoding",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING },         0, 0, VE, "usage" },
+    { "ultralowlatency","", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY },    0, 0, VE, "usage" },
+    { "lowlatency",     "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY },          0, 0, VE, "usage" },
+    { "webcam",         "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM },               0, 0, VE, "usage" },
+
+    { "profile",        "Set the profile (default main)",           OFFSET(profile),   AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, VE, "profile" },
+    { "main",           "", 0,                      AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, 0, 0, VE, "profile" },
+
+    { "profile_tier",   "Set the profile tier (default main)",      OFFSET(tier), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, AMF_VIDEO_ENCODER_HEVC_TIER_MAIN, AMF_VIDEO_ENCODER_HEVC_TIER_HIGH, VE, "tier" },
+    { "main",           "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, 0, 0, VE, "tier" },
+    { "high",           "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_HIGH }, 0, 0, VE, "tier" },
+
+    { "level",          "Set the encoding level (default auto)",    OFFSET(level), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, AMF_LEVEL_6_2, VE, "level" },
+    { "auto",           "", 0, AV_OPT_TYPE_CONST, { .i64 = 0             }, 0, 0, VE, "level" },
+    { "1.0",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_1   }, 0, 0, VE, "level" },
+    { "2.0",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_2   }, 0, 0, VE, "level" },
+    { "2.1",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_2_1 }, 0, 0, VE, "level" },
+    { "3.0",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_3   }, 0, 0, VE, "level" },
+    { "3.1",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_3_1 }, 0, 0, VE, "level" },
+    { "4.0",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_4   }, 0, 0, VE, "level" },
+    { "4.1",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_4_1 }, 0, 0, VE, "level" },
+    { "5.0",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5   }, 0, 0, VE, "level" },
+    { "5.1",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5_1 }, 0, 0, VE, "level" },
+    { "5.2",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5_2 }, 0, 0, VE, "level" },
+    { "6.0",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6   }, 0, 0, VE, "level" },
+    { "6.1",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6_1 }, 0, 0, VE, "level" },
+    { "6.2",            "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6_2 }, 0, 0, VE, "level" },
+
+    { "quality",        "Set the encoding quality",                 OFFSET(quality),      AV_OPT_TYPE_INT,   { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED }, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED, VE, "quality" },
+    { "balanced",       "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality" },
+    { "speed",          "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED    }, 0, 0, VE, "quality" },
+    { "quality",        "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY  }, 0, 0, VE, "quality" },
+
+    { "rc",             "Set the rate control mode",            OFFSET(rate_control_mode),   AV_OPT_TYPE_INT,   { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR, VE, "rc" },
+    { "unknown",        "Unknown",                              0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN                 }, 0, 0, VE, "rc" },
+    { "cqp",            "Constant Quantization Parameter",      0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP             }, 0, 0, VE, "rc" },
+    { "cbr",            "Constant Bitrate",                     0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR                     }, 0, 0, VE, "rc" },
+    { "vbr_peak",       "Peak Contrained Variable Bitrate",     0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR    }, 0, 0, VE, "rc" },
+    { "vbr_latency",    "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" },
+
+    { "header_insertion_mode",        "Set header insertion mode",  OFFSET(header_insertion_mode),      AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE }, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED, VE, "hdrmode" },
+    { "none",           "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE        }, 0, 0, VE, "hdrmode" },
+    { "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 },
+    { "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},
+    { "filler_data",    "Filler Data Enable",                       OFFSET(filler_data),   AV_OPT_TYPE_BOOL, { .i64 = 0  },  0, 1, VE},
+    { "max_au_size",    "Maximum Access Unit Size for rate control (in bits)", OFFSET(max_au_size),   AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, INT_MAX, VE},
+    { "min_qp_i",       "min quantization parameter for I-frame",   OFFSET(min_qp_i),      AV_OPT_TYPE_INT, { .i64 = -1  }, -1, 51, VE },
+    { "max_qp_i",       "max quantization parameter for I-frame",   OFFSET(max_qp_i),      AV_OPT_TYPE_INT, { .i64 = -1  }, -1, 51, VE },
+    { "min_qp_p",       "min quantization parameter for P-frame",   OFFSET(min_qp_p),      AV_OPT_TYPE_INT, { .i64 = -1  }, -1, 51, VE },
+    { "max_qp_p",       "max quantization parameter for P-frame",   OFFSET(max_qp_p),      AV_OPT_TYPE_INT, { .i64 = -1  }, -1, 51, VE },
+    { "qp_p",           "quantization parameter for P-frame",       OFFSET(qp_p),          AV_OPT_TYPE_INT, { .i64 = -1  }, -1, 51, VE },
+    { "qp_i",           "quantization parameter for I-frame",       OFFSET(qp_i),          AV_OPT_TYPE_INT, { .i64 = -1  }, -1, 51, VE },
+    { "skip_frame",     "Rate Control Based Frame Skip",            OFFSET(skip_frame),    AV_OPT_TYPE_BOOL,{ .i64 = 0   },  0, 1, VE },
+    { "me_half_pel",    "Enable ME Half Pixel",                     OFFSET(me_half_pel),   AV_OPT_TYPE_BOOL,{ .i64 = 1   },  0, 1, VE },
+    { "me_quarter_pel", "Enable ME Quarter Pixel ",                 OFFSET(me_quarter_pel),AV_OPT_TYPE_BOOL,{ .i64 = 1   },  0, 1, VE },
+
+    { "aud",            "Inserts AU Delimiter NAL unit",            OFFSET(aud)           ,AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE },
+
+    { "log_to_dbg",     "Enable AMF logging to debug output",   OFFSET(log_to_dbg), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE },
+    { NULL }
+};
+
+static av_cold int amf_encode_init_hevc(AVCodecContext *avctx)
+{
+    int                 ret = 0;
+    AMF_RESULT          res = AMF_OK;
+    AmfContext         *ctx = avctx->priv_data;
+    AMFVariantStruct    var = {0};
+    amf_int64           profile = 0;
+    amf_int64           profile_level = 0;
+    AMFBuffer          *buffer;
+    AMFGuid             guid;
+    AMFRate             framerate;
+    AMFSize             framesize = AMFConstructSize(avctx->width, avctx->height);
+    int                 deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
+
+    if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
+        framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den);
+    }else {
+        framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame);
+    }
+
+    if ((ret = ff_amf_encode_init(avctx)) < 0)
+        return ret;
+
+    // init static parameters
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_USAGE, ctx->usage);
+
+    AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMESIZE, framesize);
+
+    AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMERATE, framerate);
+
+    switch (avctx->profile) {
+    case FF_PROFILE_HEVC_MAIN:
+        profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN;
+        break;
+    default:
+        break;
+    }
+    if (profile == 0) {
+        profile = ctx->profile;
+    }
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE, profile);
+
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier);
+
+    profile_level = avctx->level;
+    if (profile_level == 0) {
+        profile_level = ctx->level;
+    }
+    if (profile_level != 0) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE_LEVEL, profile_level);
+    }
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality);
+    // Maximum Reference Frames
+    if (avctx->refs != 0) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES, avctx->refs);
+    }
+    // Aspect Ratio
+    if (avctx->sample_aspect_ratio.den && avctx->sample_aspect_ratio.num) {
+        AMFRatio ratio = AMFConstructRatio(avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
+        AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio);
+    }
+
+    // Picture control properties
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr);
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size);
+    if (avctx->slices > 1) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_SLICES_PER_FRAME, avctx->slices);
+    }
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE, deblocking_filter);
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE, ctx->header_insertion_mode);
+
+    // Rate control
+    // autodetect rate control method
+    if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN) {
+        if (ctx->min_qp_i != -1 || ctx->max_qp_i != -1 || 
+            ctx->min_qp_p != -1 || ctx->max_qp_p != -1 ||
+            ctx->qp_i !=-1 || ctx->qp_p != -1) {
+            ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP;
+            av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n");
+        }else if (avctx->rc_max_rate > 0) {
+            ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR;
+            av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n");
+        }else {
+            ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR;
+            av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n");
+        }
+    }
+
+
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD, ctx->rate_control_mode);
+    if (avctx->rc_buffer_size) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_VBV_BUFFER_SIZE, avctx->rc_buffer_size);
+
+        if (avctx->rc_initial_buffer_occupancy != 0) {
+            int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size;
+            if (amf_buffer_fullness > 64)
+                amf_buffer_fullness = 64;
+            AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness);
+        }
+    }
+    // Pre-Pass, Pre-Analysis, Two-Pass
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis);
+
+    if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) {
+        AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, false);
+        if (ctx->enable_vbaq)
+            av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n");
+    } else {
+        AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, !!ctx->enable_vbaq);
+    }
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_HALF_PIXEL, ctx->me_half_pel);
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_QUARTERPIXEL, ctx->me_quarter_pel);
+
+    // init encoder
+    res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res);
+
+    // init dynamic rate control params
+    if (ctx->max_au_size)
+        ctx->enforce_hrd = 1;
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENFORCE_HRD, ctx->enforce_hrd);
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FILLER_DATA_ENABLE, ctx->filler_data);
+
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE, avctx->bit_rate);
+
+    if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->bit_rate);
+    } 
+    if(avctx->rc_max_rate){
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->rc_max_rate);
+    }else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) {
+        av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n");
+    }
+
+    // init dynamic picture control params
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_AU_SIZE, ctx->max_au_size);
+
+    if (ctx->min_qp_i != -1) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, ctx->min_qp_i);
+    }else if (avctx->qmin != -1) {
+        int qval = avctx->qmin > 51 ? 51 : avctx->qmin;
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, qval);
+    }
+    if (ctx->max_qp_i != -1) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, ctx->max_qp_i);
+    }else if (avctx->qmax != -1) {
+        int qval = avctx->qmax > 51 ? 51 : avctx->qmax;
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, qval);
+    }
+    if (ctx->min_qp_p != -1) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, ctx->min_qp_p);
+    }else if (avctx->qmin != -1) {
+        int qval = avctx->qmin > 51 ? 51 : avctx->qmin;
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, qval);
+    }
+    if (ctx->max_qp_p != -1) {
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, ctx->max_qp_p);
+    }else if (avctx->qmax != -1) {
+        int qval = avctx->qmax > 51 ? 51 : avctx->qmax;
+        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, qval);
+    }
+
+    if (ctx->qp_p != -1) {
+        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_P, ctx->qp_i);
+    }
+    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame);
+
+
+    // fill extradata
+    res = AMFVariantInit(&var);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res);
+
+    res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_HEVC_EXTRADATA, &var);
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res);
+    AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n");
+
+    guid = IID_AMFBuffer();
+
+    res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface
+    if (res != AMF_OK) {
+        var.pInterface->pVtbl->Release(var.pInterface);
+    }
+    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res);
+
+    avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer);
+    avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!avctx->extradata) {
+        buffer->pVtbl->Release(buffer);
+        var.pInterface->pVtbl->Release(var.pInterface);
+        return AVERROR(ENOMEM);
+    }
+    memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size);
+
+    buffer->pVtbl->Release(buffer);
+    var.pInterface->pVtbl->Release(var.pInterface);
+
+    return 0;
+}
+static const AVCodecDefault defaults[] = {
+    { "refs",       "-1"  },
+    { "aspect",     "0"   },
+    { "sar",        "0"   },
+    { "b",          "2M"  },
+    { "g",          "250" },
+    { "slices",     "1"   },
+    { NULL                },
+};
+static const AVClass hevc_amf_class = {
+    .class_name = "hevc_amf",
+    .item_name = av_default_item_name,
+    .option = options,
+    .version = LIBAVUTIL_VERSION_INT,
+};
+//TODO declare as HW encoder when available
+AVCodec ff_hevc_amf_encoder = {
+    .name           = "hevc_amf",
+    .long_name      = NULL_IF_CONFIG_SMALL("AMD AMF HEVC encoder"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_HEVC,
+    .init           = amf_encode_init_hevc,
+    .send_frame     = ff_amf_send_frame,
+    .receive_packet = ff_amf_receive_packet,
+    .close          = ff_amf_encode_close,
+    .priv_data_size = sizeof(AmfContext),
+    .priv_class     = &hevc_amf_class,
+    .defaults       = defaults,
+    .capabilities   = AV_CODEC_CAP_DELAY,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .pix_fmts       = ff_amf_pix_fmts,
+};