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
419be239
Commit
419be239
authored
May 31, 2015
by
Damjan Jovanovic
Committed by
Alexandre Julliard
Jun 02, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
qcap: Get the SmartTee filter to a minimally functional level.
parent
95c2b22c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
161 additions
and
16 deletions
+161
-16
smartteefilter.c
dlls/qcap/smartteefilter.c
+153
-8
smartteefilter.c
dlls/qcap/tests/smartteefilter.c
+8
-8
No files found.
dlls/qcap/smartteefilter.c
View file @
419be239
...
...
@@ -147,8 +147,13 @@ static ULONG WINAPI SmartTeeFilter_Release(IBaseFilter *iface)
static
HRESULT
WINAPI
SmartTeeFilter_Stop
(
IBaseFilter
*
iface
)
{
SmartTeeFilter
*
This
=
impl_from_IBaseFilter
(
iface
);
FIXME
(
"(%p): stub
\n
"
,
This
);
return
E_NOTIMPL
;
TRACE
(
"(%p)
\n
"
,
This
);
EnterCriticalSection
(
&
This
->
filter
.
csFilter
);
if
(
This
->
filter
.
state
!=
State_Stopped
)
{
This
->
filter
.
state
=
State_Stopped
;
}
LeaveCriticalSection
(
&
This
->
filter
.
csFilter
);
return
S_OK
;
}
static
HRESULT
WINAPI
SmartTeeFilter_Pause
(
IBaseFilter
*
iface
)
...
...
@@ -160,14 +165,40 @@ static HRESULT WINAPI SmartTeeFilter_Pause(IBaseFilter *iface)
static
HRESULT
WINAPI
SmartTeeFilter_Run
(
IBaseFilter
*
iface
,
REFERENCE_TIME
tStart
)
{
FIXME
(
"(%p, %x%08x): stub
\n
"
,
iface
,
(
ULONG
)(
tStart
>>
32
),
(
ULONG
)
tStart
);
return
E_NOTIMPL
;
SmartTeeFilter
*
This
=
impl_from_IBaseFilter
(
iface
);
HRESULT
hr
=
S_OK
;
TRACE
(
"(%p, %x%08x)
\n
"
,
This
,
(
ULONG
)(
tStart
>>
32
),
(
ULONG
)
tStart
);
EnterCriticalSection
(
&
This
->
filter
.
csFilter
);
if
(
This
->
filter
.
state
!=
State_Running
)
{
/* We share an allocator among all pins, an allocator can only get committed
* once, state transitions occur in upstream order, and only output pins
* commit allocators, so let the filter attached to the input pin worry about it. */
if
(
This
->
input
->
pin
.
pConnectedTo
)
This
->
filter
.
state
=
State_Running
;
else
hr
=
VFW_E_NOT_CONNECTED
;
}
LeaveCriticalSection
(
&
This
->
filter
.
csFilter
);
return
hr
;
}
static
HRESULT
WINAPI
SmartTeeFilter_FindPin
(
IBaseFilter
*
iface
,
LPCWSTR
Id
,
IPin
**
ppPin
)
{
SmartTeeFilter
*
This
=
impl_from_IBaseFilter
(
iface
);
FIXME
(
"(%p)->(%s, %p): stub
\n
"
,
This
,
debugstr_w
(
Id
),
ppPin
);
TRACE
(
"(%p)->(%s, %p)
\n
"
,
This
,
debugstr_w
(
Id
),
ppPin
);
if
(
lstrcmpW
(
Id
,
This
->
input
->
pin
.
pinInfo
.
achName
)
==
0
)
{
*
ppPin
=
&
This
->
input
->
pin
.
IPin_iface
;
IPin_AddRef
(
*
ppPin
);
return
S_OK
;
}
else
if
(
lstrcmpW
(
Id
,
This
->
capture
->
pin
.
pinInfo
.
achName
)
==
0
)
{
*
ppPin
=
&
This
->
capture
->
pin
.
IPin_iface
;
IPin_AddRef
(
*
ppPin
);
return
S_OK
;
}
else
if
(
lstrcmpW
(
Id
,
This
->
preview
->
pin
.
pinInfo
.
achName
)
==
0
)
{
*
ppPin
=
&
This
->
preview
->
pin
.
IPin_iface
;
IPin_AddRef
(
*
ppPin
);
return
S_OK
;
}
return
VFW_E_NOT_FOUND
;
}
...
...
@@ -292,11 +323,125 @@ static HRESULT WINAPI SmartTeeFilterInput_GetMediaType(BasePin *base, int iPosit
return
hr
;
}
static
HRESULT
WINAPI
SmartTeeFilterInput_Receive
(
BaseInputPin
*
base
,
IMediaSample
*
pSample
)
static
HRESULT
copy_sample
(
IMediaSample
*
inputSample
,
IMemAllocator
*
allocator
,
IMediaSample
**
pOutputSample
)
{
REFERENCE_TIME
startTime
,
endTime
;
BOOL
haveStartTime
=
TRUE
,
haveEndTime
=
TRUE
;
IMediaSample
*
outputSample
=
NULL
;
BYTE
*
ptrIn
,
*
ptrOut
;
AM_MEDIA_TYPE
*
mediaType
=
NULL
;
HRESULT
hr
;
hr
=
IMediaSample_GetTime
(
inputSample
,
&
startTime
,
&
endTime
);
if
(
hr
==
S_OK
)
;
else
if
(
hr
==
VFW_S_NO_STOP_TIME
)
haveEndTime
=
FALSE
;
else
if
(
hr
==
VFW_E_SAMPLE_TIME_NOT_SET
)
haveStartTime
=
haveEndTime
=
FALSE
;
else
goto
end
;
hr
=
IMemAllocator_GetBuffer
(
allocator
,
&
outputSample
,
haveStartTime
?
&
startTime
:
NULL
,
haveEndTime
?
&
endTime
:
NULL
,
0
);
if
(
FAILED
(
hr
))
goto
end
;
if
(
IMediaSample_GetSize
(
outputSample
)
<
IMediaSample_GetActualDataLength
(
inputSample
))
{
ERR
(
"insufficient space in sample
\n
"
);
hr
=
VFW_E_BUFFER_OVERFLOW
;
goto
end
;
}
hr
=
IMediaSample_SetTime
(
outputSample
,
haveStartTime
?
&
startTime
:
NULL
,
haveEndTime
?
&
endTime
:
NULL
);
if
(
FAILED
(
hr
))
goto
end
;
hr
=
IMediaSample_GetPointer
(
inputSample
,
&
ptrIn
);
if
(
FAILED
(
hr
))
goto
end
;
hr
=
IMediaSample_GetPointer
(
outputSample
,
&
ptrOut
);
if
(
FAILED
(
hr
))
goto
end
;
memcpy
(
ptrOut
,
ptrIn
,
IMediaSample_GetActualDataLength
(
inputSample
));
IMediaSample_SetActualDataLength
(
outputSample
,
IMediaSample_GetActualDataLength
(
inputSample
));
hr
=
IMediaSample_SetDiscontinuity
(
outputSample
,
IMediaSample_IsDiscontinuity
(
inputSample
)
==
S_OK
);
if
(
FAILED
(
hr
))
goto
end
;
haveStartTime
=
haveEndTime
=
TRUE
;
hr
=
IMediaSample_GetMediaTime
(
inputSample
,
&
startTime
,
&
endTime
);
if
(
hr
==
S_OK
)
;
else
if
(
hr
==
VFW_S_NO_STOP_TIME
)
haveEndTime
=
FALSE
;
else
if
(
hr
==
VFW_E_MEDIA_TIME_NOT_SET
)
haveStartTime
=
haveEndTime
=
FALSE
;
else
goto
end
;
hr
=
IMediaSample_SetMediaTime
(
outputSample
,
haveStartTime
?
&
startTime
:
NULL
,
haveEndTime
?
&
endTime
:
NULL
);
if
(
FAILED
(
hr
))
goto
end
;
hr
=
IMediaSample_GetMediaType
(
inputSample
,
&
mediaType
);
if
(
FAILED
(
hr
))
goto
end
;
if
(
hr
==
S_OK
)
{
hr
=
IMediaSample_SetMediaType
(
outputSample
,
mediaType
);
if
(
FAILED
(
hr
))
goto
end
;
}
hr
=
IMediaSample_SetPreroll
(
outputSample
,
IMediaSample_IsPreroll
(
inputSample
)
==
S_OK
);
if
(
FAILED
(
hr
))
goto
end
;
hr
=
IMediaSample_SetSyncPoint
(
outputSample
,
IMediaSample_IsSyncPoint
(
inputSample
)
==
S_OK
);
if
(
FAILED
(
hr
))
goto
end
;
end:
if
(
mediaType
)
DeleteMediaType
(
mediaType
);
if
(
FAILED
(
hr
)
&&
outputSample
)
{
IMediaSample_Release
(
outputSample
);
outputSample
=
NULL
;
}
*
pOutputSample
=
outputSample
;
return
hr
;
}
static
HRESULT
WINAPI
SmartTeeFilterInput_Receive
(
BaseInputPin
*
base
,
IMediaSample
*
inputSample
)
{
SmartTeeFilter
*
This
=
impl_from_BasePin
(
&
base
->
pin
);
FIXME
(
"(%p)->(%p): stub
\n
"
,
This
,
pSample
);
return
E_NOTIMPL
;
IMediaSample
*
captureSample
=
NULL
;
IMediaSample
*
previewSample
=
NULL
;
HRESULT
hrCapture
=
VFW_E_NOT_CONNECTED
,
hrPreview
=
VFW_E_NOT_CONNECTED
;
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
inputSample
);
/* Modifying the image coming out of one pin doesn't modify the image
* coming out of the other. MSDN claims the filter doesn't copy,
* but unless it somehow uses copy-on-write, I just don't see how
* that's possible. */
/* FIXME: we should ideally do each of these in a separate thread */
EnterCriticalSection
(
&
This
->
filter
.
csFilter
);
if
(
This
->
capture
->
pin
.
pConnectedTo
)
hrCapture
=
copy_sample
(
inputSample
,
This
->
capture
->
pAllocator
,
&
captureSample
);
LeaveCriticalSection
(
&
This
->
filter
.
csFilter
);
if
(
SUCCEEDED
(
hrCapture
))
hrCapture
=
BaseOutputPinImpl_Deliver
(
This
->
capture
,
captureSample
);
if
(
captureSample
)
IMediaSample_Release
(
captureSample
);
EnterCriticalSection
(
&
This
->
filter
.
csFilter
);
if
(
This
->
preview
->
pin
.
pConnectedTo
)
hrPreview
=
copy_sample
(
inputSample
,
This
->
preview
->
pAllocator
,
&
previewSample
);
LeaveCriticalSection
(
&
This
->
filter
.
csFilter
);
/* No timestamps on preview stream: */
if
(
SUCCEEDED
(
hrPreview
))
hrPreview
=
IMediaSample_SetTime
(
previewSample
,
NULL
,
NULL
);
if
(
SUCCEEDED
(
hrPreview
))
hrPreview
=
BaseOutputPinImpl_Deliver
(
This
->
preview
,
previewSample
);
if
(
previewSample
)
IMediaSample_Release
(
previewSample
);
/* FIXME: how to merge the HRESULTs from the 2 pins? */
if
(
SUCCEEDED
(
hrCapture
))
return
hrCapture
;
else
return
hrPreview
;
}
static
const
BaseInputPinFuncTable
SmartTeeFilterInputFuncs
=
{
...
...
dlls/qcap/tests/smartteefilter.c
View file @
419be239
...
...
@@ -520,9 +520,9 @@ static HRESULT WINAPI SinkMemInputPin_GetAllocatorRequirements(IMemInputPin *ifa
static
HRESULT
WINAPI
SinkMemInputPin_Receive
(
IMemInputPin
*
iface
,
IMediaSample
*
pSample
)
{
SinkFilter
*
This
=
impl_from_SinkFilter_IMemInputPin
(
iface
)
;
ok
(
0
,
"SmartTeeFilter never calls IMemInputPin_Receive(), only IMemInputPin_ReceiveMultiple()
\n
"
);
return
IMemInputPin_Receive
(
This
->
nullRendererMemInputPin
,
pSample
);
LONG
samplesProcessed
;
todo_wine
ok
(
0
,
"SmartTeeFilter never calls IMemInputPin_Receive(), only IMemInputPin_ReceiveMultiple()
\n
"
);
return
IMemInputPin_Receive
Multiple
(
iface
,
&
pSample
,
1
,
&
samplesProcessed
);
}
static
HRESULT
WINAPI
SinkMemInputPin_ReceiveMultiple
(
IMemInputPin
*
iface
,
IMediaSample
**
pSamples
,
...
...
@@ -735,7 +735,7 @@ static DWORD WINAPI media_thread(LPVOID param)
}
hr
=
IMemInputPin_Receive
(
This
->
memInputPin
,
sample
);
todo_wine
ok
(
SUCCEEDED
(
hr
),
"delivering sample to SmartTeeFilter's Input pin failed, hr=0x%08x
\n
"
,
hr
);
ok
(
SUCCEEDED
(
hr
),
"delivering sample to SmartTeeFilter's Input pin failed, hr=0x%08x
\n
"
,
hr
);
IMediaSample_Release
(
sample
);
}
...
...
@@ -1364,14 +1364,14 @@ static void test_smart_tee_filter_in_graph(IBaseFilter *smartTeeFilter, IPin *in
break
;
}
if
(
previewSinkFilter
->
receiveThreadId
!=
0
&&
captureSinkFilter
->
receiveThreadId
!=
0
)
{
ok
(
sourceFilter
->
mediaThreadId
!=
captureSinkFilter
->
receiveThreadId
,
todo_wine
ok
(
sourceFilter
->
mediaThreadId
!=
captureSinkFilter
->
receiveThreadId
,
"sending thread should != capture receiving thread
\n
"
);
ok
(
sourceFilter
->
mediaThreadId
!=
previewSinkFilter
->
receiveThreadId
,
todo_wine
ok
(
sourceFilter
->
mediaThreadId
!=
previewSinkFilter
->
receiveThreadId
,
"sending thread should != preview receiving thread
\n
"
);
ok
(
captureSinkFilter
->
receiveThreadId
!=
previewSinkFilter
->
receiveThreadId
,
todo_wine
ok
(
captureSinkFilter
->
receiveThreadId
!=
previewSinkFilter
->
receiveThreadId
,
"capture receiving thread should != preview receiving thread"
);
}
else
{
todo_wine
ok
(
0
,
"timeout: threads did not receive sample in time
\n
"
);
ok
(
0
,
"timeout: threads did not receive sample in time
\n
"
);
}
IMediaControl_Stop
(
mediaControl
);
...
...
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