1
//------------------------------------------------------------------------------
4
// Desc: DirectShow base classes - implements helper classes for building
7
// Copyright (c) 1992-2004 Microsoft Corporation. All rights reserved.
8
//------------------------------------------------------------------------------
10
#include <pjmedia-videodev/config.h>
12
#if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
17
// Declare function from largeint.h we need so that PPC can build
21
// Enlarged integer divide - 64-bits / 32-bits > 32-bits
26
#define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
31
EnlargedUnsignedDivide (
32
IN ULARGE_INTEGER Dividend,
37
// return remainder if necessary
38
if (Remainder != NULL)
39
*Remainder = (ULONG)(LLtoU64(Dividend) % Divisor);
40
return (ULONG)(LLtoU64(Dividend) / Divisor);
47
EnlargedUnsignedDivide (
48
IN ULARGE_INTEGER Dividend,
55
mov eax,Dividend.LowPart
56
mov edx,Dividend.HighPart
70
/* Arithmetic functions to help with time format conversions
74
// work around bug in version 12.00.8385 of the alpha compiler where
75
// UInt32x32To64 sign-extends its arguments (?)
77
#define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff))
80
/* Compute (a * b + d) / c */
81
LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d)
83
/* Compute the absolute values to avoid signed arithmetic problems */
84
ULARGE_INTEGER ua, ub;
87
ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
88
ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b);
89
uc = (DWORDLONG)(c >= 0 ? c : -c);
90
BOOL bSign = (a < 0) ^ (b < 0);
92
/* Do long multiplication */
94
p[0].QuadPart = UInt32x32To64(ua.LowPart, ub.LowPart);
96
/* This next computation cannot overflow into p[1].HighPart because
97
the max number we can compute here is:
99
(2 ** 32 - 1) * (2 ** 32 - 1) + // ua.LowPart * ub.LowPart
100
(2 ** 32) * (2 ** 31) * (2 ** 32 - 1) * 2 // x.LowPart * y.HighPart * 2
102
== 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1)
103
== 2 ** 96 - 2 ** 33 + 1
108
x.QuadPart = UInt32x32To64(ua.LowPart, ub.HighPart) +
109
UInt32x32To64(ua.HighPart, ub.LowPart) +
111
p[0].HighPart = x.LowPart;
112
p[1].QuadPart = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
115
ULARGE_INTEGER ud[2];
117
ud[0].QuadPart = (DWORDLONG)(-d);
120
ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
122
ud[1].QuadPart = (DWORDLONG)0;
125
ud[0].QuadPart = (DWORDLONG)d;
127
ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
129
ud[1].QuadPart = (DWORDLONG)0;
132
/* Now do extended addition */
133
ULARGE_INTEGER uliTotal;
136
uliTotal.QuadPart = (DWORDLONG)ud[0].LowPart + p[0].LowPart;
137
p[0].LowPart = uliTotal.LowPart;
139
/* Propagate carry */
140
uliTotal.LowPart = uliTotal.HighPart;
141
uliTotal.HighPart = 0;
143
/* Add 2nd most ls DWORDs */
144
uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart;
145
p[0].HighPart = uliTotal.LowPart;
147
/* Propagate carry */
148
uliTotal.LowPart = uliTotal.HighPart;
149
uliTotal.HighPart = 0;
151
/* Add MS DWORDLONGs - no carry expected */
152
p[1].QuadPart += ud[1].QuadPart + uliTotal.QuadPart;
154
/* Now see if we got a sign change from the addition */
155
if ((LONG)p[1].HighPart < 0) {
158
/* Negate the current value (ugh!) */
159
p[0].QuadPart = ~p[0].QuadPart;
160
p[1].QuadPart = ~p[1].QuadPart;
162
p[1].QuadPart += (p[0].QuadPart == 0);
166
/* Now for the division */
172
/* This will catch c == 0 and overflow */
173
if (uc <= p[1].QuadPart) {
174
return bSign ? (LONGLONG)0x8000000000000000 :
175
(LONGLONG)0x7FFFFFFFFFFFFFFF;
180
/* Do the division */
181
/* If the dividend is a DWORD_LONG use the compiler */
182
if (p[1].QuadPart == 0) {
183
ullResult = p[0].QuadPart / uc;
184
return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult;
187
/* If the divisor is a DWORD then its simpler */
190
if (ulic.HighPart == 0) {
191
ULARGE_INTEGER uliDividend;
192
ULARGE_INTEGER uliResult;
193
DWORD dwDivisor = (DWORD)uc;
194
// ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
195
uliDividend.HighPart = p[1].LowPart;
196
uliDividend.LowPart = p[0].HighPart;
198
uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor);
199
p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor);
200
uliResult.LowPart = 0;
201
uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart;
203
/* NOTE - this routine will take exceptions if
204
the result does not fit in a DWORD
206
if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
207
uliResult.HighPart = EnlargedUnsignedDivide(
212
uliResult.HighPart = 0;
214
uliResult.LowPart = EnlargedUnsignedDivide(
219
return bSign ? -(LONGLONG)uliResult.QuadPart :
220
(LONGLONG)uliResult.QuadPart;
226
/* OK - do long division */
227
for (int i = 0; i < 64; i++) {
230
/* Shift 128 bit p left 1 */
232
if ((p[0].HighPart & 0x80000000) != 0) {
238
if (uc <= p[1].QuadPart) {
244
return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult;
247
LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d)
253
/* Compute the absolute values to avoid signed arithmetic problems */
254
ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
255
ub = (DWORD)(b >= 0 ? b : -b);
256
uc = (DWORD)(c >= 0 ? c : -c);
257
BOOL bSign = (a < 0) ^ (b < 0);
259
/* Do long multiplication */
262
p0.QuadPart = UInt32x32To64(ua.LowPart, ub);
264
if (ua.HighPart != 0) {
266
x.QuadPart = UInt32x32To64(ua.HighPart, ub) + p0.HighPart;
267
p0.HighPart = x.LowPart;
279
// Cast d to LONGLONG first otherwise -0x80000000 sign extends
282
ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d);
290
ud0.QuadPart = (DWORDLONG)d;
297
/* Now do extended addition */
298
ULARGE_INTEGER uliTotal;
301
uliTotal.QuadPart = (DWORDLONG)ud0.LowPart + p0.LowPart;
302
p0.LowPart = uliTotal.LowPart;
304
/* Propagate carry */
305
uliTotal.LowPart = uliTotal.HighPart;
306
uliTotal.HighPart = 0;
308
/* Add 2nd most ls DWORDs */
309
uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart;
310
p0.HighPart = uliTotal.LowPart;
312
/* Add MS DWORDLONGs - no carry expected */
313
p1 += ud1 + uliTotal.HighPart;
315
/* Now see if we got a sign change from the addition */
319
/* Negate the current value (ugh!) */
320
p0.QuadPart = ~p0.QuadPart;
323
p1 += (p0.QuadPart == 0);
327
/* Now for the division */
333
/* This will catch c == 0 and overflow */
335
return bSign ? (LONGLONG)0x8000000000000000 :
336
(LONGLONG)0x7FFFFFFFFFFFFFFF;
339
/* Do the division */
341
/* If the divisor is a DWORD then its simpler */
342
ULARGE_INTEGER uliDividend;
343
ULARGE_INTEGER uliResult;
344
DWORD dwDivisor = uc;
345
uliDividend.HighPart = p1;
346
uliDividend.LowPart = p0.HighPart;
347
/* NOTE - this routine will take exceptions if
348
the result does not fit in a DWORD
350
if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
351
uliResult.HighPart = EnlargedUnsignedDivide(
356
uliResult.HighPart = 0;
358
uliResult.LowPart = EnlargedUnsignedDivide(
362
return bSign ? -(LONGLONG)uliResult.QuadPart :
363
(LONGLONG)uliResult.QuadPart;
366
#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */