Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
3dd56dd6
Commit
3dd56dd6
authored
Nov 24, 2022
by
Paul Gofman
Committed by
Alexandre Julliard
Dec 03, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winegstreamer: Query stream tags and set MF_SD_LANGUAGE attribute.
Loosely based on a patch by Derek Lesho and Rémi Bernon.
parent
2dad3edf
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
139 additions
and
3 deletions
+139
-3
gst_private.h
dlls/winegstreamer/gst_private.h
+1
-1
main.c
dlls/winegstreamer/main.c
+31
-0
media_source.c
dlls/winegstreamer/media_source.c
+30
-0
unixlib.h
dlls/winegstreamer/unixlib.h
+15
-0
wg_parser.c
dlls/winegstreamer/wg_parser.c
+60
-2
wm_reader.c
dlls/winegstreamer/wm_reader.c
+2
-0
No files found.
dlls/winegstreamer/gst_private.h
View file @
3dd56dd6
...
@@ -33,7 +33,6 @@
...
@@ -33,7 +33,6 @@
#define NONAMELESSUNION
#define NONAMELESSUNION
#include "dshow.h"
#include "dshow.h"
#include "mfidl.h"
#include "mfidl.h"
#include "wmsdk.h"
#include "wine/debug.h"
#include "wine/debug.h"
#include "wine/strmbase.h"
#include "wine/strmbase.h"
...
@@ -96,6 +95,7 @@ void wg_parser_stream_notify_qos(struct wg_parser_stream *stream,
...
@@ -96,6 +95,7 @@ void wg_parser_stream_notify_qos(struct wg_parser_stream *stream,
/* Returns the duration in 100-nanosecond units. */
/* Returns the duration in 100-nanosecond units. */
uint64_t
wg_parser_stream_get_duration
(
struct
wg_parser_stream
*
stream
);
uint64_t
wg_parser_stream_get_duration
(
struct
wg_parser_stream
*
stream
);
char
*
wg_parser_stream_get_tag
(
struct
wg_parser_stream
*
stream
,
enum
wg_parser_tag
tag
);
/* start_pos and stop_pos are in 100-nanosecond units. */
/* start_pos and stop_pos are in 100-nanosecond units. */
void
wg_parser_stream_seek
(
struct
wg_parser_stream
*
stream
,
double
rate
,
void
wg_parser_stream_seek
(
struct
wg_parser_stream
*
stream
,
double
rate
,
uint64_t
start_pos
,
uint64_t
stop_pos
,
DWORD
start_flags
,
DWORD
stop_flags
);
uint64_t
start_pos
,
uint64_t
stop_pos
,
DWORD
start_flags
,
DWORD
stop_flags
);
...
...
dlls/winegstreamer/main.c
View file @
3dd56dd6
...
@@ -21,6 +21,9 @@
...
@@ -21,6 +21,9 @@
#define WINE_NO_NAMELESS_EXTENSION
#define WINE_NO_NAMELESS_EXTENSION
#define EXTERN_GUID DEFINE_GUID
#define EXTERN_GUID DEFINE_GUID
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "initguid.h"
#include "initguid.h"
#include "gst_private.h"
#include "gst_private.h"
#include "winternl.h"
#include "winternl.h"
...
@@ -273,6 +276,34 @@ uint64_t wg_parser_stream_get_duration(struct wg_parser_stream *stream)
...
@@ -273,6 +276,34 @@ uint64_t wg_parser_stream_get_duration(struct wg_parser_stream *stream)
return
params
.
duration
;
return
params
.
duration
;
}
}
char
*
wg_parser_stream_get_tag
(
struct
wg_parser_stream
*
stream
,
enum
wg_parser_tag
tag
)
{
uint32_t
size
=
0
;
struct
wg_parser_stream_get_tag_params
params
=
{
.
stream
=
stream
,
.
tag
=
tag
,
.
size
=
&
size
,
};
char
*
buffer
;
if
(
WINE_UNIX_CALL
(
unix_wg_parser_stream_get_tag
,
&
params
)
!=
STATUS_BUFFER_TOO_SMALL
)
return
NULL
;
if
(
!
(
buffer
=
malloc
(
size
)))
{
ERR
(
"No memory.
\n
"
);
return
NULL
;
}
params
.
buffer
=
buffer
;
if
(
WINE_UNIX_CALL
(
unix_wg_parser_stream_get_tag
,
&
params
))
{
ERR
(
"wg_parser_stream_get_tag failed unexpectedly.
\n
"
);
free
(
buffer
);
return
NULL
;
}
return
buffer
;
}
void
wg_parser_stream_seek
(
struct
wg_parser_stream
*
stream
,
double
rate
,
void
wg_parser_stream_seek
(
struct
wg_parser_stream
*
stream
,
double
rate
,
uint64_t
start_pos
,
uint64_t
stop_pos
,
DWORD
start_flags
,
DWORD
stop_flags
)
uint64_t
start_pos
,
uint64_t
stop_pos
,
DWORD
start_flags
,
DWORD
stop_flags
)
{
{
...
...
dlls/winegstreamer/media_source.c
View file @
3dd56dd6
...
@@ -1481,7 +1481,37 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
...
@@ -1481,7 +1481,37 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
descriptors
=
malloc
(
object
->
stream_count
*
sizeof
(
IMFStreamDescriptor
*
));
descriptors
=
malloc
(
object
->
stream_count
*
sizeof
(
IMFStreamDescriptor
*
));
for
(
i
=
0
;
i
<
object
->
stream_count
;
i
++
)
for
(
i
=
0
;
i
<
object
->
stream_count
;
i
++
)
{
{
static
const
struct
{
enum
wg_parser_tag
tag
;
const
GUID
*
mf_attr
;
}
tags
[]
=
{
{
WG_PARSER_TAG_LANGUAGE
,
&
MF_SD_LANGUAGE
},
};
unsigned
int
j
;
WCHAR
*
strW
;
DWORD
len
;
char
*
str
;
IMFMediaStream_GetStreamDescriptor
(
&
object
->
streams
[
i
]
->
IMFMediaStream_iface
,
&
descriptors
[
i
]);
IMFMediaStream_GetStreamDescriptor
(
&
object
->
streams
[
i
]
->
IMFMediaStream_iface
,
&
descriptors
[
i
]);
for
(
j
=
0
;
j
<
ARRAY_SIZE
(
tags
);
++
j
)
{
if
(
!
(
str
=
wg_parser_stream_get_tag
(
object
->
streams
[
i
]
->
wg_stream
,
tags
[
j
].
tag
)))
continue
;
if
(
!
(
len
=
MultiByteToWideChar
(
CP_UTF8
,
0
,
str
,
-
1
,
NULL
,
0
)))
{
free
(
str
);
continue
;
}
strW
=
malloc
(
len
*
sizeof
(
*
strW
));
if
(
MultiByteToWideChar
(
CP_UTF8
,
0
,
str
,
-
1
,
strW
,
len
))
IMFStreamDescriptor_SetString
(
descriptors
[
i
],
tags
[
j
].
mf_attr
,
strW
);
free
(
strW
);
free
(
str
);
}
}
}
if
(
FAILED
(
hr
=
MFCreatePresentationDescriptor
(
object
->
stream_count
,
descriptors
,
&
object
->
pres_desc
)))
if
(
FAILED
(
hr
=
MFCreatePresentationDescriptor
(
object
->
stream_count
,
descriptors
,
&
object
->
pres_desc
)))
...
...
dlls/winegstreamer/unixlib.h
View file @
3dd56dd6
...
@@ -252,6 +252,20 @@ struct wg_parser_stream_get_duration_params
...
@@ -252,6 +252,20 @@ struct wg_parser_stream_get_duration_params
UINT64
duration
;
UINT64
duration
;
};
};
enum
wg_parser_tag
{
WG_PARSER_TAG_LANGUAGE
,
WG_PARSER_TAG_COUNT
};
struct
wg_parser_stream_get_tag_params
{
struct
wg_parser_stream
*
stream
;
enum
wg_parser_tag
tag
;
char
*
buffer
;
UINT32
*
size
;
};
struct
wg_parser_stream_seek_params
struct
wg_parser_stream_seek_params
{
{
struct
wg_parser_stream
*
stream
;
struct
wg_parser_stream
*
stream
;
...
@@ -312,6 +326,7 @@ enum unix_funcs
...
@@ -312,6 +326,7 @@ enum unix_funcs
unix_wg_parser_stream_notify_qos
,
unix_wg_parser_stream_notify_qos
,
unix_wg_parser_stream_get_duration
,
unix_wg_parser_stream_get_duration
,
unix_wg_parser_stream_get_tag
,
unix_wg_parser_stream_seek
,
unix_wg_parser_stream_seek
,
unix_wg_transform_create
,
unix_wg_transform_create
,
...
...
dlls/winegstreamer/wg_parser.c
View file @
3dd56dd6
...
@@ -34,6 +34,8 @@
...
@@ -34,6 +34,8 @@
#include <gst/video/video.h>
#include <gst/video/video.h>
#include <gst/audio/audio.h>
#include <gst/audio/audio.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "winternl.h"
#include "winternl.h"
#include "dshow.h"
#include "dshow.h"
...
@@ -107,9 +109,10 @@ struct wg_parser_stream
...
@@ -107,9 +109,10 @@ struct wg_parser_stream
GstBuffer
*
buffer
;
GstBuffer
*
buffer
;
GstMapInfo
map_info
;
GstMapInfo
map_info
;
bool
flushing
,
eos
,
enabled
,
has_caps
;
bool
flushing
,
eos
,
enabled
,
has_caps
,
has_tags
,
has_buffer
;
uint64_t
duration
;
uint64_t
duration
;
gchar
*
tags
[
WG_PARSER_TAG_COUNT
];
};
};
static
NTSTATUS
wg_parser_get_stream_count
(
void
*
args
)
static
NTSTATUS
wg_parser_get_stream_count
(
void
*
args
)
...
@@ -397,6 +400,24 @@ static NTSTATUS wg_parser_stream_get_duration(void *args)
...
@@ -397,6 +400,24 @@ static NTSTATUS wg_parser_stream_get_duration(void *args)
return
S_OK
;
return
S_OK
;
}
}
static
NTSTATUS
wg_parser_stream_get_tag
(
void
*
args
)
{
struct
wg_parser_stream_get_tag_params
*
params
=
args
;
uint32_t
len
;
if
(
params
->
tag
>=
WG_PARSER_TAG_COUNT
)
return
STATUS_INVALID_PARAMETER
;
if
(
!
params
->
stream
->
tags
[
params
->
tag
])
return
STATUS_NOT_FOUND
;
if
((
len
=
strlen
(
params
->
stream
->
tags
[
params
->
tag
])
+
1
)
>
*
params
->
size
)
{
*
params
->
size
=
len
;
return
STATUS_BUFFER_TOO_SMALL
;
}
memcpy
(
params
->
buffer
,
params
->
stream
->
tags
[
params
->
tag
],
len
);
return
STATUS_SUCCESS
;
}
static
NTSTATUS
wg_parser_stream_seek
(
void
*
args
)
static
NTSTATUS
wg_parser_stream_seek
(
void
*
args
)
{
{
GstSeekType
start_type
=
GST_SEEK_TYPE_SET
,
stop_type
=
GST_SEEK_TYPE_SET
;
GstSeekType
start_type
=
GST_SEEK_TYPE_SET
,
stop_type
=
GST_SEEK_TYPE_SET
;
...
@@ -574,6 +595,13 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
...
@@ -574,6 +595,13 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
break
;
break
;
}
}
case
GST_EVENT_TAG
:
pthread_mutex_lock
(
&
parser
->
mutex
);
stream
->
has_tags
=
true
;
pthread_cond_signal
(
&
parser
->
init_cond
);
pthread_mutex_unlock
(
&
parser
->
mutex
);
break
;
default:
default:
GST_WARNING
(
"Ignoring
\"
%s
\"
event."
,
GST_EVENT_TYPE_NAME
(
event
));
GST_WARNING
(
"Ignoring
\"
%s
\"
event."
,
GST_EVENT_TYPE_NAME
(
event
));
}
}
...
@@ -590,6 +618,12 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu
...
@@ -590,6 +618,12 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu
pthread_mutex_lock
(
&
parser
->
mutex
);
pthread_mutex_lock
(
&
parser
->
mutex
);
if
(
!
stream
->
has_buffer
)
{
stream
->
has_buffer
=
true
;
pthread_cond_signal
(
&
parser
->
init_cond
);
}
/* Allow this buffer to be flushed by GStreamer. We are effectively
/* Allow this buffer to be flushed by GStreamer. We are effectively
* implementing a queue object here. */
* implementing a queue object here. */
...
@@ -756,6 +790,8 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser)
...
@@ -756,6 +790,8 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser)
static
void
free_stream
(
struct
wg_parser_stream
*
stream
)
static
void
free_stream
(
struct
wg_parser_stream
*
stream
)
{
{
unsigned
int
i
;
if
(
stream
->
their_src
)
if
(
stream
->
their_src
)
{
{
if
(
stream
->
post_sink
)
if
(
stream
->
post_sink
)
...
@@ -771,6 +807,11 @@ static void free_stream(struct wg_parser_stream *stream)
...
@@ -771,6 +807,11 @@ static void free_stream(struct wg_parser_stream *stream)
pthread_cond_destroy
(
&
stream
->
event_cond
);
pthread_cond_destroy
(
&
stream
->
event_cond
);
pthread_cond_destroy
(
&
stream
->
event_empty_cond
);
pthread_cond_destroy
(
&
stream
->
event_empty_cond
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
stream
->
tags
);
++
i
)
{
if
(
stream
->
tags
[
i
])
g_free
(
stream
->
tags
[
i
]);
}
free
(
stream
);
free
(
stream
);
}
}
...
@@ -1232,6 +1273,19 @@ static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
...
@@ -1232,6 +1273,19 @@ static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
return
ret
;
return
ret
;
}
}
static
void
query_tags
(
struct
wg_parser_stream
*
stream
)
{
GstTagList
*
tag_list
;
GstEvent
*
tag_event
;
if
(
!
(
tag_event
=
gst_pad_get_sticky_event
(
stream
->
their_src
,
GST_EVENT_TAG
,
0
)))
return
;
gst_event_parse_tag
(
tag_event
,
&
tag_list
);
gst_tag_list_get_string
(
tag_list
,
"language-code"
,
&
stream
->
tags
[
WG_PARSER_TAG_LANGUAGE
]);
gst_event_unref
(
tag_event
);
}
static
NTSTATUS
wg_parser_connect
(
void
*
args
)
static
NTSTATUS
wg_parser_connect
(
void
*
args
)
{
{
GstStaticPadTemplate
src_template
=
GST_STATIC_PAD_TEMPLATE
(
"quartz_src"
,
GstStaticPadTemplate
src_template
=
GST_STATIC_PAD_TEMPLATE
(
"quartz_src"
,
...
@@ -1290,7 +1344,8 @@ static NTSTATUS wg_parser_connect(void *args)
...
@@ -1290,7 +1344,8 @@ static NTSTATUS wg_parser_connect(void *args)
struct
wg_parser_stream
*
stream
=
parser
->
streams
[
i
];
struct
wg_parser_stream
*
stream
=
parser
->
streams
[
i
];
gint64
duration
;
gint64
duration
;
while
(
!
stream
->
has_caps
&&
!
parser
->
error
)
/* If we receieved a buffer waiting for tags or caps does not make sense anymore. */
while
((
!
stream
->
has_caps
||
!
stream
->
has_tags
)
&&
!
parser
->
error
&&
!
stream
->
has_buffer
)
pthread_cond_wait
(
&
parser
->
init_cond
,
&
parser
->
mutex
);
pthread_cond_wait
(
&
parser
->
init_cond
,
&
parser
->
mutex
);
/* GStreamer doesn't actually provide any guarantees about when duration
/* GStreamer doesn't actually provide any guarantees about when duration
...
@@ -1354,6 +1409,8 @@ static NTSTATUS wg_parser_connect(void *args)
...
@@ -1354,6 +1409,8 @@ static NTSTATUS wg_parser_connect(void *args)
}
}
}
}
query_tags
(
stream
);
/* Now that we're fully initialized, enable the stream so that further
/* Now that we're fully initialized, enable the stream so that further
* samples get queued instead of being discarded. We don't actually need
* samples get queued instead of being discarded. We don't actually need
* the samples (in particular, the frontend should seek before
* the samples (in particular, the frontend should seek before
...
@@ -1676,6 +1733,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
...
@@ -1676,6 +1733,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X
(
wg_parser_stream_notify_qos
),
X
(
wg_parser_stream_notify_qos
),
X
(
wg_parser_stream_get_duration
),
X
(
wg_parser_stream_get_duration
),
X
(
wg_parser_stream_get_tag
),
X
(
wg_parser_stream_seek
),
X
(
wg_parser_stream_seek
),
X
(
wg_transform_create
),
X
(
wg_transform_create
),
...
...
dlls/winegstreamer/wm_reader.c
View file @
3dd56dd6
...
@@ -17,6 +17,8 @@
...
@@ -17,6 +17,8 @@
*/
*/
#include "gst_private.h"
#include "gst_private.h"
#include "initguid.h"
#include "wmsdk.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
wmvcore
);
WINE_DEFAULT_DEBUG_CHANNEL
(
wmvcore
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment