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
4f72fbef
Commit
4f72fbef
authored
Mar 07, 2021
by
Zebediah Figura
Committed by
Alexandre Julliard
Mar 09, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
strmbase: Merge qualitycontrol.c into renderer.c.
Signed-off-by:
Zebediah Figura
<
z.figura12@gmail.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
b67e9ddb
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
326 additions
and
326 deletions
+326
-326
Makefile.in
dlls/strmbase/Makefile.in
+0
-1
qualitycontrol.c
dlls/strmbase/qualitycontrol.c
+0
-317
renderer.c
dlls/strmbase/renderer.c
+326
-0
strmbase_private.h
dlls/strmbase/strmbase_private.h
+0
-5
Makefile.in
dlls/wineqtdecoder/Makefile.in
+0
-1
strmbase.h
include/wine/strmbase.h
+0
-2
No files found.
dlls/strmbase/Makefile.in
View file @
4f72fbef
...
...
@@ -7,6 +7,5 @@ C_SRCS = \
outputqueue.c
\
pin.c
\
pospass.c
\
qualitycontrol.c
\
renderer.c
\
seeking.c
dlls/strmbase/qualitycontrol.c
deleted
100644 → 0
View file @
b67e9ddb
/*
* Quality Control Interfaces
*
* Copyright 2010 Maarten Lankhorst for CodeWeavers
*
* rendering qos functions based on, the original can be found at
* gstreamer/libs/gst/base/gstbasesink.c which has copyright notice:
*
* Copyright (C) 2005-2007 Wim Taymans <wim.taymans@gmail.com>
*
* 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 "strmbase_private.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
strmbase_qc
);
static
inline
struct
strmbase_qc
*
impl_from_IQualityControl
(
IQualityControl
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
strmbase_qc
,
IQualityControl_iface
);
}
static
HRESULT
WINAPI
quality_control_QueryInterface
(
IQualityControl
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
struct
strmbase_qc
*
This
=
impl_from_IQualityControl
(
iface
);
return
IBaseFilter_QueryInterface
(
&
This
->
pin
->
filter
->
IBaseFilter_iface
,
riid
,
ppv
);
}
static
ULONG
WINAPI
quality_control_AddRef
(
IQualityControl
*
iface
)
{
struct
strmbase_qc
*
This
=
impl_from_IQualityControl
(
iface
);
return
IBaseFilter_AddRef
(
&
This
->
pin
->
filter
->
IBaseFilter_iface
);
}
static
ULONG
WINAPI
quality_control_Release
(
IQualityControl
*
iface
)
{
struct
strmbase_qc
*
This
=
impl_from_IQualityControl
(
iface
);
return
IBaseFilter_Release
(
&
This
->
pin
->
filter
->
IBaseFilter_iface
);
}
static
HRESULT
WINAPI
quality_control_Notify
(
IQualityControl
*
iface
,
IBaseFilter
*
sender
,
Quality
qm
)
{
struct
strmbase_qc
*
This
=
impl_from_IQualityControl
(
iface
);
HRESULT
hr
=
S_FALSE
;
TRACE
(
"iface %p, sender %p, type %#x, proportion %u, late %s, timestamp %s.
\n
"
,
iface
,
sender
,
qm
.
Type
,
qm
.
Proportion
,
debugstr_time
(
qm
.
Late
),
debugstr_time
(
qm
.
TimeStamp
));
if
(
This
->
tonotify
)
return
IQualityControl_Notify
(
This
->
tonotify
,
&
This
->
pin
->
filter
->
IBaseFilter_iface
,
qm
);
if
(
This
->
pin
->
peer
)
{
IQualityControl
*
qc
=
NULL
;
IPin_QueryInterface
(
This
->
pin
->
peer
,
&
IID_IQualityControl
,
(
void
**
)
&
qc
);
if
(
qc
)
{
hr
=
IQualityControl_Notify
(
qc
,
&
This
->
pin
->
filter
->
IBaseFilter_iface
,
qm
);
IQualityControl_Release
(
qc
);
}
}
return
hr
;
}
static
HRESULT
WINAPI
quality_control_SetSink
(
IQualityControl
*
iface
,
IQualityControl
*
tonotify
)
{
struct
strmbase_qc
*
This
=
impl_from_IQualityControl
(
iface
);
TRACE
(
"%p %p
\n
"
,
This
,
tonotify
);
This
->
tonotify
=
tonotify
;
return
S_OK
;
}
static
const
IQualityControlVtbl
quality_control_vtbl
=
{
quality_control_QueryInterface
,
quality_control_AddRef
,
quality_control_Release
,
quality_control_Notify
,
quality_control_SetSink
,
};
/* Macros copied from gstreamer, weighted average between old average and new ones */
#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
/* generic running average, this has a neutral window size */
#define UPDATE_RUNNING_AVG(avg,val) DO_RUNNING_AVG(avg,val,8)
/* the windows for these running averages are experimentally obtained.
* positive values get averaged more while negative values use a small
* window so we can react faster to badness. */
#define UPDATE_RUNNING_AVG_P(avg,val) DO_RUNNING_AVG(avg,val,16)
#define UPDATE_RUNNING_AVG_N(avg,val) DO_RUNNING_AVG(avg,val,4)
void
QualityControlRender_Start
(
struct
strmbase_qc
*
This
,
REFERENCE_TIME
tStart
)
{
This
->
avg_render
=
This
->
last_in_time
=
This
->
last_left
=
This
->
avg_duration
=
This
->
avg_pt
=
-
1
;
This
->
clockstart
=
tStart
;
This
->
avg_rate
=
-
1
.
0
;
This
->
rendered
=
This
->
dropped
=
0
;
This
->
is_dropped
=
FALSE
;
This
->
qos_handled
=
TRUE
;
/* Lie that will be corrected on first adjustment */
}
static
BOOL
QualityControlRender_IsLate
(
struct
strmbase_qc
*
This
,
REFERENCE_TIME
jitter
,
REFERENCE_TIME
start
,
REFERENCE_TIME
stop
)
{
REFERENCE_TIME
max_lateness
=
200000
;
TRACE
(
"jitter %s, start %s, stop %s.
\n
"
,
debugstr_time
(
jitter
),
debugstr_time
(
start
),
debugstr_time
(
stop
));
/* we can add a valid stop time */
if
(
stop
>=
start
)
max_lateness
+=
stop
;
else
max_lateness
+=
start
;
/* if the jitter bigger than duration and lateness we are too late */
if
(
start
+
jitter
>
max_lateness
)
{
WARN
(
"buffer is too late %i > %i
\n
"
,
(
int
)((
start
+
jitter
)
/
10000
),
(
int
)(
max_lateness
/
10000
));
/* !!emergency!!, if we did not receive anything valid for more than a
* second, render it anyway so the user sees something */
if
(
This
->
last_in_time
<
0
||
start
-
This
->
last_in_time
<
10000000
)
return
TRUE
;
FIXME
(
"A lot of buffers are being dropped.
\n
"
);
FIXME
(
"There may be a timestamping problem, or this computer is too slow.
\n
"
);
}
This
->
last_in_time
=
start
;
return
FALSE
;
}
void
QualityControlRender_DoQOS
(
struct
strmbase_qc
*
priv
)
{
REFERENCE_TIME
start
,
stop
,
jitter
,
pt
,
entered
,
left
,
duration
;
double
rate
;
TRACE
(
"%p
\n
"
,
priv
);
if
(
!
priv
->
pin
->
filter
->
clock
||
priv
->
current_rstart
<
0
)
return
;
start
=
priv
->
current_rstart
;
stop
=
priv
->
current_rstop
;
jitter
=
priv
->
current_jitter
;
if
(
jitter
<
0
)
{
/* this is the time the buffer entered the sink */
if
(
start
<
-
jitter
)
entered
=
0
;
else
entered
=
start
+
jitter
;
left
=
start
;
}
else
{
/* this is the time the buffer entered the sink */
entered
=
start
+
jitter
;
/* this is the time the buffer left the sink */
left
=
start
+
jitter
;
}
/* calculate duration of the buffer */
if
(
stop
>=
start
)
duration
=
stop
-
start
;
else
duration
=
0
;
/* if we have the time when the last buffer left us, calculate
* processing time */
if
(
priv
->
last_left
>=
0
)
{
if
(
entered
>
priv
->
last_left
)
{
pt
=
entered
-
priv
->
last_left
;
}
else
{
pt
=
0
;
}
}
else
{
pt
=
priv
->
avg_pt
;
}
TRACE
(
"start %s, entered %s, left %s, pt %s, duration %s, jitter %s.
\n
"
,
debugstr_time
(
start
),
debugstr_time
(
entered
),
debugstr_time
(
left
),
debugstr_time
(
pt
),
debugstr_time
(
duration
),
debugstr_time
(
jitter
));
TRACE
(
"average duration %s, average pt %s, average rate %.16e.
\n
"
,
debugstr_time
(
priv
->
avg_duration
),
debugstr_time
(
priv
->
avg_pt
),
priv
->
avg_rate
);
/* collect running averages. for first observations, we copy the
* values */
if
(
priv
->
avg_duration
<
0
)
priv
->
avg_duration
=
duration
;
else
priv
->
avg_duration
=
UPDATE_RUNNING_AVG
(
priv
->
avg_duration
,
duration
);
if
(
priv
->
avg_pt
<
0
)
priv
->
avg_pt
=
pt
;
else
priv
->
avg_pt
=
UPDATE_RUNNING_AVG
(
priv
->
avg_pt
,
pt
);
if
(
priv
->
avg_duration
!=
0
)
rate
=
(
double
)
priv
->
avg_pt
/
(
double
)
priv
->
avg_duration
;
else
rate
=
0
.
0
;
if
(
priv
->
last_left
>=
0
)
{
if
(
priv
->
is_dropped
||
priv
->
avg_rate
<
0
.
0
)
{
priv
->
avg_rate
=
rate
;
}
else
{
if
(
rate
>
1
.
0
)
priv
->
avg_rate
=
UPDATE_RUNNING_AVG_N
(
priv
->
avg_rate
,
rate
);
else
priv
->
avg_rate
=
UPDATE_RUNNING_AVG_P
(
priv
->
avg_rate
,
rate
);
}
}
if
(
priv
->
avg_rate
>=
0
.
0
)
{
HRESULT
hr
;
Quality
q
;
/* if we have a valid rate, start sending QoS messages */
if
(
priv
->
current_jitter
<
0
)
{
/* make sure we never go below 0 when adding the jitter to the
* timestamp. */
if
(
priv
->
current_rstart
<
-
priv
->
current_jitter
)
priv
->
current_jitter
=
-
priv
->
current_rstart
;
}
else
priv
->
current_jitter
+=
(
priv
->
current_rstop
-
priv
->
current_rstart
);
q
.
Type
=
(
jitter
>
0
?
Famine
:
Flood
);
q
.
Proportion
=
(
LONG
)(
1000
.
/
priv
->
avg_rate
);
if
(
q
.
Proportion
<
200
)
q
.
Proportion
=
200
;
else
if
(
q
.
Proportion
>
5000
)
q
.
Proportion
=
5000
;
q
.
Late
=
priv
->
current_jitter
;
q
.
TimeStamp
=
priv
->
current_rstart
;
TRACE
(
"Late: %s from %s, rate: %g
\n
"
,
debugstr_time
(
q
.
Late
),
debugstr_time
(
q
.
TimeStamp
),
1
.
/
priv
->
avg_rate
);
hr
=
IQualityControl_Notify
(
&
priv
->
IQualityControl_iface
,
&
priv
->
pin
->
filter
->
IBaseFilter_iface
,
q
);
priv
->
qos_handled
=
hr
==
S_OK
;
}
/* record when this buffer will leave us */
priv
->
last_left
=
left
;
}
void
QualityControlRender_BeginRender
(
struct
strmbase_qc
*
This
,
REFERENCE_TIME
start
,
REFERENCE_TIME
stop
)
{
This
->
start
=
-
1
;
This
->
current_rstart
=
start
;
This
->
current_rstop
=
max
(
stop
,
start
);
if
(
start
>=
0
)
{
REFERENCE_TIME
now
;
IReferenceClock_GetTime
(
This
->
pin
->
filter
->
clock
,
&
now
);
This
->
current_jitter
=
(
now
-
This
->
clockstart
)
-
start
;
}
else
This
->
current_jitter
=
0
;
/* FIXME: This isn't correct; we don't drop samples, nor should. */
This
->
is_dropped
=
QualityControlRender_IsLate
(
This
,
This
->
current_jitter
,
start
,
stop
);
TRACE
(
"dropped %d, start %s, stop %s, jitter %s.
\n
"
,
This
->
is_dropped
,
debugstr_time
(
start
),
debugstr_time
(
stop
),
debugstr_time
(
This
->
current_jitter
));
if
(
This
->
is_dropped
)
This
->
dropped
++
;
else
This
->
rendered
++
;
if
(
!
This
->
pin
->
filter
->
clock
)
return
;
IReferenceClock_GetTime
(
This
->
pin
->
filter
->
clock
,
&
This
->
start
);
TRACE
(
"Starting at %s.
\n
"
,
debugstr_time
(
This
->
start
));
}
void
QualityControlRender_EndRender
(
struct
strmbase_qc
*
This
)
{
REFERENCE_TIME
elapsed
;
TRACE
(
"%p
\n
"
,
This
);
if
(
!
This
->
pin
->
filter
->
clock
||
This
->
start
<
0
||
FAILED
(
IReferenceClock_GetTime
(
This
->
pin
->
filter
->
clock
,
&
This
->
stop
)))
return
;
elapsed
=
This
->
start
-
This
->
stop
;
if
(
elapsed
<
0
)
return
;
if
(
This
->
avg_render
<
0
)
This
->
avg_render
=
elapsed
;
else
This
->
avg_render
=
UPDATE_RUNNING_AVG
(
This
->
avg_render
,
elapsed
);
}
void
strmbase_qc_init
(
struct
strmbase_qc
*
qc
,
struct
strmbase_pin
*
pin
)
{
memset
(
qc
,
0
,
sizeof
(
*
qc
));
qc
->
pin
=
pin
;
qc
->
current_rstart
=
qc
->
current_rstop
=
-
1
;
qc
->
IQualityControl_iface
.
lpVtbl
=
&
quality_control_vtbl
;
}
dlls/strmbase/renderer.c
View file @
4f72fbef
...
...
@@ -22,6 +22,257 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
strmbase
);
/* The following quality-of-service code is based on GstBaseSink QoS code, which
* is covered by the following copyright information:
*
* GStreamer
* Copyright (C) 2005-2007 Wim Taymans <wim.taymans@gmail.com>
*
* gstbasesink.c: Base class for sink elements
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
/* Generic running average; this has a neutral window size. */
#define UPDATE_RUNNING_AVG(avg,val) DO_RUNNING_AVG(avg,val,8)
/* The windows for these running averages are experimentally obtained.
* Positive values get averaged more, while negative values use a small
* window so we can react faster to badness. */
#define UPDATE_RUNNING_AVG_P(avg,val) DO_RUNNING_AVG(avg,val,16)
#define UPDATE_RUNNING_AVG_N(avg,val) DO_RUNNING_AVG(avg,val,4)
static
void
QualityControlRender_Start
(
struct
strmbase_qc
*
This
,
REFERENCE_TIME
tStart
)
{
This
->
avg_render
=
This
->
last_in_time
=
This
->
last_left
=
This
->
avg_duration
=
This
->
avg_pt
=
-
1
;
This
->
clockstart
=
tStart
;
This
->
avg_rate
=
-
1
.
0
;
This
->
rendered
=
This
->
dropped
=
0
;
This
->
is_dropped
=
FALSE
;
This
->
qos_handled
=
TRUE
;
/* Lie that will be corrected on first adjustment */
}
static
BOOL
QualityControlRender_IsLate
(
struct
strmbase_qc
*
This
,
REFERENCE_TIME
jitter
,
REFERENCE_TIME
start
,
REFERENCE_TIME
stop
)
{
REFERENCE_TIME
max_lateness
=
200000
;
TRACE
(
"jitter %s, start %s, stop %s.
\n
"
,
debugstr_time
(
jitter
),
debugstr_time
(
start
),
debugstr_time
(
stop
));
/* we can add a valid stop time */
if
(
stop
>=
start
)
max_lateness
+=
stop
;
else
max_lateness
+=
start
;
/* if the jitter bigger than duration and lateness we are too late */
if
(
start
+
jitter
>
max_lateness
)
{
WARN
(
"buffer is too late %i > %i
\n
"
,
(
int
)((
start
+
jitter
)
/
10000
),
(
int
)(
max_lateness
/
10000
));
/* !!emergency!!, if we did not receive anything valid for more than a
* second, render it anyway so the user sees something */
if
(
This
->
last_in_time
<
0
||
start
-
This
->
last_in_time
<
10000000
)
return
TRUE
;
FIXME
(
"A lot of buffers are being dropped.
\n
"
);
FIXME
(
"There may be a timestamping problem, or this computer is too slow.
\n
"
);
}
This
->
last_in_time
=
start
;
return
FALSE
;
}
static
void
QualityControlRender_DoQOS
(
struct
strmbase_qc
*
priv
)
{
REFERENCE_TIME
start
,
stop
,
jitter
,
pt
,
entered
,
left
,
duration
;
double
rate
;
TRACE
(
"%p
\n
"
,
priv
);
if
(
!
priv
->
pin
->
filter
->
clock
||
priv
->
current_rstart
<
0
)
return
;
start
=
priv
->
current_rstart
;
stop
=
priv
->
current_rstop
;
jitter
=
priv
->
current_jitter
;
if
(
jitter
<
0
)
{
/* This is the time the buffer entered the sink. */
if
(
start
<
-
jitter
)
entered
=
0
;
else
entered
=
start
+
jitter
;
left
=
start
;
}
else
{
/* This is the time the buffer entered the sink. */
entered
=
start
+
jitter
;
/* This is the time the buffer left the sink. */
left
=
start
+
jitter
;
}
/* Calculate the duration of the buffer. */
if
(
stop
>=
start
)
duration
=
stop
-
start
;
else
duration
=
0
;
/* If we have the time when the last buffer left us, calculate processing
* time. */
if
(
priv
->
last_left
>=
0
)
{
if
(
entered
>
priv
->
last_left
)
pt
=
entered
-
priv
->
last_left
;
else
pt
=
0
;
}
else
{
pt
=
priv
->
avg_pt
;
}
TRACE
(
"start %s, entered %s, left %s, pt %s, duration %s, jitter %s.
\n
"
,
debugstr_time
(
start
),
debugstr_time
(
entered
),
debugstr_time
(
left
),
debugstr_time
(
pt
),
debugstr_time
(
duration
),
debugstr_time
(
jitter
));
TRACE
(
"average duration %s, average pt %s, average rate %.16e.
\n
"
,
debugstr_time
(
priv
->
avg_duration
),
debugstr_time
(
priv
->
avg_pt
),
priv
->
avg_rate
);
/* Collect running averages. For first observations, we copy the values. */
if
(
priv
->
avg_duration
<
0
)
priv
->
avg_duration
=
duration
;
else
priv
->
avg_duration
=
UPDATE_RUNNING_AVG
(
priv
->
avg_duration
,
duration
);
if
(
priv
->
avg_pt
<
0
)
priv
->
avg_pt
=
pt
;
else
priv
->
avg_pt
=
UPDATE_RUNNING_AVG
(
priv
->
avg_pt
,
pt
);
if
(
priv
->
avg_duration
!=
0
)
rate
=
(
double
)
priv
->
avg_pt
/
(
double
)
priv
->
avg_duration
;
else
rate
=
0
.
0
;
if
(
priv
->
last_left
>=
0
)
{
if
(
priv
->
is_dropped
||
priv
->
avg_rate
<
0
.
0
)
{
priv
->
avg_rate
=
rate
;
}
else
{
if
(
rate
>
1
.
0
)
priv
->
avg_rate
=
UPDATE_RUNNING_AVG_N
(
priv
->
avg_rate
,
rate
);
else
priv
->
avg_rate
=
UPDATE_RUNNING_AVG_P
(
priv
->
avg_rate
,
rate
);
}
}
if
(
priv
->
avg_rate
>=
0
.
0
)
{
HRESULT
hr
;
Quality
q
;
/* If we have a valid rate, start sending QoS messages. */
if
(
priv
->
current_jitter
<
0
)
{
/* Make sure we never go below 0 when adding the jitter to the
* timestamp. */
if
(
priv
->
current_rstart
<
-
priv
->
current_jitter
)
priv
->
current_jitter
=
-
priv
->
current_rstart
;
}
else
{
priv
->
current_jitter
+=
(
priv
->
current_rstop
-
priv
->
current_rstart
);
}
q
.
Type
=
(
jitter
>
0
?
Famine
:
Flood
);
q
.
Proportion
=
1000
.
0
/
priv
->
avg_rate
;
if
(
q
.
Proportion
<
200
)
q
.
Proportion
=
200
;
else
if
(
q
.
Proportion
>
5000
)
q
.
Proportion
=
5000
;
q
.
Late
=
priv
->
current_jitter
;
q
.
TimeStamp
=
priv
->
current_rstart
;
hr
=
IQualityControl_Notify
(
&
priv
->
IQualityControl_iface
,
&
priv
->
pin
->
filter
->
IBaseFilter_iface
,
q
);
priv
->
qos_handled
=
hr
==
S_OK
;
}
/* Record when this buffer will leave us. */
priv
->
last_left
=
left
;
}
static
void
QualityControlRender_BeginRender
(
struct
strmbase_qc
*
This
,
REFERENCE_TIME
start
,
REFERENCE_TIME
stop
)
{
This
->
start
=
-
1
;
This
->
current_rstart
=
start
;
This
->
current_rstop
=
max
(
stop
,
start
);
if
(
start
>=
0
)
{
REFERENCE_TIME
now
;
IReferenceClock_GetTime
(
This
->
pin
->
filter
->
clock
,
&
now
);
This
->
current_jitter
=
(
now
-
This
->
clockstart
)
-
start
;
}
else
{
This
->
current_jitter
=
0
;
}
/* FIXME: This isn't correct; we don't drop samples, nor should. */
This
->
is_dropped
=
QualityControlRender_IsLate
(
This
,
This
->
current_jitter
,
start
,
stop
);
TRACE
(
"dropped %d, start %s, stop %s, jitter %s.
\n
"
,
This
->
is_dropped
,
debugstr_time
(
start
),
debugstr_time
(
stop
),
debugstr_time
(
This
->
current_jitter
));
if
(
This
->
is_dropped
)
This
->
dropped
++
;
else
This
->
rendered
++
;
if
(
!
This
->
pin
->
filter
->
clock
)
return
;
IReferenceClock_GetTime
(
This
->
pin
->
filter
->
clock
,
&
This
->
start
);
TRACE
(
"Starting at %s.
\n
"
,
debugstr_time
(
This
->
start
));
}
static
void
QualityControlRender_EndRender
(
struct
strmbase_qc
*
This
)
{
REFERENCE_TIME
elapsed
;
TRACE
(
"%p
\n
"
,
This
);
if
(
!
This
->
pin
->
filter
->
clock
||
This
->
start
<
0
||
FAILED
(
IReferenceClock_GetTime
(
This
->
pin
->
filter
->
clock
,
&
This
->
stop
)))
return
;
elapsed
=
This
->
start
-
This
->
stop
;
if
(
elapsed
<
0
)
return
;
if
(
This
->
avg_render
<
0
)
This
->
avg_render
=
elapsed
;
else
This
->
avg_render
=
UPDATE_RUNNING_AVG
(
This
->
avg_render
,
elapsed
);
}
static
inline
struct
strmbase_renderer
*
impl_from_strmbase_filter
(
struct
strmbase_filter
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
strmbase_renderer
,
filter
);
...
...
@@ -319,6 +570,73 @@ static const struct strmbase_sink_ops sink_ops =
.
sink_end_flush
=
sink_end_flush
,
};
static
struct
strmbase_qc
*
impl_from_IQualityControl
(
IQualityControl
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
strmbase_qc
,
IQualityControl_iface
);
}
static
HRESULT
WINAPI
quality_control_QueryInterface
(
IQualityControl
*
iface
,
REFIID
iid
,
void
**
out
)
{
struct
strmbase_qc
*
qc
=
impl_from_IQualityControl
(
iface
);
return
IBaseFilter_QueryInterface
(
&
qc
->
pin
->
filter
->
IBaseFilter_iface
,
iid
,
out
);
}
static
ULONG
WINAPI
quality_control_AddRef
(
IQualityControl
*
iface
)
{
struct
strmbase_qc
*
qc
=
impl_from_IQualityControl
(
iface
);
return
IBaseFilter_AddRef
(
&
qc
->
pin
->
filter
->
IBaseFilter_iface
);
}
static
ULONG
WINAPI
quality_control_Release
(
IQualityControl
*
iface
)
{
struct
strmbase_qc
*
qc
=
impl_from_IQualityControl
(
iface
);
return
IBaseFilter_Release
(
&
qc
->
pin
->
filter
->
IBaseFilter_iface
);
}
static
HRESULT
WINAPI
quality_control_Notify
(
IQualityControl
*
iface
,
IBaseFilter
*
sender
,
Quality
q
)
{
struct
strmbase_qc
*
qc
=
impl_from_IQualityControl
(
iface
);
HRESULT
hr
=
S_FALSE
;
TRACE
(
"iface %p, sender %p, type %#x, proportion %u, late %s, timestamp %s.
\n
"
,
iface
,
sender
,
q
.
Type
,
q
.
Proportion
,
debugstr_time
(
q
.
Late
),
debugstr_time
(
q
.
TimeStamp
));
if
(
qc
->
tonotify
)
return
IQualityControl_Notify
(
qc
->
tonotify
,
&
qc
->
pin
->
filter
->
IBaseFilter_iface
,
q
);
if
(
qc
->
pin
->
peer
)
{
IQualityControl
*
peer_qc
=
NULL
;
IPin_QueryInterface
(
qc
->
pin
->
peer
,
&
IID_IQualityControl
,
(
void
**
)
&
peer_qc
);
if
(
peer_qc
)
{
hr
=
IQualityControl_Notify
(
peer_qc
,
&
qc
->
pin
->
filter
->
IBaseFilter_iface
,
q
);
IQualityControl_Release
(
peer_qc
);
}
}
return
hr
;
}
static
HRESULT
WINAPI
quality_control_SetSink
(
IQualityControl
*
iface
,
IQualityControl
*
sink
)
{
struct
strmbase_qc
*
qc
=
impl_from_IQualityControl
(
iface
);
TRACE
(
"iface %p, sink %p.
\n
"
,
iface
,
sink
);
qc
->
tonotify
=
sink
;
return
S_OK
;
}
static
const
IQualityControlVtbl
quality_control_vtbl
=
{
quality_control_QueryInterface
,
quality_control_AddRef
,
quality_control_Release
,
quality_control_Notify
,
quality_control_SetSink
,
};
void
strmbase_renderer_cleanup
(
struct
strmbase_renderer
*
filter
)
{
if
(
filter
->
sink
.
pin
.
peer
)
...
...
@@ -334,6 +652,14 @@ void strmbase_renderer_cleanup(struct strmbase_renderer *filter)
strmbase_filter_cleanup
(
&
filter
->
filter
);
}
static
void
strmbase_qc_init
(
struct
strmbase_qc
*
qc
,
struct
strmbase_pin
*
pin
)
{
memset
(
qc
,
0
,
sizeof
(
*
qc
));
qc
->
pin
=
pin
;
qc
->
current_rstart
=
qc
->
current_rstop
=
-
1
;
qc
->
IQualityControl_iface
.
lpVtbl
=
&
quality_control_vtbl
;
}
void
strmbase_renderer_init
(
struct
strmbase_renderer
*
filter
,
IUnknown
*
outer
,
const
CLSID
*
clsid
,
const
WCHAR
*
sink_name
,
const
struct
strmbase_renderer_ops
*
ops
)
{
...
...
dlls/strmbase/strmbase_private.h
View file @
4f72fbef
...
...
@@ -53,9 +53,4 @@ static inline const char *debugstr_time(REFERENCE_TIME time)
return
wine_dbg_sprintf
(
"%s"
,
rev
);
}
void
QualityControlRender_Start
(
struct
strmbase_qc
*
This
,
REFERENCE_TIME
tStart
);
void
QualityControlRender_DoQOS
(
struct
strmbase_qc
*
priv
);
void
QualityControlRender_BeginRender
(
struct
strmbase_qc
*
This
,
REFERENCE_TIME
start
,
REFERENCE_TIME
stop
);
void
QualityControlRender_EndRender
(
struct
strmbase_qc
*
This
);
#endif
/* __WINE_STRMBASE_PRIVATE_H */
dlls/wineqtdecoder/Makefile.in
View file @
4f72fbef
...
...
@@ -13,7 +13,6 @@ C_SRCS = \
qtsplitter.c
\
qtutils.c
\
qtvdecoder.c
\
qualitycontrol.c
\
seeking.c
RC_SRCS
=
\
...
...
include/wine/strmbase.h
View file @
4f72fbef
...
...
@@ -286,8 +286,6 @@ struct strmbase_qc
BOOL
qos_handled
,
is_dropped
;
};
void
strmbase_qc_init
(
struct
strmbase_qc
*
qc
,
struct
strmbase_pin
*
pin
);
struct
strmbase_renderer
{
struct
strmbase_filter
filter
;
...
...
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