[PATCH v3 3/5] winegstreamer: Introduce new WG_MAJOR_TYPE_WMA major type.

Rémi Bernon rbernon at codeweavers.com
Wed Feb 16 05:19:07 CST 2022


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/winegstreamer/mfplat.c        | 109 +++++++++++++++++++++++------
 dlls/winegstreamer/quartz_parser.c |   8 +++
 dlls/winegstreamer/unixlib.h       |  12 ++++
 dlls/winegstreamer/wg_format.c     |   7 ++
 dlls/winegstreamer/wm_reader.c     |   8 +++
 dlls/winegstreamer/wma_decoder.c   |  18 +++++
 6 files changed, 141 insertions(+), 21 deletions(-)

diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index a111bbe196d..9b3fc429d32 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -635,6 +635,10 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format)
         case WG_MAJOR_TYPE_UNKNOWN:
             return NULL;
 
+        case WG_MAJOR_TYPE_WMA:
+            FIXME("WMA format not implemented!\n");
+            return NULL;
+
         case WG_MAJOR_TYPE_AUDIO:
             return mf_media_type_from_wg_format_audio(format);
 
@@ -646,17 +650,11 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format)
     return NULL;
 }
 
-static void mf_media_type_to_wg_format_audio(IMFMediaType *type, struct wg_format *format)
+static void mf_media_type_to_wg_format_audio(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
 {
     UINT32 rate, channels, channel_mask, depth;
     unsigned int i;
-    GUID subtype;
 
-    if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
-    {
-        FIXME("Subtype is not set.\n");
-        return;
-    }
     if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
     {
         FIXME("Sample rate is not set.\n");
@@ -692,26 +690,20 @@ static void mf_media_type_to_wg_format_audio(IMFMediaType *type, struct wg_forma
 
     for (i = 0; i < ARRAY_SIZE(audio_formats); ++i)
     {
-        if (IsEqualGUID(&subtype, audio_formats[i].subtype) && depth == audio_formats[i].depth)
+        if (IsEqualGUID(subtype, audio_formats[i].subtype) && depth == audio_formats[i].depth)
         {
             format->u.audio.format = audio_formats[i].format;
             return;
         }
     }
-    FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(&subtype), depth);
+    FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(subtype), depth);
 }
 
-static void mf_media_type_to_wg_format_video(IMFMediaType *type, struct wg_format *format)
+static void mf_media_type_to_wg_format_video(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
 {
     UINT64 frame_rate, frame_size;
     unsigned int i;
-    GUID subtype;
 
-    if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
-    {
-        FIXME("Subtype is not set.\n");
-        return;
-    }
     if (FAILED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
     {
         FIXME("Frame size is not set.\n");
@@ -732,18 +724,80 @@ static void mf_media_type_to_wg_format_video(IMFMediaType *type, struct wg_forma
 
     for (i = 0; i < ARRAY_SIZE(video_formats); ++i)
     {
-        if (IsEqualGUID(&subtype, video_formats[i].subtype))
+        if (IsEqualGUID(subtype, video_formats[i].subtype))
         {
             format->u.video.format = video_formats[i].format;
             return;
         }
     }
-    FIXME("Unrecognized video subtype %s.\n", debugstr_guid(&subtype));
+    FIXME("Unrecognized video subtype %s.\n", debugstr_guid(subtype));
+}
+
+static void mf_media_type_to_wg_format_wma(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
+{
+    UINT32 rate, depth, channels, block_align, bytes_per_second, codec_data_len;
+    BYTE codec_data[64];
+    UINT32 version;
+
+    if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
+    {
+        FIXME("Sample rate is not set.\n");
+        return;
+    }
+    if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
+    {
+        FIXME("Channel count is not set.\n");
+        return;
+    }
+    if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align)))
+    {
+        FIXME("Block alignment is not set.\n");
+        return;
+    }
+    if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &depth)))
+    {
+        FIXME("Depth is not set.\n");
+        return;
+    }
+    if (FAILED(IMFMediaType_GetBlob(type, &MF_MT_USER_DATA, codec_data, sizeof(codec_data), &codec_data_len)))
+    {
+        FIXME("Codec data is not set.\n");
+        return;
+    }
+    if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &bytes_per_second)))
+    {
+        FIXME("Bitrate is not set.\n");
+        bytes_per_second = 0;
+    }
+
+    if (IsEqualGUID(subtype, &MEDIASUBTYPE_MSAUDIO1))
+        version = 1;
+    else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV8))
+        version = 2;
+    else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV9))
+        version = 3;
+    else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudio_Lossless))
+        version = 4;
+    else
+    {
+        assert(0);
+        return;
+    }
+
+    format->major_type = WG_MAJOR_TYPE_WMA;
+    format->u.wma.version = version;
+    format->u.wma.bitrate = bytes_per_second * 8;
+    format->u.wma.rate = rate;
+    format->u.wma.depth = depth;
+    format->u.wma.channels = channels;
+    format->u.wma.block_align = block_align;
+    format->u.wma.codec_data_len = codec_data_len;
+    memcpy(format->u.wma.codec_data, codec_data, codec_data_len);
 }
 
 void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
 {
-    GUID major_type;
+    GUID major_type, subtype;
 
     memset(format, 0, sizeof(*format));
 
@@ -752,11 +806,24 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
         FIXME("Major type is not set.\n");
         return;
     }
+    if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+    {
+        FIXME("Subtype is not set.\n");
+        return;
+    }
 
     if (IsEqualGUID(&major_type, &MFMediaType_Audio))
-        mf_media_type_to_wg_format_audio(type, format);
+    {
+        if (IsEqualGUID(&subtype, &MEDIASUBTYPE_MSAUDIO1) ||
+                IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV8) ||
+                IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9) ||
+                IsEqualGUID(&subtype, &MFAudioFormat_WMAudio_Lossless))
+            mf_media_type_to_wg_format_wma(type, &subtype, format);
+        else
+            mf_media_type_to_wg_format_audio(type, &subtype, format);
+    }
     else if (IsEqualGUID(&major_type, &MFMediaType_Video))
-        mf_media_type_to_wg_format_video(type, format);
+        mf_media_type_to_wg_format_video(type, &subtype, format);
     else
         FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type));
 }
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index 45313ebda27..e06c55ccfe0 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -319,6 +319,10 @@ unsigned int wg_format_get_max_size(const struct wg_format *format)
             break;
         }
 
+        case WG_MAJOR_TYPE_WMA:
+            FIXME("WMA format not implemented!\n");
+            return 0;
+
         case WG_MAJOR_TYPE_UNKNOWN:
             FIXME("Cannot guess maximum sample size for unknown format.\n");
             return 0;
@@ -413,6 +417,10 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
     case WG_MAJOR_TYPE_UNKNOWN:
         return false;
 
+    case WG_MAJOR_TYPE_WMA:
+        FIXME("WMA format not implemented!\n");
+        return false;
+
     case WG_MAJOR_TYPE_AUDIO:
         return amt_from_wg_format_audio(mt, format);
 
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 82bb534b938..45ec606fc6a 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -37,6 +37,7 @@ struct wg_format
         WG_MAJOR_TYPE_UNKNOWN,
         WG_MAJOR_TYPE_VIDEO,
         WG_MAJOR_TYPE_AUDIO,
+        WG_MAJOR_TYPE_WMA,
     } major_type;
 
     union
@@ -88,6 +89,17 @@ struct wg_format
             uint32_t channel_mask; /* In WinMM format. */
             uint32_t rate;
         } audio;
+        struct
+        {
+            uint32_t version;
+            uint32_t bitrate;
+            uint32_t rate;
+            uint32_t depth;
+            uint32_t channels;
+            uint32_t block_align;
+            uint32_t codec_data_len;
+            unsigned char codec_data[64];
+        } wma;
     } u;
 };
 
diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c
index 8952acc1c2e..8f771bb8abd 100644
--- a/dlls/winegstreamer/wg_format.c
+++ b/dlls/winegstreamer/wg_format.c
@@ -400,6 +400,9 @@ GstCaps *wg_format_to_caps(const struct wg_format *format)
     {
         case WG_MAJOR_TYPE_UNKNOWN:
             return NULL;
+        case WG_MAJOR_TYPE_WMA:
+            GST_FIXME("WMA format not implemented!\n");
+            return NULL;
         case WG_MAJOR_TYPE_AUDIO:
             return wg_format_to_caps_audio(format);
         case WG_MAJOR_TYPE_VIDEO:
@@ -419,6 +422,10 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
         case WG_MAJOR_TYPE_UNKNOWN:
             return false;
 
+        case WG_MAJOR_TYPE_WMA:
+            GST_FIXME("WMA format not implemented!\n");
+            return false;
+
         case WG_MAJOR_TYPE_AUDIO:
             return a->u.audio.format == b->u.audio.format
                     && a->u.audio.channels == b->u.audio.channels
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index d40afb66afd..01518c6b9a8 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -1687,6 +1687,9 @@ HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output
             *count = ARRAY_SIZE(video_formats);
             break;
 
+        case WG_MAJOR_TYPE_WMA:
+            FIXME("WMA format not implemented!\n");
+            /* fallthrough */
         case WG_MAJOR_TYPE_AUDIO:
         case WG_MAJOR_TYPE_UNKNOWN:
             *count = 1;
@@ -1733,6 +1736,9 @@ HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output,
             format.u.audio.format = WG_AUDIO_FORMAT_S16LE;
             break;
 
+        case WG_MAJOR_TYPE_WMA:
+            FIXME("WMA format not implemented!\n");
+            break;
         case WG_MAJOR_TYPE_UNKNOWN:
             break;
     }
@@ -1808,6 +1814,8 @@ static const char *get_major_type_string(enum wg_major_type type)
             return "video";
         case WG_MAJOR_TYPE_UNKNOWN:
             return "unknown";
+        case WG_MAJOR_TYPE_WMA:
+            return "wma";
     }
     assert(0);
     return NULL;
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 78316059052..31f735a5b1d 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -60,6 +60,21 @@ static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
     return CONTAINING_RECORD(iface, struct wma_decoder, IUnknown_inner);
 }
 
+static HRESULT try_create_wg_transform(struct wma_decoder *decoder)
+{
+    struct wg_format input_format, output_format;
+
+    mf_media_type_to_wg_format(decoder->input_type, &input_format);
+    if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
+        return MF_E_INVALIDMEDIATYPE;
+
+    mf_media_type_to_wg_format(decoder->output_type, &output_format);
+    if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
+        return MF_E_INVALIDMEDIATYPE;
+
+    return S_OK;
+}
+
 static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out)
 {
     struct wma_decoder *decoder = impl_from_IUnknown(iface);
@@ -438,6 +453,9 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
     if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)decoder->output_type)))
         goto failed;
 
+    if (FAILED(hr = try_create_wg_transform(decoder)))
+        goto failed;
+
     return S_OK;
 
 failed:
-- 
2.34.1




More information about the wine-devel mailing list