Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
939638b0
Commit
939638b0
authored
Sep 18, 2019
by
Zebediah Figura
Committed by
Alexandre Julliard
Sep 19, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winegstreamer: Reimplement the WAVE parser ontop of the wavparse plugin.
Signed-off-by:
Zebediah Figura
<
z.figura12@gmail.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
41fc4564
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
173 additions
and
471 deletions
+173
-471
Makefile.in
dlls/quartz/Makefile.in
+1
-2
main.c
dlls/quartz/main.c
+0
-1
quartz_private.h
dlls/quartz/quartz_private.h
+0
-1
quartz_strmif.idl
dlls/quartz/quartz_strmif.idl
+0
-7
regsvr.c
dlls/quartz/regsvr.c
+0
-19
waveparser.c
dlls/quartz/tests/waveparser.c
+12
-1
waveparser.c
dlls/quartz/waveparser.c
+0
-440
gst_private.h
dlls/winegstreamer/gst_private.h
+1
-0
gstdemux.c
dlls/winegstreamer/gstdemux.c
+109
-0
main.c
dlls/winegstreamer/main.c
+50
-0
No files found.
dlls/quartz/Makefile.in
View file @
939638b0
...
...
@@ -23,8 +23,7 @@ C_SRCS = \
regsvr.c
\
systemclock.c
\
videorenderer.c
\
vmr9.c
\
waveparser.c
vmr9.c
RC_SRCS
=
quartz.rc
...
...
dlls/quartz/main.c
View file @
939638b0
...
...
@@ -80,7 +80,6 @@ static const struct object_creation_info object_creation[] =
{
&
CLSID_AVIDec
,
AVIDec_create
},
{
&
CLSID_SystemClock
,
QUARTZ_CreateSystemClock
},
{
&
CLSID_ACMWrapper
,
ACMWrapper_create
},
{
&
CLSID_WAVEParser
,
WAVEParser_create
}
};
static
HRESULT
WINAPI
DSCF_QueryInterface
(
IClassFactory
*
iface
,
REFIID
riid
,
void
**
ppobj
)
...
...
dlls/quartz/quartz_private.h
View file @
939638b0
...
...
@@ -63,7 +63,6 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN
HRESULT
VideoRendererDefault_create
(
IUnknown
*
pUnkOuter
,
LPVOID
*
ppv
)
DECLSPEC_HIDDEN
;
HRESULT
QUARTZ_CreateSystemClock
(
IUnknown
*
pUnkOuter
,
LPVOID
*
ppv
)
DECLSPEC_HIDDEN
;
HRESULT
ACMWrapper_create
(
IUnknown
*
pUnkOuter
,
LPVOID
*
ppv
)
DECLSPEC_HIDDEN
;
HRESULT
WAVEParser_create
(
IUnknown
*
pUnkOuter
,
LPVOID
*
ppv
)
DECLSPEC_HIDDEN
;
HRESULT
VMR7Impl_create
(
IUnknown
*
pUnkOuter
,
LPVOID
*
ppv
)
DECLSPEC_HIDDEN
;
HRESULT
VMR9Impl_create
(
IUnknown
*
pUnkOuter
,
LPVOID
*
ppv
)
DECLSPEC_HIDDEN
;
...
...
dlls/quartz/quartz_strmif.idl
View file @
939638b0
...
...
@@ -141,13 +141,6 @@ coclass VideoRendererDefault { interface IBaseFilter; }
coclass
ACMWrapper
{
interface
IBaseFilter
; }
[
helpstring
(
"Wave Parser"
),
threading
(
both
),
uuid
(
d51bd5a1
-
7548
-
11
cf
-
a520
-
0080
c77ef58a
)
]
coclass
WAVEParser
{
interface
IBaseFilter
; }
[
helpstring
(
"Video Mixing Renderer"
),
threading
(
both
),
uuid
(
b87beb7b
-
8
d29
-
423
f
-
ae4d
-
6582
c10175ac
)
...
...
dlls/quartz/regsvr.c
View file @
939638b0
...
...
@@ -354,25 +354,6 @@ static struct regsvr_filter const filter_list[] = {
{
0xFFFFFFFF
},
}
},
{
&
CLSID_WAVEParser
,
&
CLSID_LegacyAmFilterCategory
,
{
'W'
,
'a'
,
'v'
,
'e'
,
' '
,
'P'
,
'a'
,
'r'
,
's'
,
'e'
,
'r'
,
0
},
0x400000
,
{
{
0
,
{
{
&
MEDIATYPE_Stream
,
&
MEDIASUBTYPE_WAVE
},
{
&
MEDIATYPE_Stream
,
&
MEDIASUBTYPE_AU
},
{
&
MEDIATYPE_Stream
,
&
MEDIASUBTYPE_AIFF
},
{
NULL
}
},
},
{
REG_PINFLAG_B_OUTPUT
,
{
{
&
MEDIATYPE_Audio
,
&
GUID_NULL
},
{
NULL
}
},
},
{
0xFFFFFFFF
},
}
},
{
NULL
}
/* list terminator */
};
...
...
dlls/quartz/tests/waveparser.c
View file @
939638b0
...
...
@@ -148,7 +148,7 @@ static void test_interfaces(void)
check_interface
(
pin
,
&
IID_IKsPropertySet
,
FALSE
);
check_interface
(
pin
,
&
IID_IMemInputPin
,
FALSE
);
check_interface
(
pin
,
&
IID_IMediaPosition
,
FALSE
);
todo_wine
check_interface
(
pin
,
&
IID_IMediaSeeking
,
FALSE
);
check_interface
(
pin
,
&
IID_IMediaSeeking
,
FALSE
);
IPin_Release
(
pin
);
...
...
@@ -157,6 +157,7 @@ static void test_interfaces(void)
todo_wine
check_interface
(
pin
,
&
IID_IMediaPosition
,
TRUE
);
check_interface
(
pin
,
&
IID_IMediaSeeking
,
TRUE
);
check_interface
(
pin
,
&
IID_IPin
,
TRUE
);
check_interface
(
pin
,
&
IID_IQualityControl
,
TRUE
);
check_interface
(
pin
,
&
IID_IUnknown
,
TRUE
);
check_interface
(
pin
,
&
IID_IAsyncReader
,
FALSE
);
...
...
@@ -762,8 +763,18 @@ static void test_enum_media_types(void)
START_TEST
(
waveparser
)
{
IBaseFilter
*
filter
;
CoInitialize
(
NULL
);
if
(
FAILED
(
CoCreateInstance
(
&
CLSID_WAVEParser
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IBaseFilter
,
(
void
**
)
&
filter
)))
{
skip
(
"Failed to create WAVE parser.
\n
"
);
return
;
}
IBaseFilter_Release
(
filter
);
test_interfaces
();
test_aggregation
();
test_enum_pins
();
...
...
dlls/quartz/waveparser.c
deleted
100644 → 0
View file @
41fc4564
/*
* WAVE Parser Filter
*
* Copyright 2005 Christian Costa
*
* 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
*/
#include "quartz_private.h"
#include "pin.h"
#include "uuids.h"
#include "aviriff.h"
#include "vfwmsgs.h"
#include "mmsystem.h"
#include "wine/debug.h"
#include <math.h>
#include <assert.h>
#include "parser.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
quartz
);
static
const
WCHAR
outputW
[]
=
{
'o'
,
'u'
,
't'
,
'p'
,
'u'
,
't'
,
0
};
typedef
struct
WAVEParserImpl
{
ParserImpl
Parser
;
LONGLONG
StartOfFile
;
/* in media time */
LONGLONG
EndOfFile
;
DWORD
nAvgBytesPerSec
;
DWORD
nBlockAlign
;
}
WAVEParserImpl
;
static
inline
WAVEParserImpl
*
impl_from_IMediaSeeking
(
IMediaSeeking
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
WAVEParserImpl
,
Parser
.
sourceSeeking
.
IMediaSeeking_iface
);
}
static
inline
WAVEParserImpl
*
impl_from_strmbase_filter
(
struct
strmbase_filter
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
WAVEParserImpl
,
Parser
.
filter
);
}
static
LONGLONG
bytepos_to_duration
(
WAVEParserImpl
*
This
,
LONGLONG
bytepos
)
{
LONGLONG
duration
=
BYTES_FROM_MEDIATIME
(
bytepos
-
This
->
StartOfFile
);
duration
*=
10000000
;
duration
/=
This
->
nAvgBytesPerSec
;
return
duration
;
}
static
LONGLONG
duration_to_bytepos
(
WAVEParserImpl
*
This
,
LONGLONG
duration
)
{
LONGLONG
bytepos
;
bytepos
=
This
->
nAvgBytesPerSec
;
bytepos
*=
duration
;
bytepos
/=
10000000
;
bytepos
-=
bytepos
%
This
->
nBlockAlign
;
bytepos
+=
BYTES_FROM_MEDIATIME
(
This
->
StartOfFile
);
return
MEDIATIME_FROM_BYTES
(
bytepos
);
}
static
HRESULT
WAVEParser_Sample
(
LPVOID
iface
,
IMediaSample
*
pSample
,
DWORD_PTR
cookie
)
{
WAVEParserImpl
*
This
=
iface
;
LPBYTE
pbSrcStream
=
NULL
;
ULONG
cbSrcStream
=
0
;
REFERENCE_TIME
tStart
,
tStop
;
HRESULT
hr
;
IMediaSample
*
newsample
=
NULL
;
Parser_OutputPin
*
pOutputPin
;
PullPin
*
pin
=
This
->
Parser
.
pInputPin
;
IMediaSample_GetPointer
(
pSample
,
&
pbSrcStream
);
hr
=
IMediaSample_GetTime
(
pSample
,
&
tStart
,
&
tStop
);
cbSrcStream
=
IMediaSample_GetActualDataLength
(
pSample
);
/* Flush occurring */
if
(
cbSrcStream
==
0
)
{
TRACE
(
".. Why do I need you?
\n
"
);
return
S_OK
;
}
pOutputPin
=
This
->
Parser
.
sources
[
0
];
if
(
SUCCEEDED
(
hr
))
hr
=
IMemAllocator_GetBuffer
(
pin
->
pAlloc
,
&
newsample
,
NULL
,
NULL
,
0
);
if
(
SUCCEEDED
(
hr
))
{
LONGLONG
rtSampleStart
=
pin
->
rtNext
;
/* Add 4 for the next header, which should hopefully work */
LONGLONG
rtSampleStop
=
rtSampleStart
+
MEDIATIME_FROM_BYTES
(
IMediaSample_GetSize
(
newsample
));
if
(
rtSampleStop
>
pin
->
rtStop
)
rtSampleStop
=
MEDIATIME_FROM_BYTES
(
ALIGNUP
(
BYTES_FROM_MEDIATIME
(
pin
->
rtStop
),
pin
->
cbAlign
));
IMediaSample_SetTime
(
newsample
,
&
rtSampleStart
,
&
rtSampleStop
);
pin
->
rtCurrent
=
pin
->
rtNext
;
pin
->
rtNext
=
rtSampleStop
;
IMediaSample_SetPreroll
(
newsample
,
FALSE
);
IMediaSample_SetDiscontinuity
(
newsample
,
FALSE
);
IMediaSample_SetSyncPoint
(
newsample
,
TRUE
);
hr
=
IAsyncReader_Request
(
pin
->
pReader
,
newsample
,
0
);
}
if
(
SUCCEEDED
(
hr
))
{
REFERENCE_TIME
tAviStart
,
tAviStop
;
IMediaSample_SetSyncPoint
(
pSample
,
TRUE
);
pOutputPin
->
dwSamplesProcessed
++
;
tAviStart
=
bytepos_to_duration
(
This
,
tStart
);
tAviStop
=
bytepos_to_duration
(
This
,
tStart
+
MEDIATIME_FROM_BYTES
(
IMediaSample_GetActualDataLength
(
pSample
)));
IMediaSample_SetTime
(
pSample
,
&
tAviStart
,
&
tAviStop
);
hr
=
BaseOutputPinImpl_Deliver
(
&
pOutputPin
->
pin
,
pSample
);
if
(
hr
!=
S_OK
&&
hr
!=
S_FALSE
&&
hr
!=
VFW_E_WRONG_STATE
)
ERR
(
"Error sending sample (%x)
\n
"
,
hr
);
else
if
(
hr
!=
S_OK
)
/* Unset progression if denied! */
This
->
Parser
.
pInputPin
->
rtCurrent
=
tStart
;
}
if
(
tStop
>=
This
->
EndOfFile
||
(
bytepos_to_duration
(
This
,
tStop
)
>=
This
->
Parser
.
sourceSeeking
.
llStop
)
||
hr
==
VFW_E_NOT_CONNECTED
)
{
unsigned
int
i
;
TRACE
(
"End of file reached
\n
"
);
for
(
i
=
0
;
i
<
This
->
Parser
.
cStreams
;
i
++
)
{
IPin
*
ppin
;
HRESULT
hr
;
TRACE
(
"Send End Of Stream to output pin %u
\n
"
,
i
);
hr
=
IPin_ConnectedTo
(
&
This
->
Parser
.
sources
[
i
]
->
pin
.
pin
.
IPin_iface
,
&
ppin
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
IPin_EndOfStream
(
ppin
);
IPin_Release
(
ppin
);
}
if
(
FAILED
(
hr
))
{
ERR
(
"%x
\n
"
,
hr
);
break
;
}
}
/* Force the pullpin thread to stop */
hr
=
S_FALSE
;
}
return
hr
;
}
static
HRESULT
WAVEParser_QueryAccept
(
LPVOID
iface
,
const
AM_MEDIA_TYPE
*
pmt
)
{
if
(
!
IsEqualIID
(
&
pmt
->
majortype
,
&
MEDIATYPE_Stream
))
return
S_FALSE
;
if
(
IsEqualIID
(
&
pmt
->
subtype
,
&
MEDIASUBTYPE_WAVE
))
return
S_OK
;
if
(
IsEqualIID
(
&
pmt
->
subtype
,
&
MEDIASUBTYPE_AU
)
||
IsEqualIID
(
&
pmt
->
subtype
,
&
MEDIASUBTYPE_AIFF
))
FIXME
(
"AU and AIFF files not supported yet!
\n
"
);
return
S_FALSE
;
}
static
HRESULT
WINAPI
WAVEParserImpl_seek
(
IMediaSeeking
*
iface
)
{
WAVEParserImpl
*
This
=
impl_from_IMediaSeeking
(
iface
);
PullPin
*
pPin
=
This
->
Parser
.
pInputPin
;
LONGLONG
newpos
,
curpos
,
endpos
,
bytepos
;
IPin
*
peer
;
newpos
=
This
->
Parser
.
sourceSeeking
.
llCurrent
;
curpos
=
bytepos_to_duration
(
This
,
pPin
->
rtCurrent
);
endpos
=
bytepos_to_duration
(
This
,
This
->
EndOfFile
);
bytepos
=
duration_to_bytepos
(
This
,
newpos
);
if
(
newpos
>
endpos
)
{
WARN
(
"Requesting position %s beyond end of stream %s
\n
"
,
wine_dbgstr_longlong
(
newpos
),
wine_dbgstr_longlong
(
endpos
));
return
E_INVALIDARG
;
}
if
(
curpos
/
1000000
==
newpos
/
1000000
)
{
TRACE
(
"Requesting position %s same as current position %s
\n
"
,
wine_dbgstr_longlong
(
newpos
),
wine_dbgstr_longlong
(
curpos
));
return
S_OK
;
}
TRACE
(
"Moving sound to %08u bytes!
\n
"
,
(
DWORD
)
BYTES_FROM_MEDIATIME
(
bytepos
));
EnterCriticalSection
(
&
pPin
->
thread_lock
);
IPin_BeginFlush
(
&
pPin
->
pin
.
IPin_iface
);
/* Make sure this is done while stopped, BeginFlush takes care of this */
EnterCriticalSection
(
&
This
->
Parser
.
filter
.
csFilter
);
if
((
peer
=
This
->
Parser
.
sources
[
0
]
->
pin
.
pin
.
pConnectedTo
))
IPin_NewSegment
(
peer
,
newpos
,
endpos
,
pPin
->
dRate
);
pPin
->
rtStart
=
pPin
->
rtCurrent
=
bytepos
;
This
->
Parser
.
sources
[
0
]
->
dwSamplesProcessed
=
0
;
LeaveCriticalSection
(
&
This
->
Parser
.
filter
.
csFilter
);
TRACE
(
"Done flushing
\n
"
);
IPin_EndFlush
(
&
pPin
->
pin
.
IPin_iface
);
LeaveCriticalSection
(
&
pPin
->
thread_lock
);
return
S_OK
;
}
static
HRESULT
WAVEParser_InputPin_PreConnect
(
IPin
*
iface
,
IPin
*
pConnectPin
,
ALLOCATOR_PROPERTIES
*
props
)
{
PullPin
*
This
=
impl_PullPin_from_IPin
(
iface
);
HRESULT
hr
;
RIFFLIST
list
;
RIFFCHUNK
chunk
;
LONGLONG
pos
=
0
;
/* in bytes */
AM_MEDIA_TYPE
amt
;
WAVEParserImpl
*
pWAVEParser
=
impl_from_strmbase_filter
(
This
->
pin
.
filter
);
hr
=
IAsyncReader_SyncRead
(
This
->
pReader
,
pos
,
sizeof
(
list
),
(
BYTE
*
)
&
list
);
pos
+=
sizeof
(
list
);
if
(
list
.
fcc
!=
FOURCC_RIFF
)
{
ERR
(
"Input stream not a RIFF file
\n
"
);
return
E_FAIL
;
}
if
(
list
.
cb
>
1
*
1024
*
1024
*
1024
)
/* cannot be more than 1Gb in size */
{
ERR
(
"Input stream violates RIFF spec
\n
"
);
return
E_FAIL
;
}
if
(
list
.
fccListType
!=
mmioFOURCC
(
'W'
,
'A'
,
'V'
,
'E'
))
{
ERR
(
"Input stream not an WAVE RIFF file
\n
"
);
return
E_FAIL
;
}
hr
=
IAsyncReader_SyncRead
(
This
->
pReader
,
pos
,
sizeof
(
chunk
),
(
BYTE
*
)
&
chunk
);
pos
+=
sizeof
(
chunk
);
if
(
chunk
.
fcc
!=
mmioFOURCC
(
'f'
,
'm'
,
't'
,
' '
))
{
ERR
(
"Expected 'fmt ' chunk, but got %.04s
\n
"
,
(
LPSTR
)
&
chunk
.
fcc
);
return
E_FAIL
;
}
amt
.
majortype
=
MEDIATYPE_Audio
;
amt
.
formattype
=
FORMAT_WaveFormatEx
;
amt
.
bFixedSizeSamples
=
TRUE
;
amt
.
bTemporalCompression
=
FALSE
;
amt
.
lSampleSize
=
1
;
amt
.
pUnk
=
NULL
;
amt
.
cbFormat
=
max
(
chunk
.
cb
,
sizeof
(
WAVEFORMATEX
));
amt
.
pbFormat
=
CoTaskMemAlloc
(
amt
.
cbFormat
);
memset
(
amt
.
pbFormat
,
0
,
amt
.
cbFormat
);
IAsyncReader_SyncRead
(
This
->
pReader
,
pos
,
chunk
.
cb
,
amt
.
pbFormat
);
amt
.
subtype
=
MEDIATYPE_Audio
;
amt
.
subtype
.
Data1
=
((
WAVEFORMATEX
*
)
amt
.
pbFormat
)
->
wFormatTag
;
pos
+=
chunk
.
cb
;
hr
=
IAsyncReader_SyncRead
(
This
->
pReader
,
pos
,
sizeof
(
chunk
),
(
BYTE
*
)
&
chunk
);
while
(
chunk
.
fcc
!=
mmioFOURCC
(
'd'
,
'a'
,
't'
,
'a'
))
{
FIXME
(
"Ignoring %s chunk.
\n
"
,
debugstr_fourcc
(
chunk
.
fcc
));
pos
+=
sizeof
(
chunk
)
+
chunk
.
cb
;
hr
=
IAsyncReader_SyncRead
(
This
->
pReader
,
pos
,
sizeof
(
chunk
),
(
BYTE
*
)
&
chunk
);
if
(
hr
!=
S_OK
)
return
E_FAIL
;
}
pWAVEParser
->
StartOfFile
=
MEDIATIME_FROM_BYTES
(
pos
+
sizeof
(
RIFFCHUNK
));
pWAVEParser
->
EndOfFile
=
MEDIATIME_FROM_BYTES
(
pos
+
chunk
.
cb
+
sizeof
(
RIFFCHUNK
));
props
->
cbAlign
=
((
WAVEFORMATEX
*
)
amt
.
pbFormat
)
->
nBlockAlign
;
props
->
cbPrefix
=
0
;
props
->
cbBuffer
=
4096
;
props
->
cBuffers
=
3
;
pWAVEParser
->
nBlockAlign
=
((
WAVEFORMATEX
*
)
amt
.
pbFormat
)
->
nBlockAlign
;
pWAVEParser
->
nAvgBytesPerSec
=
((
WAVEFORMATEX
*
)
amt
.
pbFormat
)
->
nAvgBytesPerSec
;
hr
=
Parser_AddPin
(
&
pWAVEParser
->
Parser
,
outputW
,
props
,
&
amt
);
CoTaskMemFree
(
amt
.
pbFormat
);
pWAVEParser
->
Parser
.
sourceSeeking
.
llCurrent
=
0
;
pWAVEParser
->
Parser
.
sourceSeeking
.
llStop
=
pWAVEParser
->
Parser
.
sourceSeeking
.
llDuration
=
bytepos_to_duration
(
pWAVEParser
,
pWAVEParser
->
EndOfFile
);
TRACE
(
"Duration: %u seconds
\n
"
,
(
DWORD
)(
pWAVEParser
->
Parser
.
sourceSeeking
.
llDuration
/
(
LONGLONG
)
10000000
));
This
->
rtStop
=
pWAVEParser
->
EndOfFile
;
This
->
rtStart
=
pWAVEParser
->
StartOfFile
;
TRACE
(
"WAVE File ok
\n
"
);
return
hr
;
}
static
HRESULT
WAVEParser_Cleanup
(
LPVOID
iface
)
{
WAVEParserImpl
*
This
=
iface
;
TRACE
(
"(%p)->()
\n
"
,
This
);
return
S_OK
;
}
static
HRESULT
WAVEParser_first_request
(
LPVOID
iface
)
{
WAVEParserImpl
*
This
=
iface
;
PullPin
*
pin
=
This
->
Parser
.
pInputPin
;
HRESULT
hr
;
IMediaSample
*
sample
;
if
(
pin
->
rtCurrent
>=
pin
->
rtStop
)
{
/* Last sample has already been queued, request nothing more */
TRACE
(
"Done!
\n
"
);
return
S_OK
;
}
hr
=
IMemAllocator_GetBuffer
(
pin
->
pAlloc
,
&
sample
,
NULL
,
NULL
,
0
);
pin
->
rtNext
=
pin
->
rtCurrent
;
if
(
SUCCEEDED
(
hr
))
{
LONGLONG
rtSampleStart
=
pin
->
rtNext
;
/* Add 4 for the next header, which should hopefully work */
LONGLONG
rtSampleStop
=
rtSampleStart
+
MEDIATIME_FROM_BYTES
(
IMediaSample_GetSize
(
sample
));
if
(
rtSampleStop
>
pin
->
rtStop
)
rtSampleStop
=
MEDIATIME_FROM_BYTES
(
ALIGNUP
(
BYTES_FROM_MEDIATIME
(
pin
->
rtStop
),
pin
->
cbAlign
));
IMediaSample_SetTime
(
sample
,
&
rtSampleStart
,
&
rtSampleStop
);
pin
->
rtCurrent
=
pin
->
rtNext
;
pin
->
rtNext
=
rtSampleStop
;
IMediaSample_SetPreroll
(
sample
,
FALSE
);
if
(
!
This
->
Parser
.
sources
[
0
]
->
dwSamplesProcessed
++
)
IMediaSample_SetDiscontinuity
(
sample
,
TRUE
);
else
IMediaSample_SetDiscontinuity
(
sample
,
FALSE
);
hr
=
IAsyncReader_Request
(
pin
->
pReader
,
sample
,
0
);
}
if
(
FAILED
(
hr
))
ERR
(
"Horsemen of the apocalypse came to bring error 0x%08x %p
\n
"
,
hr
,
sample
);
return
hr
;
}
static
HRESULT
WAVEParser_disconnect
(
LPVOID
iface
)
{
/* TODO: Find and plug memory leaks */
return
S_OK
;
}
static
const
IBaseFilterVtbl
WAVEParser_Vtbl
=
{
BaseFilterImpl_QueryInterface
,
BaseFilterImpl_AddRef
,
BaseFilterImpl_Release
,
BaseFilterImpl_GetClassID
,
Parser_Stop
,
Parser_Pause
,
Parser_Run
,
Parser_GetState
,
Parser_SetSyncSource
,
BaseFilterImpl_GetSyncSource
,
BaseFilterImpl_EnumPins
,
BaseFilterImpl_FindPin
,
BaseFilterImpl_QueryFilterInfo
,
BaseFilterImpl_JoinFilterGraph
,
BaseFilterImpl_QueryVendorInfo
,
};
static
void
wave_parser_destroy
(
struct
strmbase_filter
*
iface
)
{
WAVEParserImpl
*
filter
=
impl_from_strmbase_filter
(
iface
);
Parser_Destroy
(
&
filter
->
Parser
);
}
static
const
struct
strmbase_filter_ops
filter_ops
=
{
.
filter_get_pin
=
parser_get_pin
,
.
filter_destroy
=
wave_parser_destroy
,
};
HRESULT
WAVEParser_create
(
IUnknown
*
outer
,
void
**
out
)
{
static
const
WCHAR
sink_name
[]
=
{
'i'
,
'n'
,
'p'
,
'u'
,
't'
,
' '
,
'p'
,
'i'
,
'n'
,
0
};
HRESULT
hr
;
WAVEParserImpl
*
This
;
*
out
=
NULL
;
/* Note: This memory is managed by the transform filter once created */
This
=
CoTaskMemAlloc
(
sizeof
(
WAVEParserImpl
));
hr
=
Parser_Create
(
&
This
->
Parser
,
&
WAVEParser_Vtbl
,
outer
,
&
CLSID_WAVEParser
,
&
filter_ops
,
sink_name
,
WAVEParser_Sample
,
WAVEParser_QueryAccept
,
WAVEParser_InputPin_PreConnect
,
WAVEParser_Cleanup
,
WAVEParser_disconnect
,
WAVEParser_first_request
,
NULL
,
NULL
,
WAVEParserImpl_seek
,
NULL
);
if
(
FAILED
(
hr
))
return
hr
;
*
out
=
&
This
->
Parser
.
filter
.
IUnknown_inner
;
return
hr
;
}
dlls/winegstreamer/gst_private.h
View file @
939638b0
...
...
@@ -43,6 +43,7 @@ IUnknown * CALLBACK Gstreamer_Mp3_create(IUnknown *pUnkOuter, HRESULT *phr);
IUnknown
*
CALLBACK
Gstreamer_YUV2RGB_create
(
IUnknown
*
pUnkOuter
,
HRESULT
*
phr
);
IUnknown
*
CALLBACK
Gstreamer_YUV2ARGB_create
(
IUnknown
*
pUnkOuter
,
HRESULT
*
phr
);
IUnknown
*
CALLBACK
Gstreamer_Splitter_create
(
IUnknown
*
pUnkOuter
,
HRESULT
*
phr
);
IUnknown
*
CALLBACK
wave_parser_create
(
IUnknown
*
outer
,
HRESULT
*
phr
)
DECLSPEC_HIDDEN
;
BOOL
init_gstreamer
(
void
)
DECLSPEC_HIDDEN
;
...
...
dlls/winegstreamer/gstdemux.c
View file @
939638b0
...
...
@@ -2172,3 +2172,112 @@ void start_dispatch_thread(void)
pthread_key_create
(
&
wine_gst_key
,
NULL
);
CloseHandle
(
CreateThread
(
NULL
,
0
,
&
dispatch_thread
,
NULL
,
0
,
NULL
));
}
static
HRESULT
WINAPI
wave_parser_sink_CheckMediaType
(
BasePin
*
iface
,
const
AM_MEDIA_TYPE
*
mt
)
{
if
(
!
IsEqualGUID
(
&
mt
->
majortype
,
&
MEDIATYPE_Stream
))
return
S_FALSE
;
if
(
IsEqualGUID
(
&
mt
->
subtype
,
&
MEDIASUBTYPE_WAVE
))
return
S_OK
;
if
(
IsEqualGUID
(
&
mt
->
subtype
,
&
MEDIASUBTYPE_AU
)
||
IsEqualGUID
(
&
mt
->
subtype
,
&
MEDIASUBTYPE_AIFF
))
FIXME
(
"AU and AIFF files are not yet supported.
\n
"
);
return
S_FALSE
;
}
static
const
BasePinFuncTable
wave_parser_sink_ops
=
{
.
pfnCheckMediaType
=
wave_parser_sink_CheckMediaType
,
.
pfnGetMediaType
=
BasePinImpl_GetMediaType
,
};
static
BOOL
wave_parser_init_gst
(
struct
gstdemux
*
filter
)
{
static
const
WCHAR
source_name
[]
=
{
'o'
,
'u'
,
't'
,
'p'
,
'u'
,
't'
,
0
};
struct
gstdemux_source
*
pin
;
GstElement
*
element
;
LONGLONG
duration
;
int
ret
;
if
(
!
(
element
=
gst_element_factory_make
(
"wavparse"
,
NULL
)))
{
ERR
(
"Failed to create wavparse; are %u-bit GStreamer
\"
good
\"
plugins installed?
\n
"
,
8
*
(
int
)
sizeof
(
void
*
));
return
FALSE
;
}
gst_bin_add
(
GST_BIN
(
filter
->
container
),
element
);
filter
->
their_sink
=
gst_element_get_static_pad
(
element
,
"sink"
);
if
((
ret
=
gst_pad_link
(
filter
->
my_src
,
filter
->
their_sink
))
<
0
)
{
ERR
(
"Failed to link sink pads, error %d.
\n
"
,
ret
);
return
FALSE
;
}
if
(
!
(
pin
=
create_pin
(
filter
,
source_name
)))
return
FALSE
;
pin
->
their_src
=
gst_element_get_static_pad
(
element
,
"src"
);
gst_object_ref
(
pin
->
their_src
);
if
((
ret
=
gst_pad_link
(
pin
->
their_src
,
pin
->
my_sink
))
<
0
)
{
ERR
(
"Failed to link source pads, error %d.
\n
"
,
ret
);
return
FALSE
;
}
gst_pad_set_active
(
pin
->
my_sink
,
1
);
gst_element_set_state
(
filter
->
container
,
GST_STATE_PAUSED
);
ret
=
gst_element_get_state
(
filter
->
container
,
NULL
,
NULL
,
-
1
);
if
(
ret
==
GST_STATE_CHANGE_FAILURE
)
{
ERR
(
"Failed to play stream.
\n
"
);
return
FALSE
;
}
gst_pad_query_duration
(
pin
->
their_src
,
GST_FORMAT_TIME
,
&
duration
);
pin
->
seek
.
llDuration
=
pin
->
seek
.
llStop
=
duration
/
100
;
pin
->
seek
.
llCurrent
=
0
;
if
(
!
pin
->
seek
.
llDuration
)
pin
->
seek
.
dwCapabilities
=
0
;
WaitForSingleObject
(
pin
->
caps_event
,
INFINITE
);
filter
->
ignore_flush
=
TRUE
;
gst_element_set_state
(
filter
->
container
,
GST_STATE_READY
);
gst_element_get_state
(
filter
->
container
,
NULL
,
NULL
,
-
1
);
filter
->
ignore_flush
=
FALSE
;
return
TRUE
;
}
IUnknown
*
CALLBACK
wave_parser_create
(
IUnknown
*
outer
,
HRESULT
*
phr
)
{
static
const
WCHAR
sink_name
[]
=
{
'i'
,
'n'
,
'p'
,
'u'
,
't'
,
' '
,
'p'
,
'i'
,
'n'
,
0
};
struct
gstdemux
*
object
;
if
(
!
init_gstreamer
())
{
*
phr
=
E_FAIL
;
return
NULL
;
}
mark_wine_thread
();
if
(
!
(
object
=
heap_alloc_zero
(
sizeof
(
*
object
))))
{
*
phr
=
E_OUTOFMEMORY
;
return
NULL
;
}
strmbase_filter_init
(
&
object
->
filter
,
&
GST_Vtbl
,
outer
,
&
CLSID_WAVEParser
,
&
filter_ops
);
object
->
sink
.
dir
=
PINDIR_INPUT
;
object
->
sink
.
filter
=
&
object
->
filter
;
lstrcpynW
(
object
->
sink
.
name
,
sink_name
,
ARRAY_SIZE
(
object
->
sink
.
name
));
object
->
sink
.
IPin_iface
.
lpVtbl
=
&
GST_InputPin_Vtbl
;
object
->
sink
.
pFuncsTable
=
&
wave_parser_sink_ops
;
object
->
init_gst
=
wave_parser_init_gst
;
*
phr
=
S_OK
;
TRACE
(
"Created WAVE parser %p.
\n
"
,
object
);
return
&
object
->
filter
.
IUnknown_inner
;
}
dlls/winegstreamer/main.c
View file @
939638b0
...
...
@@ -46,6 +46,8 @@ static const WCHAR wGstreamer_Mp3[] =
{
'G'
,
'S'
,
't'
,
'r'
,
'e'
,
'a'
,
'm'
,
'e'
,
'r'
,
' '
,
'M'
,
'p'
,
'3'
,
' '
,
'f'
,
'i'
,
'l'
,
't'
,
'e'
,
'r'
,
0
};
static
const
WCHAR
wGstreamer_AudioConvert
[]
=
{
'G'
,
'S'
,
't'
,
'r'
,
'e'
,
'a'
,
'm'
,
'e'
,
'r'
,
' '
,
'A'
,
'u'
,
'd'
,
'i'
,
'o'
,
'C'
,
'o'
,
'n'
,
'v'
,
'e'
,
'r'
,
't'
,
' '
,
'f'
,
'i'
,
'l'
,
't'
,
'e'
,
'r'
,
0
};
static
const
WCHAR
wave_parserW
[]
=
{
'W'
,
'a'
,
'v'
,
'e'
,
' '
,
'P'
,
'a'
,
'r'
,
's'
,
'e'
,
'r'
,
0
};
static
WCHAR
wNull
[]
=
{
'\0'
};
...
...
@@ -180,6 +182,47 @@ AMOVIESETUP_FILTER const amfAudioConvert =
amfAudioConvertPin
};
static
const
AMOVIESETUP_MEDIATYPE
wave_parser_sink_type_data
[]
=
{
{
&
MEDIATYPE_Stream
,
&
MEDIASUBTYPE_WAVE
},
{
&
MEDIATYPE_Stream
,
&
MEDIASUBTYPE_AU
},
{
&
MEDIATYPE_Stream
,
&
MEDIASUBTYPE_AIFF
},
};
static
const
AMOVIESETUP_MEDIATYPE
wave_parser_source_type_data
[]
=
{
{
&
MEDIATYPE_Audio
,
&
GUID_NULL
},
};
static
const
AMOVIESETUP_PIN
wave_parser_pin_data
[]
=
{
{
NULL
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
&
GUID_NULL
,
NULL
,
ARRAY_SIZE
(
wave_parser_sink_type_data
),
wave_parser_sink_type_data
,
},
{
NULL
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
&
GUID_NULL
,
NULL
,
ARRAY_SIZE
(
wave_parser_source_type_data
),
wave_parser_source_type_data
,
},
};
static
const
AMOVIESETUP_FILTER
wave_parser_filter_data
=
{
&
CLSID_WAVEParser
,
wave_parserW
,
MERIT_UNLIKELY
,
ARRAY_SIZE
(
wave_parser_pin_data
),
wave_parser_pin_data
,
};
FactoryTemplate
const
g_Templates
[]
=
{
{
wGstreamer_Splitter
,
...
...
@@ -216,6 +259,13 @@ FactoryTemplate const g_Templates[] = {
NULL
,
&
amfAudioConvert
,
},
{
wave_parserW
,
&
CLSID_WAVEParser
,
wave_parser_create
,
NULL
,
&
wave_parser_filter_data
,
},
};
const
int
g_cTemplates
=
ARRAY_SIZE
(
g_Templates
);
...
...
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