Commit 7b261182 authored by Alfred Agrell's avatar Alfred Agrell Committed by Alexandre Julliard

winegstreamer: Add WG_MAJOR_TYPE_VIDEO_MPEG1 media type.

parent 5c24b7e5
......@@ -565,6 +565,7 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format)
case WG_MAJOR_TYPE_VIDEO_H264:
case WG_MAJOR_TYPE_VIDEO_WMV:
case WG_MAJOR_TYPE_VIDEO_INDEO:
case WG_MAJOR_TYPE_VIDEO_MPEG1:
FIXME("Format %u not implemented!\n", format->major_type);
/* fallthrough */
case WG_MAJOR_TYPE_UNKNOWN:
......
......@@ -280,46 +280,50 @@ static bool amt_from_wg_format_audio_mpeg1(AM_MEDIA_TYPE *mt, const struct wg_fo
#define ALIGN(n, alignment) (((n) + (alignment) - 1) & ~((alignment) - 1))
static unsigned int wg_format_get_max_size_video_raw(enum wg_video_format format, unsigned int width, unsigned int height)
{
switch (format)
{
case WG_VIDEO_FORMAT_BGRA:
case WG_VIDEO_FORMAT_BGRx:
case WG_VIDEO_FORMAT_AYUV:
return width * height * 4;
case WG_VIDEO_FORMAT_BGR:
return ALIGN(width * 3, 4) * height;
case WG_VIDEO_FORMAT_RGB15:
case WG_VIDEO_FORMAT_RGB16:
case WG_VIDEO_FORMAT_UYVY:
case WG_VIDEO_FORMAT_YUY2:
case WG_VIDEO_FORMAT_YVYU:
return ALIGN(width * 2, 4) * height;
case WG_VIDEO_FORMAT_I420:
case WG_VIDEO_FORMAT_YV12:
return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
+ 2 * ALIGN((width + 1) / 2, 4) * ((height + 1) / 2); /* U and V planes */
case WG_VIDEO_FORMAT_NV12:
return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
+ ALIGN(width, 4) * ((height + 1) / 2); /* U/V plane */
case WG_VIDEO_FORMAT_UNKNOWN:
FIXME("Cannot guess maximum sample size for unknown video format.\n");
return 0;
}
assert(0);
return 0;
}
unsigned int wg_format_get_max_size(const struct wg_format *format)
{
switch (format->major_type)
{
case WG_MAJOR_TYPE_VIDEO:
{
unsigned int width = format->u.video.width, height = abs(format->u.video.height);
switch (format->u.video.format)
{
case WG_VIDEO_FORMAT_BGRA:
case WG_VIDEO_FORMAT_BGRx:
case WG_VIDEO_FORMAT_AYUV:
return width * height * 4;
case WG_VIDEO_FORMAT_BGR:
return ALIGN(width * 3, 4) * height;
case WG_VIDEO_FORMAT_RGB15:
case WG_VIDEO_FORMAT_RGB16:
case WG_VIDEO_FORMAT_UYVY:
case WG_VIDEO_FORMAT_YUY2:
case WG_VIDEO_FORMAT_YVYU:
return ALIGN(width * 2, 4) * height;
case WG_VIDEO_FORMAT_I420:
case WG_VIDEO_FORMAT_YV12:
return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
+ 2 * ALIGN((width + 1) / 2, 4) * ((height + 1) / 2); /* U and V planes */
case WG_VIDEO_FORMAT_NV12:
return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
+ ALIGN(width, 4) * ((height + 1) / 2); /* U/V plane */
case WG_VIDEO_FORMAT_UNKNOWN:
FIXME("Cannot guess maximum sample size for unknown video format.\n");
return 0;
}
break;
}
return wg_format_get_max_size_video_raw(format->u.video.format,
format->u.video.width, abs(format->u.video.height));
case WG_MAJOR_TYPE_VIDEO_CINEPAK:
/* Both ffmpeg's encoder and a Cinepak file seen in the wild report
......@@ -327,6 +331,13 @@ unsigned int wg_format_get_max_size(const struct wg_format *format)
* but as long as every sample fits into our allocator, we're fine. */
return format->u.video_cinepak.width * format->u.video_cinepak.height * 3;
case WG_MAJOR_TYPE_VIDEO_MPEG1:
/* Estimated max size of a compressed video frame.
* There's no way to no way to know the real upper bound,
* so let's just use the decompressed size and hope it works. */
return wg_format_get_max_size_video_raw(WG_VIDEO_FORMAT_YV12,
format->u.video_mpeg1.width, format->u.video_mpeg1.height);
case WG_MAJOR_TYPE_AUDIO:
{
unsigned int rate = format->u.audio.rate, channels = format->u.audio.channels;
......@@ -595,6 +606,36 @@ static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_form
return true;
}
static bool amt_from_wg_format_video_mpeg1(AM_MEDIA_TYPE *mt, const struct wg_format *format)
{
MPEG1VIDEOINFO *video_format;
uint32_t frame_time;
if (!(video_format = CoTaskMemAlloc(sizeof(*video_format))))
return false;
mt->majortype = MEDIATYPE_Video;
mt->subtype = MEDIASUBTYPE_MPEG1Payload;
mt->bTemporalCompression = TRUE;
mt->lSampleSize = 1;
mt->formattype = FORMAT_MPEGVideo;
mt->cbFormat = sizeof(MPEG1VIDEOINFO);
mt->pbFormat = (BYTE *)video_format;
memset(video_format, 0, sizeof(*video_format));
if ((frame_time = MulDiv(10000000, format->u.video_mpeg1.fps_d, format->u.video_mpeg1.fps_n)) != -1)
video_format->hdr.AvgTimePerFrame = frame_time;
video_format->hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
video_format->hdr.bmiHeader.biWidth = format->u.video_mpeg1.width;
video_format->hdr.bmiHeader.biHeight = format->u.video_mpeg1.height;
video_format->hdr.bmiHeader.biPlanes = 1;
video_format->hdr.bmiHeader.biBitCount = 12;
video_format->hdr.bmiHeader.biCompression = mt->subtype.Data1;
video_format->hdr.bmiHeader.biSizeImage = wg_format_get_max_size(format);
return true;
}
bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm)
{
memset(mt, 0, sizeof(*mt));
......@@ -624,6 +665,9 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
case WG_MAJOR_TYPE_VIDEO_WMV:
return amt_from_wg_format_video_wmv(mt, format);
case WG_MAJOR_TYPE_VIDEO_MPEG1:
return amt_from_wg_format_video_mpeg1(mt, format);
}
assert(0);
......@@ -838,6 +882,30 @@ static bool amt_to_wg_format_video_wmv(const AM_MEDIA_TYPE *mt, struct wg_format
return true;
}
static bool amt_to_wg_format_video_mpeg1(const AM_MEDIA_TYPE *mt, struct wg_format *format)
{
const MPEG1VIDEOINFO *video_format = (const MPEG1VIDEOINFO *)mt->pbFormat;
if (!IsEqualGUID(&mt->formattype, &FORMAT_MPEGVideo))
{
FIXME("Unknown format type %s.\n", debugstr_guid(&mt->formattype));
return false;
}
if (mt->cbFormat < sizeof(VIDEOINFOHEADER) || !mt->pbFormat)
{
ERR("Unexpected format size %lu.\n", mt->cbFormat);
return false;
}
format->major_type = WG_MAJOR_TYPE_VIDEO_MPEG1;
format->u.video_mpeg1.width = video_format->hdr.bmiHeader.biWidth;
format->u.video_mpeg1.height = video_format->hdr.bmiHeader.biHeight;
format->u.video_mpeg1.fps_n = 10000000;
format->u.video_mpeg1.fps_d = video_format->hdr.AvgTimePerFrame;
return true;
}
bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format)
{
memset(format, 0, sizeof(*format));
......@@ -854,6 +922,8 @@ bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format)
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV3)
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_VC1S))
return amt_to_wg_format_video_wmv(mt, format);
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MPEG1Payload))
return amt_to_wg_format_video_mpeg1(mt, format);
return amt_to_wg_format_video(mt, format);
}
if (IsEqualGUID(&mt->majortype, &MEDIATYPE_Audio))
......
......@@ -42,6 +42,7 @@ enum wg_major_type
WG_MAJOR_TYPE_VIDEO_H264,
WG_MAJOR_TYPE_VIDEO_WMV,
WG_MAJOR_TYPE_VIDEO_INDEO,
WG_MAJOR_TYPE_VIDEO_MPEG1,
};
typedef UINT32 wg_audio_format;
......@@ -163,6 +164,11 @@ struct wg_format
uint32_t fps_n, fps_d;
uint32_t version;
} video_indeo;
struct
{
int32_t width, height;
uint32_t fps_n, fps_d;
} video_mpeg1;
} u;
};
......
......@@ -282,6 +282,34 @@ static void wg_format_from_caps_video_wmv(struct wg_format *format, const GstCap
format->u.video_wmv.fps_d = fps_d;
}
static void wg_format_from_caps_video_mpeg1(struct wg_format *format, const GstCaps *caps)
{
const GstStructure *structure = gst_caps_get_structure(caps, 0);
gint width, height, fps_n, fps_d;
if (!gst_structure_get_int(structure, "width", &width))
{
GST_WARNING("Missing \"width\" value in %" GST_PTR_FORMAT ".", caps);
return;
}
if (!gst_structure_get_int(structure, "height", &height))
{
GST_WARNING("Missing \"height\" value in %" GST_PTR_FORMAT ".", caps);
return;
}
if (!gst_structure_get_fraction(structure, "framerate", &fps_n, &fps_d))
{
fps_n = 0;
fps_d = 1;
}
format->major_type = WG_MAJOR_TYPE_VIDEO_MPEG1;
format->u.video_mpeg1.width = width;
format->u.video_mpeg1.height = height;
format->u.video_mpeg1.fps_n = fps_n;
format->u.video_mpeg1.fps_d = fps_d;
}
void wg_format_from_caps(struct wg_format *format, const GstCaps *caps)
{
const GstStructure *structure = gst_caps_get_structure(caps, 0);
......@@ -316,6 +344,10 @@ void wg_format_from_caps(struct wg_format *format, const GstCaps *caps)
{
wg_format_from_caps_video_wmv(format, caps);
}
else if (!strcmp(name, "video/mpeg") && gst_structure_get_boolean(structure, "parsed", &parsed) && parsed)
{
wg_format_from_caps_video_mpeg1(format, caps);
}
else
{
GST_FIXME("Unhandled caps %" GST_PTR_FORMAT ".", caps);
......@@ -702,6 +734,25 @@ static GstCaps *wg_format_to_caps_video_indeo(const struct wg_format *format)
return caps;
}
static GstCaps *wg_format_to_caps_video_mpeg1(const struct wg_format *format)
{
GstCaps *caps;
if (!(caps = gst_caps_new_empty_simple("video/mpeg")))
return NULL;
gst_caps_set_simple(caps, "mpegversion", G_TYPE_INT, 1, NULL);
gst_caps_set_simple(caps, "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
gst_caps_set_simple(caps, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
if (format->u.video_mpeg1.width)
gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_mpeg1.width, NULL);
if (format->u.video_mpeg1.height)
gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_mpeg1.height, NULL);
if (format->u.video_mpeg1.fps_d || format->u.video_cinepak.fps_n)
gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_mpeg1.fps_n, format->u.video_mpeg1.fps_d, NULL);
return caps;
}
GstCaps *wg_format_to_caps(const struct wg_format *format)
{
switch (format->major_type)
......@@ -726,6 +777,8 @@ GstCaps *wg_format_to_caps(const struct wg_format *format)
return wg_format_to_caps_video_wmv(format);
case WG_MAJOR_TYPE_VIDEO_INDEO:
return wg_format_to_caps_video_indeo(format);
case WG_MAJOR_TYPE_VIDEO_MPEG1:
return wg_format_to_caps_video_mpeg1(format);
}
assert(0);
return NULL;
......@@ -744,6 +797,7 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
case WG_MAJOR_TYPE_VIDEO_H264:
case WG_MAJOR_TYPE_VIDEO_WMV:
case WG_MAJOR_TYPE_VIDEO_INDEO:
case WG_MAJOR_TYPE_VIDEO_MPEG1:
GST_FIXME("Format %u not implemented!", a->major_type);
/* fallthrough */
case WG_MAJOR_TYPE_UNKNOWN:
......
......@@ -369,6 +369,7 @@ NTSTATUS wg_transform_create(void *args)
case WG_MAJOR_TYPE_AUDIO:
case WG_MAJOR_TYPE_VIDEO:
break;
case WG_MAJOR_TYPE_VIDEO_MPEG1:
case WG_MAJOR_TYPE_UNKNOWN:
GST_FIXME("Format %u not implemented!", input_format.major_type);
gst_caps_unref(raw_caps);
......@@ -422,6 +423,7 @@ NTSTATUS wg_transform_create(void *args)
case WG_MAJOR_TYPE_VIDEO_H264:
case WG_MAJOR_TYPE_VIDEO_INDEO:
case WG_MAJOR_TYPE_VIDEO_WMV:
case WG_MAJOR_TYPE_VIDEO_MPEG1:
GST_FIXME("Format %u not implemented!", output_format.major_type);
goto out;
}
......
......@@ -1589,6 +1589,8 @@ static const char *get_major_type_string(enum wg_major_type type)
return "wmv";
case WG_MAJOR_TYPE_VIDEO_INDEO:
return "indeo";
case WG_MAJOR_TYPE_VIDEO_MPEG1:
return "mpeg1-video";
case WG_MAJOR_TYPE_UNKNOWN:
return "unknown";
}
......@@ -1948,6 +1950,7 @@ static HRESULT WINAPI reader_GetOutputFormat(IWMSyncReader2 *iface,
case WG_MAJOR_TYPE_VIDEO_H264:
case WG_MAJOR_TYPE_VIDEO_WMV:
case WG_MAJOR_TYPE_VIDEO_INDEO:
case WG_MAJOR_TYPE_VIDEO_MPEG1:
FIXME("Format %u not implemented!\n", format.major_type);
break;
case WG_MAJOR_TYPE_UNKNOWN:
......@@ -1990,6 +1993,7 @@ static HRESULT WINAPI reader_GetOutputFormatCount(IWMSyncReader2 *iface, DWORD o
case WG_MAJOR_TYPE_VIDEO_H264:
case WG_MAJOR_TYPE_VIDEO_WMV:
case WG_MAJOR_TYPE_VIDEO_INDEO:
case WG_MAJOR_TYPE_VIDEO_MPEG1:
FIXME("Format %u not implemented!\n", format.major_type);
/* fallthrough */
case WG_MAJOR_TYPE_AUDIO:
......
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