From: Rémi Bernon rbernon@codeweavers.com
--- configure.ac | 8 ++-- dlls/winedmo/Makefile.in | 1 + dlls/winedmo/main.c | 32 ++++++++++++++ dlls/winedmo/unix_demuxer.c | 12 +++++ dlls/winedmo/unix_media_type.c | 80 ++++++++++++++++++++++++++++++++++ dlls/winedmo/unix_private.h | 9 ++++ dlls/winedmo/unixlib.c | 2 + dlls/winedmo/unixlib.h | 22 ++++++++++ dlls/winedmo/winedmo.spec | 1 + include/wine/winedmo.h | 10 +++++ 10 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 dlls/winedmo/unix_media_type.c
diff --git a/configure.ac b/configure.ac index bd7c0e14718..eed177ba861 100644 --- a/configure.ac +++ b/configure.ac @@ -1622,14 +1622,16 @@ WINE_NOTICE_WITH(pulse, [test -z "$PULSE_LIBS"], dnl **** Check for FFmpeg **** if test "x$with_ffmpeg" != "xno"; then - WINE_PACKAGE_FLAGS(FFMPEG,[libavutil libavformat],,,, - [AC_CHECK_HEADERS([libavutil/avutil.h libavformat/avformat.h]) - if test "$ac_cv_header_libavutil_avutil_h" = "yes" -a "$ac_cv_header_libavformat_avformat_h" = "yes" + WINE_PACKAGE_FLAGS(FFMPEG,[libavutil libavformat libavcodec],,,, + [AC_CHECK_HEADERS([libavutil/avutil.h libavformat/avformat.h libavcodec/avcodec.h]) + if test "$ac_cv_header_libavutil_avutil_h" = "yes" -a "$ac_cv_header_libavformat_avformat_h" = "yes" -a "$ac_cv_header_libavcodec_avcodec_h" = "yes" then AC_CHECK_LIB(avutil,av_log_set_callback, [AC_CHECK_LIB(avformat,av_find_input_format, + [AC_CHECK_LIB(avcodec,avcodec_get_name, [AC_DEFINE(HAVE_FFMPEG, 1, [Define to 1 if you have the FFmpeg libraries.])], [FFMPEG_LIBS=""],[$FFMPEG_LIBS])], + [FFMPEG_LIBS=""],[$FFMPEG_LIBS])], [FFMPEG_LIBS=""],[$FFMPEG_LIBS]) else FFMPEG_LIBS="" diff --git a/dlls/winedmo/Makefile.in b/dlls/winedmo/Makefile.in index 5b816357770..2d829deb07b 100644 --- a/dlls/winedmo/Makefile.in +++ b/dlls/winedmo/Makefile.in @@ -7,4 +7,5 @@ UNIX_LIBS = $(FFMPEG_LIBS) $(PTHREAD_LIBS) SOURCES = \ main.c \ unix_demuxer.c \ + unix_media_type.c \ unixlib.c diff --git a/dlls/winedmo/main.c b/dlls/winedmo/main.c index ad7bc6753cd..7d30c31d05d 100644 --- a/dlls/winedmo/main.c +++ b/dlls/winedmo/main.c @@ -179,3 +179,35 @@ NTSTATUS CDECL winedmo_demuxer_destroy( struct winedmo_demuxer *demuxer )
return status; } + +static HRESULT get_media_type( UINT code, void *params, struct media_type *media_type, + GUID *major, union winedmo_format **format ) +{ + NTSTATUS status; + + media_type->format = NULL; + if ((status = WINE_UNIX_CALL( code, params )) && status == STATUS_BUFFER_TOO_SMALL) + { + if (!(media_type->format = malloc( media_type->format_size ))) return STATUS_NO_MEMORY; + status = WINE_UNIX_CALL( code, params ); + } + + if (!status) + { + *major = media_type->major; + *format = media_type->format; + return STATUS_SUCCESS; + } + + WARN( "Failed to get media type, code %#x, status %#lx\n", code, status ); + free( media_type->format ); + return status; +} + +NTSTATUS CDECL winedmo_demuxer_stream_type( struct winedmo_demuxer demuxer, UINT stream, + GUID *major, union winedmo_format **format ) +{ + struct demuxer_stream_type_params params = {.demuxer = demuxer, .stream = stream}; + TRACE( "demuxer %#I64x, stream %u, major %p, format %p\n", demuxer.handle, stream, major, format ); + return get_media_type( unix_demuxer_stream_type, ¶ms, ¶ms.media_type, major, format ); +} diff --git a/dlls/winedmo/unix_demuxer.c b/dlls/winedmo/unix_demuxer.c index 2a3499068dc..632b75480d7 100644 --- a/dlls/winedmo/unix_demuxer.c +++ b/dlls/winedmo/unix_demuxer.c @@ -159,4 +159,16 @@ NTSTATUS demuxer_destroy( void *arg ) return STATUS_SUCCESS; }
+NTSTATUS demuxer_stream_type( void *arg ) +{ + struct demuxer_stream_type_params *params = arg; + AVFormatContext *ctx = get_demuxer( params->demuxer ); + AVStream *stream = ctx->streams[params->stream]; + + TRACE( "context %p, stream %u, stream %p, index %u\n", ctx, params->stream, stream, stream->index ); + + return media_type_from_codec_params( stream->codecpar, &stream->sample_aspect_ratio, + &stream->avg_frame_rate, 0, ¶ms->media_type ); +} + #endif /* HAVE_FFMPEG */ diff --git a/dlls/winedmo/unix_media_type.c b/dlls/winedmo/unix_media_type.c new file mode 100644 index 00000000000..fb0350d39b4 --- /dev/null +++ b/dlls/winedmo/unix_media_type.c @@ -0,0 +1,80 @@ +/* + * Copyright 2024 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" + +#include "initguid.h" +#include "unix_private.h" + +#include "d3d9.h" +#include "mfapi.h" +#include "uuids.h" + +#include "wine/debug.h" + +#ifdef HAVE_FFMPEG + +WINE_DEFAULT_DEBUG_CHANNEL(dmo); + +#define TRACE_HEXDUMP( data, size ) \ + if (__WINE_IS_DEBUG_ON(_TRACE, __wine_dbch___default)) \ + do { \ + const unsigned char *__ptr, *__end, *__tmp; \ + for (__ptr = (void *)(data), __end = __ptr + (size); __ptr < __end; __ptr += 16) \ + { \ + char __buf[256], *__lim = __buf + sizeof(__buf), *__out = __buf; \ + __out += snprintf( __out, __lim - __out, "%08zx ", (char *)__ptr - (char *)data ); \ + for (__tmp = __ptr; __tmp < __end && __tmp < __ptr + 16; ++__tmp) \ + __out += snprintf( __out, __lim - __out, " %02x", *__tmp ); \ + memset( __out, ' ', (__ptr + 16 - __tmp) * 3 + 2 ); \ + __out += (__ptr + 16 - __tmp) * 3 + 2; \ + for (__tmp = __ptr; __tmp < __end && __tmp < __ptr + 16; ++__tmp) \ + *__out++ = *__tmp >= ' ' && *__tmp <= '~' ? *__tmp : '.'; \ + *__out++ = 0; \ + TRACE( "%s\n", __buf ); \ + } \ + } while (0) + +NTSTATUS media_type_from_codec_params( const AVCodecParameters *params, const AVRational *sar, const AVRational *fps, + UINT32 align, struct media_type *media_type ) +{ + TRACE( "codec type %#x, id %#x (%s), tag %#x (%s)\n", params->codec_type, params->codec_id, avcodec_get_name(params->codec_id), + params->codec_tag, debugstr_fourcc(params->codec_tag) ); + if (params->extradata_size) TRACE_HEXDUMP( params->extradata, params->extradata_size ); + + if (params->codec_type == AVMEDIA_TYPE_AUDIO) + { + media_type->major = MFMediaType_Audio; + return STATUS_SUCCESS; + } + + if (params->codec_type == AVMEDIA_TYPE_VIDEO) + { + media_type->major = MFMediaType_Video; + return STATUS_SUCCESS; + } + + FIXME( "Unknown type %#x\n", params->codec_type ); + return STATUS_NOT_IMPLEMENTED; +} + +#endif /* HAVE_FFMPEG */ diff --git a/dlls/winedmo/unix_private.h b/dlls/winedmo/unix_private.h index 41607ae1e3c..bb91e06449b 100644 --- a/dlls/winedmo/unix_private.h +++ b/dlls/winedmo/unix_private.h @@ -26,6 +26,10 @@ #include <libavutil/avutil.h> #include <libavutil/imgutils.h> #include <libavformat/avformat.h> +#include <libavcodec/avcodec.h> +#else +typedef struct AVCodecParameters AVCodecParameters; +typedef struct AVRational AVRational; #endif /* HAVE_FFMPEG */
#include "unixlib.h" @@ -39,3 +43,8 @@ extern int unix_read_callback( void *opaque, uint8_t *buffer, int size ); extern NTSTATUS demuxer_check( void * ); extern NTSTATUS demuxer_create( void * ); extern NTSTATUS demuxer_destroy( void * ); +extern NTSTATUS demuxer_stream_type( void * ); + +/* unix_media_type.c */ +extern NTSTATUS media_type_from_codec_params( const AVCodecParameters *params, const AVRational *sar, const AVRational *fps, + UINT32 align, struct media_type *media_type ); diff --git a/dlls/winedmo/unixlib.c b/dlls/winedmo/unixlib.c index e6f2a8ee889..13178ec5260 100644 --- a/dlls/winedmo/unixlib.c +++ b/dlls/winedmo/unixlib.c @@ -132,6 +132,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = X( demuxer_check ), X( demuxer_create ), X( demuxer_destroy ), + X( demuxer_stream_type ), };
C_ASSERT(ARRAY_SIZE(__wine_unix_call_funcs) == unix_funcs_count); @@ -190,6 +191,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = X( demuxer_check ), X64( demuxer_create ), X64( demuxer_destroy ), + X( demuxer_stream_type ), };
C_ASSERT(ARRAY_SIZE(__wine_unix_call_wow64_funcs) == unix_funcs_count); diff --git a/dlls/winedmo/unixlib.h b/dlls/winedmo/unixlib.h index b3f0583ff07..9e1bdd14ad2 100644 --- a/dlls/winedmo/unixlib.h +++ b/dlls/winedmo/unixlib.h @@ -63,6 +63,20 @@ struct read_callback_params };
+struct media_type +{ + GUID major; + UINT32 format_size; + union + { + void *format; + WAVEFORMATEX *audio; + MFVIDEOFORMAT *video; + UINT64 __pad; + }; +}; + + struct demuxer_check_params { char mime_type[256]; @@ -84,6 +98,13 @@ struct demuxer_destroy_params struct stream_context *context; };
+struct demuxer_stream_type_params +{ + struct winedmo_demuxer demuxer; + UINT32 stream; + struct media_type media_type; +}; +
enum unix_funcs { @@ -92,6 +113,7 @@ enum unix_funcs unix_demuxer_check, unix_demuxer_create, unix_demuxer_destroy, + unix_demuxer_stream_type,
unix_funcs_count, }; diff --git a/dlls/winedmo/winedmo.spec b/dlls/winedmo/winedmo.spec index 61da0617a7c..8038312d942 100644 --- a/dlls/winedmo/winedmo.spec +++ b/dlls/winedmo/winedmo.spec @@ -1,3 +1,4 @@ @ cdecl winedmo_demuxer_check(str) @ cdecl winedmo_demuxer_create(wstr ptr ptr ptr ptr ptr ptr) @ cdecl winedmo_demuxer_destroy(ptr) +@ cdecl winedmo_demuxer_stream_type(int64 ptr ptr) diff --git a/include/wine/winedmo.h b/include/wine/winedmo.h index 758066a85b5..cdcd77f5dd0 100644 --- a/include/wine/winedmo.h +++ b/include/wine/winedmo.h @@ -26,6 +26,14 @@ #include "winbase.h" #include "winternl.h"
+#include "mfapi.h" + +union winedmo_format +{ + WAVEFORMATEX audio; + MFVIDEOFORMAT video; +}; + struct winedmo_stream { NTSTATUS (CDECL *p_seek)( struct winedmo_stream *stream, UINT64 *pos ); @@ -38,5 +46,7 @@ NTSTATUS CDECL winedmo_demuxer_check( const char *mime_type ); NTSTATUS CDECL winedmo_demuxer_create( const WCHAR *url, struct winedmo_stream *stream, UINT64 *stream_size, INT64 *duration, UINT *stream_count, WCHAR *mime_type, struct winedmo_demuxer *demuxer ); NTSTATUS CDECL winedmo_demuxer_destroy( struct winedmo_demuxer *demuxer ); +NTSTATUS CDECL winedmo_demuxer_stream_type( struct winedmo_demuxer demuxer, UINT stream, + GUID *major, union winedmo_format **format );
#endif /* __WINE_WINEDMO_H */