Commit 4199bb7f authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

winegstreamer: Support MPEG4 (AAC) compressed audio format.

parent b3b2a559
......@@ -550,6 +550,7 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format)
switch (format->major_type)
{
case WG_MAJOR_TYPE_AUDIO_MPEG1:
case WG_MAJOR_TYPE_AUDIO_MPEG4:
case WG_MAJOR_TYPE_AUDIO_WMA:
case WG_MAJOR_TYPE_VIDEO_CINEPAK:
case WG_MAJOR_TYPE_VIDEO_H264:
......@@ -618,6 +619,51 @@ static void mf_media_type_to_wg_format_audio(IMFMediaType *type, const GUID *sub
FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(subtype), depth);
}
static void mf_media_type_to_wg_format_audio_mpeg4(IMFMediaType *type, struct wg_format *format)
{
/* Audio specific config is stored at after HEAACWAVEINFO in MF_MT_USER_DATA
* https://docs.microsoft.com/en-us/windows/win32/api/mmreg/ns-mmreg-heaacwaveformat
*/
typedef struct
{
WORD wPayloadType;
WORD wAudioProfileLevelIndication;
WORD wStructType;
WORD wReserved1;
DWORD dwReserved2;
} HEAACWAVEINFO;
typedef struct
{
HEAACWAVEINFO wfInfo;
BYTE pbAudioSpecificConfig[1];
} HEAACWAVEFORMAT;
BYTE buffer[64];
HEAACWAVEFORMAT *user_data = (HEAACWAVEFORMAT *)buffer;
UINT32 codec_data_size;
if (FAILED(IMFMediaType_GetBlob(type, &MF_MT_USER_DATA, buffer, sizeof(buffer), &codec_data_size)))
{
FIXME("Codec data is not set.\n");
return;
}
codec_data_size -= min(codec_data_size, offsetof(HEAACWAVEFORMAT, pbAudioSpecificConfig));
if (codec_data_size > sizeof(format->u.audio_mpeg4.codec_data))
{
FIXME("Codec data needs %u bytes.\n", codec_data_size);
return;
}
format->major_type = WG_MAJOR_TYPE_AUDIO_MPEG4;
if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AAC_PAYLOAD_TYPE, &format->u.audio_mpeg4.payload_type)))
format->u.audio_mpeg4.payload_type = -1;
format->u.audio_mpeg4.codec_data_len = codec_data_size;
memcpy(format->u.audio_mpeg4.codec_data, user_data->pbAudioSpecificConfig, codec_data_size);
}
static void mf_media_type_to_wg_format_video(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
{
UINT64 frame_rate, frame_size;
......@@ -781,6 +827,8 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9) ||
IsEqualGUID(&subtype, &MFAudioFormat_WMAudio_Lossless))
mf_media_type_to_wg_format_audio_wma(type, &subtype, format);
else if (IsEqualGUID(&subtype, &MFAudioFormat_AAC))
mf_media_type_to_wg_format_audio_mpeg4(type, format);
else
mf_media_type_to_wg_format_audio(type, &subtype, format);
}
......
......@@ -359,6 +359,7 @@ unsigned int wg_format_get_max_size(const struct wg_format *format)
}
break;
case WG_MAJOR_TYPE_AUDIO_MPEG4:
case WG_MAJOR_TYPE_AUDIO_WMA:
case WG_MAJOR_TYPE_VIDEO_H264:
FIXME("Format %u not implemented!\n", format->major_type);
......@@ -528,6 +529,7 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
switch (format->major_type)
{
case WG_MAJOR_TYPE_AUDIO_MPEG4:
case WG_MAJOR_TYPE_AUDIO_WMA:
case WG_MAJOR_TYPE_VIDEO_H264:
FIXME("Format %u not implemented!\n", format->major_type);
......
......@@ -37,6 +37,7 @@ struct wg_format
WG_MAJOR_TYPE_UNKNOWN = 0,
WG_MAJOR_TYPE_AUDIO,
WG_MAJOR_TYPE_AUDIO_MPEG1,
WG_MAJOR_TYPE_AUDIO_MPEG4,
WG_MAJOR_TYPE_AUDIO_WMA,
WG_MAJOR_TYPE_VIDEO,
WG_MAJOR_TYPE_VIDEO_CINEPAK,
......@@ -71,6 +72,12 @@ struct wg_format
} audio_mpeg1;
struct
{
uint32_t payload_type;
uint32_t codec_data_len;
unsigned char codec_data[64];
} audio_mpeg4;
struct
{
uint32_t version;
uint32_t bitrate;
uint32_t rate;
......
......@@ -346,6 +346,37 @@ static GstCaps *wg_format_to_caps_audio_mpeg1(const struct wg_format *format)
return caps;
}
static GstCaps *wg_format_to_caps_audio_mpeg4(const struct wg_format *format)
{
GstBuffer *buffer;
GstCaps *caps;
if (!(caps = gst_caps_new_empty_simple("audio/mpeg")))
return NULL;
gst_caps_set_simple(caps, "mpegversion", G_TYPE_INT, 4, NULL);
switch (format->u.audio_mpeg4.payload_type)
{
case 0: gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "raw", NULL); break;
case 1: gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "adts", NULL); break;
case 2: gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "adif", NULL); break;
case 3: gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "loas", NULL); break;
}
/* FIXME: Use gst_codec_utils_aac_caps_set_level_and_profile from GStreamer pbutils library */
if (format->u.audio_mpeg4.codec_data_len)
{
buffer = gst_buffer_new_and_alloc(format->u.audio_mpeg4.codec_data_len);
gst_buffer_fill(buffer, 0, format->u.audio_mpeg4.codec_data, format->u.audio_mpeg4.codec_data_len);
gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL);
gst_buffer_unref(buffer);
}
return caps;
}
static GstCaps *wg_format_to_caps_audio(const struct wg_format *format)
{
GstAudioChannelPosition positions[32];
......@@ -533,6 +564,8 @@ GstCaps *wg_format_to_caps(const struct wg_format *format)
return wg_format_to_caps_audio(format);
case WG_MAJOR_TYPE_AUDIO_MPEG1:
return wg_format_to_caps_audio_mpeg1(format);
case WG_MAJOR_TYPE_AUDIO_MPEG4:
return wg_format_to_caps_audio_mpeg4(format);
case WG_MAJOR_TYPE_AUDIO_WMA:
return wg_format_to_caps_audio_wma(format);
case WG_MAJOR_TYPE_VIDEO:
......@@ -554,6 +587,7 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
switch (a->major_type)
{
case WG_MAJOR_TYPE_AUDIO_MPEG1:
case WG_MAJOR_TYPE_AUDIO_MPEG4:
case WG_MAJOR_TYPE_AUDIO_WMA:
case WG_MAJOR_TYPE_VIDEO_H264:
GST_FIXME("Format %u not implemented!", a->major_type);
......
......@@ -424,6 +424,7 @@ NTSTATUS wg_transform_create(void *args)
goto out;
/* fallthrough */
case WG_MAJOR_TYPE_AUDIO_MPEG1:
case WG_MAJOR_TYPE_AUDIO_MPEG4:
case WG_MAJOR_TYPE_AUDIO_WMA:
case WG_MAJOR_TYPE_VIDEO_CINEPAK:
if (!(element = transform_find_element(GST_ELEMENT_FACTORY_TYPE_DECODER, src_caps, raw_caps))
......@@ -474,6 +475,7 @@ NTSTATUS wg_transform_create(void *args)
break;
case WG_MAJOR_TYPE_AUDIO_MPEG1:
case WG_MAJOR_TYPE_AUDIO_MPEG4:
case WG_MAJOR_TYPE_AUDIO_WMA:
case WG_MAJOR_TYPE_VIDEO_CINEPAK:
case WG_MAJOR_TYPE_VIDEO_H264:
......
......@@ -1555,6 +1555,8 @@ static const char *get_major_type_string(enum wg_major_type type)
return "audio";
case WG_MAJOR_TYPE_AUDIO_MPEG1:
return "mpeg1-audio";
case WG_MAJOR_TYPE_AUDIO_MPEG4:
return "mpeg4-audio";
case WG_MAJOR_TYPE_AUDIO_WMA:
return "wma";
case WG_MAJOR_TYPE_VIDEO:
......@@ -1971,6 +1973,7 @@ static HRESULT WINAPI reader_GetOutputFormat(IWMSyncReader2 *iface,
break;
case WG_MAJOR_TYPE_AUDIO_MPEG1:
case WG_MAJOR_TYPE_AUDIO_MPEG4:
case WG_MAJOR_TYPE_AUDIO_WMA:
case WG_MAJOR_TYPE_VIDEO_CINEPAK:
case WG_MAJOR_TYPE_VIDEO_H264:
......@@ -2010,6 +2013,7 @@ static HRESULT WINAPI reader_GetOutputFormatCount(IWMSyncReader2 *iface, DWORD o
break;
case WG_MAJOR_TYPE_AUDIO_MPEG1:
case WG_MAJOR_TYPE_AUDIO_MPEG4:
case WG_MAJOR_TYPE_AUDIO_WMA:
case WG_MAJOR_TYPE_VIDEO_CINEPAK:
case WG_MAJOR_TYPE_VIDEO_H264:
......
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