[PATCH 1/2] winegstreamer: Add helper for GstCaps <-> IMFMediaType conversion.

Derek Lesho dlesho at codeweavers.com
Tue Mar 24 14:39:52 CDT 2020


Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
 dlls/winegstreamer/gst_private.h |   4 +
 dlls/winegstreamer/mfplat.c      | 533 ++++++++++++++++++++++++++++++-
 include/codecapi.h               |  38 +++
 3 files changed, 574 insertions(+), 1 deletion(-)
 create mode 100644 include/codecapi.h

diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index e6fb841fc8..a6c3fd3784 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -36,6 +36,7 @@
 #include "winuser.h"
 #include "dshow.h"
 #include "strmif.h"
+#include "mfobjects.h"
 #include "wine/heap.h"
 #include "wine/strmbase.h"
 
@@ -54,4 +55,7 @@ void start_dispatch_thread(void) DECLSPEC_HIDDEN;
 
 extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN;
 
+IMFMediaType* media_type_from_caps(GstCaps *caps);
+GstCaps *caps_from_media_type(IMFMediaType *type);
+
 #endif /* __GST_PRIVATE_INCLUDED__ */
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 55b9b08876..a6f4fbc2ec 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -16,11 +16,16 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+#include <gst/gst.h>
+
+#include "gst_private.h"
+
 #include <stdarg.h>
 
 #include "gst_private.h"
 #include "mfapi.h"
-#include "mfidl.h"
+#include "codecapi.h"
 
 #include "wine/debug.h"
 #include "wine/heap.h"
@@ -433,3 +438,529 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
 
     return CLASS_E_CLASSNOTAVAILABLE;
 }
+
+struct aac_user_data
+{
+    WORD payload_type;
+    WORD profile_level_indication;
+    WORD struct_type;
+    WORD reserved;
+  /*BYTE audio_specific_config;*/
+};
+
+/* IMPORTANT: caps will be modified to represent the exact type needed for the format */
+IMFMediaType* media_type_from_caps(GstCaps *caps)
+{
+    IMFMediaType *media_type;
+    GstStructure *info;
+    const char *media_type_name;
+    gchar *human_readable;
+
+    if (FAILED(MFCreateMediaType(&media_type)))
+    {
+        return NULL;
+    }
+
+    info = gst_caps_get_structure(caps, 0);
+    media_type_name = gst_structure_get_name(info);
+
+    human_readable = gst_caps_to_string(caps);
+    TRACE("caps = %s\n", human_readable);
+    g_free(human_readable);
+
+    if (!(strncmp(media_type_name, "video", 5)))
+    {
+        const char *video_format = media_type_name + 6;
+        gint width, height, framerate_num, framerate_den;
+
+        IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
+
+        if (gst_structure_get_int(info, "width", &width) && gst_structure_get_int(info, "height", &height))
+        {
+            IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)width << 32) | height);
+        }
+        if (gst_structure_get_fraction(info, "framerate", &framerate_num, &framerate_den))
+        {
+            IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, ((UINT64)framerate_num << 32) | framerate_den);
+        }
+
+        if (!(strcmp(video_format, "x-h264")))
+        {
+            const char *profile, *level;
+
+            IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_H264);
+            IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, TRUE);
+
+            if ((profile = gst_structure_get_string(info, "profile")))
+            {
+                if (!(strcmp(profile, "main")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_Main);
+                else if (!(strcmp(profile, "high")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_High);
+                else if (!(strcmp(profile, "high-4:4:4")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_444);
+                else
+                    ERR("Unrecognized profile %s\n", profile);
+            }
+            if ((level = gst_structure_get_string(info, "level")))
+            {
+                if (!(strcmp(level, "1")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel1);
+                else if (!(strcmp(level, "1.1")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel1_1);
+                else if (!(strcmp(level, "1.2")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel1_2);
+                else if (!(strcmp(level, "1.3")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel1_3);
+                else if (!(strcmp(level, "2")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel2);
+                else if (!(strcmp(level, "2.1")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel2_1);
+                else if (!(strcmp(level, "2.2")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel2_2);
+                else if (!(strcmp(level, "3")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel3);
+                else if (!(strcmp(level, "3.1")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel3_1);
+                else if (!(strcmp(level, "3.2")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel3_2);
+                else if (!(strcmp(level, "4")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel4);
+                else if (!(strcmp(level, "4.1")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel4_1);
+                else if (!(strcmp(level, "4.2")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel4_2);
+                else if (!(strcmp(level, "5")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel5);
+                else if (!(strcmp(level, "5.1")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel5_1);
+                else if (!(strcmp(level, "5.2")))
+                    IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, eAVEncH264VLevel5_2);
+                else
+                    ERR("Unrecognized level %s\n", level);
+            }
+            gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "byte-stream", NULL);
+            gst_caps_set_simple(caps, "alignment", G_TYPE_STRING, "au", NULL);
+            for (unsigned int i = 0; i < gst_caps_get_size(caps); i++)
+            {
+                GstStructure *structure = gst_caps_get_structure (caps, i);
+                gst_structure_remove_field(structure, "codec_data");
+            }
+        }
+        else if (!(strcmp(video_format, "x-wmv")))
+        {
+            gint wmv_version;
+            const char *format;
+            const GValue *codec_data;
+
+            if (gst_structure_get_int(info, "wmvversion", &wmv_version))
+            {
+                switch (wmv_version)
+                {
+                    case 1:
+                        IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WMV1);
+                        break;
+                    case 2:
+                        IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WMV2);
+                        break;
+                    case 3:
+                        IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WMV3);
+                        break;
+                    default:
+                        ERR("Unrecognized wmvversion %d\n", wmv_version);
+                }
+            }
+
+            if ((format = gst_structure_get_string(info, "format")))
+            {
+                if (!(strcmp(format, "WVC1")))
+                    IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WVC1);
+            }
+
+            if ((codec_data = gst_structure_get_value(info, "codec_data")))
+            {
+                GstBuffer *codec_data_buffer = gst_value_get_buffer(codec_data);
+                if (codec_data_buffer)
+                {
+                    gsize codec_data_size = gst_buffer_get_size(codec_data_buffer);
+                    gpointer codec_data_raw = heap_alloc(codec_data_size);
+                    gst_buffer_extract(codec_data_buffer, 0, codec_data_raw, codec_data_size);
+                    IMFMediaType_SetBlob(media_type, &MF_MT_USER_DATA, codec_data_raw, codec_data_size);
+                }
+            }
+        }
+        else if (!(strcmp(video_format, "mpeg")))
+        {
+            IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_M4S2);
+            IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, TRUE);
+        }
+        else if (!(strcmp(video_format, "x-raw")))
+        {
+            const char *fourcc = gst_structure_get_string(info, "stream-format");
+            IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, FALSE);
+            if (fourcc && (strlen(fourcc) == 4))
+            {
+                GUID fourcc_subtype = MFVideoFormat_Base;
+                fourcc_subtype.Data1 = MAKEFOURCC(
+                    toupper(fourcc[0]), toupper(fourcc[1]), toupper(fourcc[2]), toupper(fourcc[3]));
+                IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &fourcc_subtype);
+            }
+            else
+                ERR("uncompressed video has no stream-format\n");
+        }
+        else
+            ERR("Unrecognized video format %s\n", video_format);
+    }
+    else if (!(strncmp(media_type_name, "audio", 5)))
+    {
+        const char *audio_format = media_type_name + 6;
+
+        IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
+        if (!(strcmp(audio_format, "mpeg")))
+        {
+            int mpeg_version = -1;
+
+            IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, TRUE);
+
+            if (!(gst_structure_get_int(info, "mpegversion", &mpeg_version)))
+                ERR("Failed to get mpegversion\n");
+            switch (mpeg_version)
+            {
+                case 1:
+                {
+                    IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_MPEG);
+                    break;
+                }
+                case 2:
+                case 4:
+                {
+                    const char *format, *profile, *level;
+                    DWORD profile_level_indication = 0;
+                    const GValue *codec_data;
+                    DWORD asc_size = 0;
+                    struct aac_user_data *user_data = NULL;
+
+                    IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_AAC);
+
+                    codec_data = gst_structure_get_value(info, "codec_data");
+                    if (codec_data)
+                    {
+                        GstBuffer *codec_data_buffer = gst_value_get_buffer(codec_data);
+                        if (codec_data_buffer)
+                        {
+                            if ((asc_size = gst_buffer_get_size(codec_data_buffer)) >= 2)
+                            {
+                                user_data = heap_alloc_zero(sizeof(*user_data)+asc_size);
+                                gst_buffer_extract(codec_data_buffer, 0, (gpointer)(user_data + 1), asc_size);
+                            }
+                            else
+                                ERR("Unexpected buffer size\n");
+                        }
+                        else
+                            ERR("codec_data not a buffer\n");
+                    }
+                    else
+                        ERR("codec_data not found\n");
+                    if (!user_data)
+                        user_data = heap_alloc_zero(sizeof(*user_data));
+
+                    {
+                        int rate;
+                        if (gst_structure_get_int(info, "rate", &rate))
+                            IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, rate);
+                    }
+                    {
+                        int channels;
+                        if (gst_structure_get_int(info, "channels", &channels))
+                            IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, channels);
+                    }
+
+                    if ((format = gst_structure_get_string(info, "stream-format")))
+                    {
+                        DWORD payload_type = -1;
+                        if (!(strcmp(format, "raw")))
+                            payload_type = 0;
+                        else if (!(strcmp(format, "adts")))
+                            payload_type = 1;
+                        else
+                            ERR("Unrecognized stream-format\n");
+                        if (payload_type != -1)
+                        {
+                            IMFMediaType_SetUINT32(media_type, &MF_MT_AAC_PAYLOAD_TYPE, payload_type);
+                            user_data->payload_type = payload_type;
+                        }
+                    }
+                    else
+                    {
+                        ERR("Stream format not present\n");
+                    }
+
+                    profile = gst_structure_get_string(info, "profile");
+                    level = gst_structure_get_string(info, "level");
+                    /* Data from https://docs.microsoft.com/en-us/windows/win32/medfound/aac-encoder#output-types */
+                    if (profile && level)
+                    {
+                        if (!(strcmp(profile, "lc")) && !(strcmp(level, "2")))
+                            profile_level_indication = 0x29;
+                        else if (!(strcmp(profile, "lc")) && !(strcmp(level, "4")))
+                            profile_level_indication = 0x2A;
+                        else if (!(strcmp(profile, "lc")) && !(strcmp(level, "5")))
+                            profile_level_indication = 0x2B;
+                        else
+                            ERR("Unhandled profile/level combo\n");
+                    }
+                    else
+                        ERR("Profile or level not present\n");
+
+                    if (profile_level_indication)
+                    {
+                        IMFMediaType_SetUINT32(media_type, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, profile_level_indication);
+                        user_data->profile_level_indication = profile_level_indication;
+                    }
+
+                    IMFMediaType_SetBlob(media_type, &MF_MT_USER_DATA, (BYTE *)user_data, sizeof(user_data) + asc_size);
+                    heap_free(user_data);
+                    break;
+                }
+                default:
+                    ERR("Unhandled mpegversion %d\n", mpeg_version);
+            }
+        }
+        else if (!(strcmp(audio_format, "x-raw")))
+        {
+            IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
+
+            gst_caps_set_simple(caps, "format", G_TYPE_STRING, "F32LE", NULL);
+        }
+        else
+            ERR("Unrecognized audio format %s\n", audio_format);
+    }
+    else
+    {
+        goto fail;
+    }
+
+    return media_type;
+    fail:
+    IMFMediaType_Release(media_type);
+    return NULL;
+}
+
+static const char *fourcc_str(DWORD fourcc)
+{
+    if (!fourcc) return NULL;
+    return wine_dbg_sprintf ("%c%c%c%c",
+        (char)(fourcc), (char)(fourcc >> 8),
+        (char)(fourcc >> 16), (char)(fourcc >> 24));
+}
+
+GstCaps *caps_from_media_type(IMFMediaType *type)
+{
+    GUID major_type;
+    GUID subtype;
+    GUID base_masked_subtype;
+    GstCaps *output = NULL;
+
+    if (FAILED(IMFMediaType_GetMajorType(type, &major_type)))
+        return NULL;
+    if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+        return NULL;
+    base_masked_subtype = subtype;
+    base_masked_subtype.Data1 = 0;
+
+    if (IsEqualGUID(&major_type, &MFMediaType_Video))
+    {
+        UINT64 frame_rate = 0, frame_size = 0;
+        DWORD *framerate_num = ((DWORD*)&frame_rate) + 1;
+        DWORD *framerate_den = ((DWORD*)&frame_rate);
+        DWORD *width = ((DWORD*)&frame_size) + 1;
+        DWORD *height = ((DWORD*)&frame_size);
+
+        if (IsEqualGUID(&subtype, &MFVideoFormat_H264))
+        {
+            enum eAVEncH264VProfile h264_profile;
+            enum eAVEncH264VLevel h264_level;
+            output = gst_caps_new_empty_simple("video/x-h264");
+            gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "byte-stream", NULL);
+            gst_caps_set_simple(output, "alignment", G_TYPE_STRING, "au", NULL);
+
+            if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_PROFILE, &h264_profile)))
+            {
+                const char *profile = NULL;
+                switch (h264_profile)
+                {
+                    case eAVEncH264VProfile_Main: profile = "main"; break;
+                    case eAVEncH264VProfile_High: profile = "high"; break;
+                    case eAVEncH264VProfile_444: profile = "high-4:4:4"; break;
+                    default: ERR("Unknown profile %u\n", h264_profile);
+                }
+                if (profile)
+                    gst_caps_set_simple(output, "profile", G_TYPE_STRING, profile, NULL);
+            }
+            if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &h264_level)))
+            {
+                const char *level = NULL;
+                switch (h264_level)
+                {
+                    case eAVEncH264VLevel1:   level = "1";   break;
+                    case eAVEncH264VLevel1_1: level = "1.1"; break;
+                    case eAVEncH264VLevel1_2: level = "1.2"; break;
+                    case eAVEncH264VLevel1_3: level = "1.3"; break;
+                    case eAVEncH264VLevel2:   level = "2";   break;
+                    case eAVEncH264VLevel2_1: level = "2.1"; break;
+                    case eAVEncH264VLevel2_2: level = "2.2"; break;
+                    case eAVEncH264VLevel3:   level = "3";   break;
+                    case eAVEncH264VLevel3_1: level = "3.1"; break;
+                    case eAVEncH264VLevel3_2: level = "3.2"; break;
+                    case eAVEncH264VLevel4:   level = "4";   break;
+                    case eAVEncH264VLevel4_1: level = "4.1"; break;
+                    case eAVEncH264VLevel4_2: level = "4.2"; break;
+                    case eAVEncH264VLevel5:   level = "5";   break;
+                    case eAVEncH264VLevel5_1: level = "5.1"; break;
+                    case eAVEncH264VLevel5_2: level = "5.2"; break;
+                    default: ERR("Unknown level %u\n", h264_level);
+                }
+                if (level)
+                    gst_caps_set_simple(output, "level", G_TYPE_STRING, level, NULL);
+            }
+        }
+        else if (IsEqualGUID(&subtype, &MFVideoFormat_WVC1))
+        {
+            BYTE *user_data;
+            DWORD user_data_size;
+            output = gst_caps_new_empty_simple("video/x-wmv");
+            gst_caps_set_simple(output, "format", G_TYPE_STRING, "WVC1", NULL);
+
+            gst_caps_set_simple(output, "wmvversion", G_TYPE_INT, 3, NULL);
+
+            if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(type, &MF_MT_USER_DATA, &user_data, &user_data_size)))
+            {
+                GstBuffer *codec_data_buffer = gst_buffer_new_allocate(NULL, user_data_size, NULL);
+                gst_buffer_fill(codec_data_buffer, 0, user_data, user_data_size);
+                gst_caps_set_simple(output, "codec_data", GST_TYPE_BUFFER, codec_data_buffer, NULL);
+                gst_buffer_unref(codec_data_buffer);
+                CoTaskMemFree(user_data);
+            }
+        }
+        else if (IsEqualGUID(&base_masked_subtype, &MFVideoFormat_Base))
+        {
+            output = gst_caps_new_empty_simple("video/x-raw");
+            gst_caps_set_simple(output, "format", G_TYPE_STRING, fourcc_str(subtype.Data1), NULL);
+        }
+        else {
+            ERR("Unrecognized subtype %s\n", debugstr_guid(&subtype));
+            return NULL;
+        }
+
+        IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate);
+        IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size);
+
+        if (frame_rate)
+            gst_caps_set_simple(output, "framerate", GST_TYPE_FRACTION, *framerate_num, *framerate_den, NULL);
+        if (frame_size)
+        {
+            gst_caps_set_simple(output, "width", G_TYPE_INT, *width, NULL);
+            gst_caps_set_simple(output, "height", G_TYPE_INT, *height, NULL);
+        }
+        return output;
+    }
+    else if (IsEqualGUID(&major_type, &MFMediaType_Audio))
+    {
+        DWORD rate, channels;
+
+        if (IsEqualGUID(&subtype, &MFAudioFormat_AAC))
+        {
+            DWORD payload_type, indication;
+            struct aac_user_data *user_data;
+            UINT32 user_data_size;
+            output = gst_caps_new_empty_simple("audio/mpeg");
+
+            /* TODO */
+            gst_caps_set_simple(output, "framed", G_TYPE_BOOLEAN, TRUE, NULL);
+            gst_caps_set_simple(output, "mpegversion", G_TYPE_INT, 4, NULL);
+
+            if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AAC_PAYLOAD_TYPE, &payload_type)))
+            {
+                switch (payload_type)
+                {
+                    case 0:
+                        gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "raw", NULL);
+                        break;
+                    case 1:
+                        gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "adts", NULL);
+                        break;
+                    default:
+                        gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "raw", NULL);
+                }
+            }
+            else
+                gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "raw", NULL);
+
+            if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, &indication)))
+            {
+                switch (indication)
+                {
+                    case 0x29:
+                    {
+                        gst_caps_set_simple(output, "profile", G_TYPE_STRING, "lc", NULL);
+                        gst_caps_set_simple(output, "level", G_TYPE_STRING, "2", NULL);
+                        break;
+                    }
+                    case 0x2A:
+                    {
+                        gst_caps_set_simple(output, "profile", G_TYPE_STRING, "lc", NULL);
+                        gst_caps_set_simple(output, "level", G_TYPE_STRING, "4", NULL);
+                        break;
+                    }
+                    case 0x2B:
+                    {
+                        gst_caps_set_simple(output, "profile", G_TYPE_STRING, "lc", NULL);
+                        gst_caps_set_simple(output, "level", G_TYPE_STRING, "5", NULL);
+                        break;
+                    }
+                    default:
+                        ERR("Unrecognized profile-level-indication %u\n", indication);
+                }
+            }
+
+            if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(type, &MF_MT_USER_DATA, (BYTE **) &user_data, &user_data_size)))
+            {
+                if (user_data_size > sizeof(sizeof(*user_data)))
+                {
+                    GstBuffer *audio_specific_config = gst_buffer_new_allocate(NULL, user_data_size - sizeof(*user_data), NULL);
+                    gst_buffer_fill(audio_specific_config, 0, user_data + 1, user_data_size - sizeof(*user_data));
+
+                    gst_caps_set_simple(output, "codec_data", GST_TYPE_BUFFER, audio_specific_config, NULL);
+                    gst_buffer_unref(audio_specific_config);
+                }
+                CoTaskMemFree(user_data);
+            }
+        }
+        else if (IsEqualGUID(&subtype, &MFAudioFormat_Float))
+        {
+            output = gst_caps_new_empty_simple("audio/x-raw");
+
+            gst_caps_set_simple(output, "format", G_TYPE_STRING, "F32LE", NULL);
+        }
+        else
+        {
+            ERR("Unrecognized subtype %s\n", debugstr_guid(&subtype));
+            if (output)
+                gst_caps_unref(output);
+            return NULL;
+        }
+        if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
+        {
+            gst_caps_set_simple(output, "rate", G_TYPE_INT, rate, NULL);
+        }
+        if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
+        {
+            gst_caps_set_simple(output, "channels", G_TYPE_INT, channels, NULL);
+        }
+
+        return output;
+    }
+
+    ERR("Unrecognized major type %s\n", debugstr_guid(&major_type));
+    return NULL;
+}
diff --git a/include/codecapi.h b/include/codecapi.h
new file mode 100644
index 0000000000..2690b523d7
--- /dev/null
+++ b/include/codecapi.h
@@ -0,0 +1,38 @@
+#ifndef __CODECAPI_H
+#define __CODECAPI_H
+
+enum eAVEncH264VProfile
+{
+   eAVEncH264VProfile_unknown  = 0,
+   eAVEncH264VProfile_Simple = 66,
+   eAVEncH264VProfile_Base = 66,
+   eAVEncH264VProfile_Main = 77,
+   eAVEncH264VProfile_High = 100,
+   eAVEncH264VProfile_422 = 122,
+   eAVEncH264VProfile_High10 = 110,
+   eAVEncH264VProfile_444 = 244,
+   eAVEncH264VProfile_Extended = 88,
+};
+
+enum eAVEncH264VLevel
+{
+    eAVEncH264VLevel1 = 10,
+    eAVEncH264VLevel1_b = 11,
+    eAVEncH264VLevel1_1 = 11,
+    eAVEncH264VLevel1_2 = 12,
+    eAVEncH264VLevel1_3 = 13,
+    eAVEncH264VLevel2 = 20,
+    eAVEncH264VLevel2_1 = 21,
+    eAVEncH264VLevel2_2 = 22,
+    eAVEncH264VLevel3 = 30,
+    eAVEncH264VLevel3_1 = 31,
+    eAVEncH264VLevel3_2 = 32,
+    eAVEncH264VLevel4 = 40,
+    eAVEncH264VLevel4_1 = 41,
+    eAVEncH264VLevel4_2 = 42,
+    eAVEncH264VLevel5 = 50,
+    eAVEncH264VLevel5_1 = 51,
+    eAVEncH264VLevel5_2 = 52
+};
+
+#endif
\ No newline at end of file
-- 
2.25.1




More information about the wine-devel mailing list