Commit 606505e5 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

winegstreamer: Try creating a wg_transform in the H264 decoder.

parent 962b4325
......@@ -48,6 +48,8 @@ struct h264_decoder
LONG refcount;
IMFMediaType *input_type;
IMFMediaType *output_type;
struct wg_transform *wg_transform;
};
static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
......@@ -55,6 +57,29 @@ static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
return CONTAINING_RECORD(iface, struct h264_decoder, IMFTransform_iface);
}
static HRESULT try_create_wg_transform(struct h264_decoder *decoder)
{
struct wg_format input_format;
struct wg_format output_format;
if (decoder->wg_transform)
wg_transform_destroy(decoder->wg_transform);
decoder->wg_transform = NULL;
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;
if (!(decoder->wg_transform = wg_transform_create(&input_format, &output_format)))
return E_FAIL;
return S_OK;
}
static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *default_type)
{
UINT32 value, width, height;
......@@ -183,6 +208,8 @@ static ULONG WINAPI transform_Release(IMFTransform *iface)
if (!refcount)
{
if (decoder->wg_transform)
wg_transform_destroy(decoder->wg_transform);
if (decoder->input_type)
IMFMediaType_Release(decoder->input_type);
if (decoder->output_type)
......@@ -416,7 +443,13 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
IMFMediaType_Release(decoder->output_type);
IMFMediaType_AddRef((decoder->output_type = type));
return S_OK;
if (FAILED(hr = try_create_wg_transform(decoder)))
{
IMFMediaType_Release(decoder->output_type);
decoder->output_type = NULL;
}
return hr;
}
static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
......
......@@ -659,11 +659,11 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format)
{
switch (format->major_type)
{
case WG_MAJOR_TYPE_UNKNOWN:
return NULL;
case WG_MAJOR_TYPE_H264:
case WG_MAJOR_TYPE_WMA:
FIXME("WMA format not implemented!\n");
FIXME("Format %u not implemented!\n", format->major_type);
/* fallthrough */
case WG_MAJOR_TYPE_UNKNOWN:
return NULL;
case WG_MAJOR_TYPE_AUDIO:
......@@ -822,6 +822,38 @@ static void mf_media_type_to_wg_format_wma(IMFMediaType *type, const GUID *subty
memcpy(format->u.wma.codec_data, codec_data, codec_data_len);
}
static void mf_media_type_to_wg_format_h264(IMFMediaType *type, struct wg_format *format)
{
UINT64 frame_rate, frame_size;
UINT32 profile, level;
memset(format, 0, sizeof(*format));
format->major_type = WG_MAJOR_TYPE_H264;
if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
{
format->u.h264.width = frame_size >> 32;
format->u.h264.height = (UINT32)frame_size;
}
if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate)
{
format->u.h264.fps_n = frame_rate >> 32;
format->u.h264.fps_d = (UINT32)frame_rate;
}
else
{
format->u.h264.fps_n = 1;
format->u.h264.fps_d = 1;
}
if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_PROFILE, &profile)))
format->u.h264.profile = profile;
if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &level)))
format->u.h264.level = level;
}
void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
{
GUID major_type, subtype;
......@@ -850,7 +882,12 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
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, &subtype, format);
{
if (IsEqualGUID(&subtype, &MFVideoFormat_H264))
mf_media_type_to_wg_format_h264(type, format);
else
mf_media_type_to_wg_format_video(type, &subtype, format);
}
else
FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type));
}
......
......@@ -328,8 +328,9 @@ unsigned int wg_format_get_max_size(const struct wg_format *format)
break;
}
case WG_MAJOR_TYPE_H264:
case WG_MAJOR_TYPE_WMA:
FIXME("WMA format not implemented!\n");
FIXME("Format %u not implemented!\n", format->major_type);
return 0;
case WG_MAJOR_TYPE_UNKNOWN:
......@@ -423,11 +424,11 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
switch (format->major_type)
{
case WG_MAJOR_TYPE_UNKNOWN:
return false;
case WG_MAJOR_TYPE_H264:
case WG_MAJOR_TYPE_WMA:
FIXME("WMA format not implemented!\n");
FIXME("Format %u not implemented!\n", format->major_type);
/* fallthrough */
case WG_MAJOR_TYPE_UNKNOWN:
return false;
case WG_MAJOR_TYPE_AUDIO:
......
......@@ -38,6 +38,7 @@ struct wg_format
WG_MAJOR_TYPE_VIDEO,
WG_MAJOR_TYPE_AUDIO,
WG_MAJOR_TYPE_WMA,
WG_MAJOR_TYPE_H264,
} major_type;
union
......@@ -100,6 +101,13 @@ struct wg_format
uint32_t codec_data_len;
unsigned char codec_data[64];
} wma;
struct
{
int32_t width, height;
uint32_t fps_n, fps_d;
uint32_t profile;
uint32_t level;
} h264;
} u;
};
......
......@@ -35,6 +35,7 @@
#include <gst/audio/audio.h>
#include "winternl.h"
#include "codecapi.h"
#include "dshow.h"
#include "unix_private.h"
......@@ -431,6 +432,64 @@ static GstCaps *wg_format_to_caps_wma(const struct wg_format *format)
return caps;
}
static GstCaps *wg_format_to_caps_h264(const struct wg_format *format)
{
const char *profile, *level;
GstCaps *caps;
caps = gst_caps_new_empty_simple("video/x-h264");
gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "byte-stream", NULL);
gst_caps_set_simple(caps, "alignment", G_TYPE_STRING, "au", NULL);
if (format->u.h264.width)
gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.h264.width, NULL);
if (format->u.h264.height)
gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.h264.height, NULL);
if (format->u.h264.fps_n || format->u.h264.fps_d)
gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.h264.fps_n, format->u.h264.fps_d, NULL);
switch (format->u.h264.profile)
{
case eAVEncH264VProfile_Main: profile = "main"; break;
case eAVEncH264VProfile_High: profile = "high"; break;
case eAVEncH264VProfile_444: profile = "high-4:4:4"; break;
default:
GST_FIXME("H264 profile attribute %u not implemented.", format->u.h264.profile);
profile = NULL;
break;
}
if (profile)
gst_caps_set_simple(caps, "profile", G_TYPE_STRING, profile, NULL);
switch (format->u.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:
GST_FIXME("H264 level attribute %u not implemented.", format->u.h264.level);
level = NULL;
break;
}
if (level)
gst_caps_set_simple(caps, "level", G_TYPE_STRING, level, NULL);
return caps;
}
GstCaps *wg_format_to_caps(const struct wg_format *format)
{
switch (format->major_type)
......@@ -439,6 +498,8 @@ GstCaps *wg_format_to_caps(const struct wg_format *format)
return NULL;
case WG_MAJOR_TYPE_WMA:
return wg_format_to_caps_wma(format);
case WG_MAJOR_TYPE_H264:
return wg_format_to_caps_h264(format);
case WG_MAJOR_TYPE_AUDIO:
return wg_format_to_caps_audio(format);
case WG_MAJOR_TYPE_VIDEO:
......@@ -455,11 +516,11 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
switch (a->major_type)
{
case WG_MAJOR_TYPE_UNKNOWN:
return false;
case WG_MAJOR_TYPE_WMA:
GST_FIXME("WMA format not implemented!\n");
case WG_MAJOR_TYPE_H264:
GST_FIXME("Format %u not implemented!", a->major_type);
/* fallthrough */
case WG_MAJOR_TYPE_UNKNOWN:
return false;
case WG_MAJOR_TYPE_AUDIO:
......
......@@ -211,6 +211,7 @@ NTSTATUS wg_transform_create(void *args)
switch (input_format.major_type)
{
case WG_MAJOR_TYPE_H264:
case WG_MAJOR_TYPE_WMA:
if (!(element = transform_find_element(GST_ELEMENT_FACTORY_TYPE_DECODER, src_caps, raw_caps))
|| !transform_append_element(transform, element, &first, &last))
......@@ -251,6 +252,9 @@ NTSTATUS wg_transform_create(void *args)
break;
case WG_MAJOR_TYPE_VIDEO:
break;
case WG_MAJOR_TYPE_H264:
case WG_MAJOR_TYPE_WMA:
case WG_MAJOR_TYPE_UNKNOWN:
GST_FIXME("Format %u not implemented!", output_format.major_type);
......
......@@ -1687,7 +1687,8 @@ HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output
break;
case WG_MAJOR_TYPE_WMA:
FIXME("WMA format not implemented!\n");
case WG_MAJOR_TYPE_H264:
FIXME("Format %u not implemented!\n", format.major_type);
/* fallthrough */
case WG_MAJOR_TYPE_AUDIO:
case WG_MAJOR_TYPE_UNKNOWN:
......@@ -1736,7 +1737,8 @@ HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output,
break;
case WG_MAJOR_TYPE_WMA:
FIXME("WMA format not implemented!\n");
case WG_MAJOR_TYPE_H264:
FIXME("Format %u not implemented!\n", format.major_type);
break;
case WG_MAJOR_TYPE_UNKNOWN:
break;
......@@ -1815,6 +1817,8 @@ static const char *get_major_type_string(enum wg_major_type type)
return "unknown";
case WG_MAJOR_TYPE_WMA:
return "wma";
case WG_MAJOR_TYPE_H264:
return "h264";
}
assert(0);
return NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment