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
0f1f42ea
Commit
0f1f42ea
authored
Apr 01, 2002
by
Hidenori Takeshima
Committed by
Alexandre Julliard
Apr 01, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed some bugs.
Implemented some methods of CLSID_ACMWrapper.
parent
3a007359
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
673 additions
and
59 deletions
+673
-59
README
dlls/quartz/README
+0
-2
acmwrap.c
dlls/quartz/acmwrap.c
+484
-11
basefilt.c
dlls/quartz/basefilt.c
+15
-0
fmap.c
dlls/quartz/fmap.c
+58
-20
main.c
dlls/quartz/main.c
+1
-0
mpgparse.c
dlls/quartz/mpgparse.c
+40
-10
parser.c
dlls/quartz/parser.c
+34
-16
xform.h
dlls/quartz/xform.h
+1
-0
winedefault.reg
winedefault.reg
+40
-0
No files found.
dlls/quartz/README
View file @
0f1f42ea
...
...
@@ -7,14 +7,12 @@ TODO
- merge some C sources
- implement filters
- restruct color-space converter
- add FilterData to winedefault.reg for Connect() and Render()
- sort active filters in filter graph
- sort regfilters in Merit order
- fix deadlocks in Receive/EndOfStream
- handle plug-in distributor
- handle seeking
- implement some interfaces as plug-ins(???)
- implement ACM drivers (g711)
- implement ACM wrapper (improve xform)
- implement mciqtz(mci driver for quartz)
- implement renderer
...
...
dlls/quartz/acmwrap.c
View file @
0f1f42ea
...
...
@@ -2,6 +2,7 @@
* Implements ACM Wrapper(CLSID_ACMWrapper).
*
* FIXME - stub
* FIXME - no encoding
*
* Copyright (C) 2002 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*
...
...
@@ -40,6 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "xform.h"
#include "mtype.h"
static
const
WCHAR
ACMWrapper_FilterName
[]
=
...
...
@@ -49,8 +51,152 @@ static const WCHAR ACMWrapper_FilterName[] =
typedef
struct
CACMWrapperImpl
{
HACMSTREAM
has
;
WAVEFORMATEX
*
pwfxIn
;
AM_MEDIA_TYPE
*
pmtOuts
;
DWORD
cOuts
;
BYTE
*
pConvBuf
;
DWORD
cbConvBlockSize
;
DWORD
cbConvCached
;
DWORD
cbConvAllocated
;
}
CACMWrapperImpl
;
static
void
ACMWrapper_CleanupMTypes
(
CACMWrapperImpl
*
This
)
{
DWORD
n
;
if
(
This
->
pmtOuts
==
NULL
)
return
;
for
(
n
=
0
;
n
<
This
->
cOuts
;
n
++
)
{
QUARTZ_MediaType_Free
(
&
This
->
pmtOuts
[
n
]
);
}
QUARTZ_FreeMem
(
This
->
pmtOuts
);
This
->
pmtOuts
=
NULL
;
This
->
cOuts
=
0
;
}
static
void
ACMWrapper_CleanupConvBuf
(
CACMWrapperImpl
*
This
)
{
if
(
This
->
pConvBuf
!=
NULL
)
{
QUARTZ_FreeMem
(
This
->
pConvBuf
);
This
->
pConvBuf
=
NULL
;
}
This
->
cbConvBlockSize
=
0
;
This
->
cbConvCached
=
0
;
This
->
cbConvAllocated
=
0
;
}
static
const
WAVEFORMATEX
*
ACMWrapper_GetAudioFmt
(
const
AM_MEDIA_TYPE
*
pmt
)
{
const
WAVEFORMATEX
*
pwfx
;
if
(
!
IsEqualGUID
(
&
pmt
->
majortype
,
&
MEDIATYPE_Audio
)
)
return
NULL
;
if
(
!
IsEqualGUID
(
&
pmt
->
subtype
,
&
MEDIASUBTYPE_NULL
)
&&
!
QUARTZ_MediaSubType_IsFourCC
(
&
pmt
->
subtype
)
)
return
NULL
;
if
(
!
IsEqualGUID
(
&
pmt
->
formattype
,
&
FORMAT_WaveFormatEx
)
)
return
NULL
;
if
(
pmt
->
pbFormat
==
NULL
||
pmt
->
cbFormat
<
(
sizeof
(
WAVEFORMATEX
)
-
sizeof
(
WORD
))
)
return
NULL
;
pwfx
=
(
const
WAVEFORMATEX
*
)
pmt
->
pbFormat
;
if
(
pwfx
->
wFormatTag
!=
1
&&
pmt
->
cbFormat
<
sizeof
(
WAVEFORMATEX
)
)
return
NULL
;
return
pwfx
;
}
static
HRESULT
ACMWrapper_SetupAudioFmt
(
AM_MEDIA_TYPE
*
pmt
,
DWORD
cbFormat
,
WORD
wFormatTag
,
DWORD
dwBlockAlign
)
{
ZeroMemory
(
pmt
,
sizeof
(
AM_MEDIA_TYPE
)
);
memcpy
(
&
pmt
->
majortype
,
&
MEDIATYPE_Audio
,
sizeof
(
GUID
)
);
QUARTZ_MediaSubType_FromFourCC
(
&
pmt
->
subtype
,
(
DWORD
)
wFormatTag
);
pmt
->
bFixedSizeSamples
=
1
;
pmt
->
bTemporalCompression
=
1
;
pmt
->
lSampleSize
=
dwBlockAlign
;
memcpy
(
&
pmt
->
formattype
,
&
FORMAT_WaveFormatEx
,
sizeof
(
GUID
)
);
pmt
->
pUnk
=
NULL
;
pmt
->
cbFormat
=
cbFormat
;
pmt
->
pbFormat
=
(
BYTE
*
)
CoTaskMemAlloc
(
cbFormat
);
if
(
pmt
->
pbFormat
==
NULL
)
return
E_OUTOFMEMORY
;
return
S_OK
;
}
static
void
ACMWrapper_FillFmtPCM
(
WAVEFORMATEX
*
pwfxOut
,
const
WAVEFORMATEX
*
pwfxIn
,
WORD
wBitsPerSampOut
)
{
pwfxOut
->
wFormatTag
=
1
;
pwfxOut
->
nChannels
=
pwfxIn
->
nChannels
;
pwfxOut
->
nSamplesPerSec
=
pwfxIn
->
nSamplesPerSec
;
pwfxOut
->
nAvgBytesPerSec
=
((
DWORD
)
pwfxIn
->
nSamplesPerSec
*
(
DWORD
)
pwfxIn
->
nChannels
*
(
DWORD
)
wBitsPerSampOut
)
>>
3
;
pwfxOut
->
nBlockAlign
=
(
pwfxIn
->
nChannels
*
wBitsPerSampOut
)
>>
3
;
pwfxOut
->
wBitsPerSample
=
wBitsPerSampOut
;
pwfxOut
->
cbSize
=
0
;
}
static
BOOL
ACMWrapper_IsSupported
(
WAVEFORMATEX
*
pwfxOut
,
WAVEFORMATEX
*
pwfxIn
)
{
MMRESULT
mr
;
mr
=
acmStreamOpen
(
NULL
,(
HACMDRIVER
)
NULL
,
pwfxIn
,
pwfxOut
,
NULL
,
0
,
0
,
ACM_STREAMOPENF_QUERY
);
if
(
mr
==
ACMERR_NOTPOSSIBLE
)
mr
=
acmStreamOpen
(
NULL
,(
HACMDRIVER
)
NULL
,
pwfxIn
,
pwfxOut
,
NULL
,
0
,
0
,
ACM_STREAMOPENF_NONREALTIME
|
ACM_STREAMOPENF_QUERY
);
return
!!
(
mr
==
MMSYSERR_NOERROR
);
}
static
HRESULT
ACMWrapper_StreamOpen
(
HACMSTREAM
*
phas
,
WAVEFORMATEX
*
pwfxOut
,
WAVEFORMATEX
*
pwfxIn
)
{
HACMSTREAM
has
=
(
HACMSTREAM
)
NULL
;
MMRESULT
mr
;
mr
=
acmStreamOpen
(
&
has
,(
HACMDRIVER
)
NULL
,
pwfxIn
,
pwfxOut
,
NULL
,
0
,
0
,
0
);
if
(
mr
==
ACMERR_NOTPOSSIBLE
)
mr
=
acmStreamOpen
(
&
has
,(
HACMDRIVER
)
NULL
,
pwfxIn
,
pwfxOut
,
NULL
,
0
,
0
,
ACM_STREAMOPENF_NONREALTIME
);
if
(
mr
!=
MMSYSERR_NOERROR
)
{
if
(
mr
==
MMSYSERR_NOMEM
)
return
E_OUTOFMEMORY
;
return
E_FAIL
;
}
*
phas
=
has
;
return
S_OK
;
}
/***************************************************************************
*
* CACMWrapperImpl methods
...
...
@@ -84,8 +230,12 @@ static HRESULT ACMWrapper_Init( CTransformBaseImpl* pImpl )
/* construct */
This
->
has
=
(
HACMSTREAM
)
NULL
;
This
->
pwfxIn
=
NULL
;
This
->
pmtOuts
=
NULL
;
This
->
cOuts
=
0
;
This
->
pConvBuf
=
NULL
;
return
E_NOTIMPL
;
return
S_OK
;
}
static
HRESULT
ACMWrapper_Cleanup
(
CTransformBaseImpl
*
pImpl
)
...
...
@@ -99,6 +249,9 @@ static HRESULT ACMWrapper_Cleanup( CTransformBaseImpl* pImpl )
/* destruct */
ACMWrapper_Close
(
This
);
QUARTZ_FreeMem
(
This
->
pwfxIn
);
ACMWrapper_CleanupMTypes
(
This
);
ACMWrapper_CleanupConvBuf
(
This
);
QUARTZ_FreeMem
(
This
);
pImpl
->
m_pUserData
=
NULL
;
...
...
@@ -109,57 +262,362 @@ static HRESULT ACMWrapper_Cleanup( CTransformBaseImpl* pImpl )
static
HRESULT
ACMWrapper_CheckMediaType
(
CTransformBaseImpl
*
pImpl
,
const
AM_MEDIA_TYPE
*
pmtIn
,
const
AM_MEDIA_TYPE
*
pmtOut
)
{
CACMWrapperImpl
*
This
=
pImpl
->
m_pUserData
;
const
WAVEFORMATEX
*
pwfxIn
;
const
WAVEFORMATEX
*
pwfxOut
;
WAVEFORMATEX
wfx
;
FIXME
(
"(%p)
\n
"
,
This
);
if
(
This
==
NULL
)
return
E_UNEXPECTED
;
return
E_NOTIMPL
;
pwfxIn
=
ACMWrapper_GetAudioFmt
(
pmtIn
);
if
(
pwfxIn
==
NULL
||
pwfxIn
->
wFormatTag
==
0
||
pwfxIn
->
wFormatTag
==
1
)
{
TRACE
(
"pwfxIn is not a compressed audio
\n
"
);
return
E_FAIL
;
}
if
(
pmtOut
!=
NULL
)
{
pwfxOut
=
ACMWrapper_GetAudioFmt
(
pmtOut
);
if
(
pwfxOut
==
NULL
||
pwfxOut
->
wFormatTag
!=
1
)
{
TRACE
(
"pwfxOut is not a linear PCM
\n
"
);
return
E_FAIL
;
}
if
(
pwfxIn
->
nChannels
!=
pwfxOut
->
nChannels
||
pwfxIn
->
nSamplesPerSec
!=
pwfxOut
->
nSamplesPerSec
)
{
TRACE
(
"nChannels or nSamplesPerSec is not matched
\n
"
);
return
E_FAIL
;
}
if
(
!
ACMWrapper_IsSupported
((
WAVEFORMATEX
*
)
pwfxOut
,(
WAVEFORMATEX
*
)
pwfxIn
)
)
{
TRACE
(
"specified formats are not supported by ACM
\n
"
);
return
E_FAIL
;
}
}
else
{
ACMWrapper_FillFmtPCM
(
&
wfx
,
pwfxIn
,
8
);
if
(
ACMWrapper_IsSupported
(
&
wfx
,(
WAVEFORMATEX
*
)
pwfxIn
)
)
{
TRACE
(
"compressed audio - can be decoded to 8bit
\n
"
);
return
S_OK
;
}
ACMWrapper_FillFmtPCM
(
&
wfx
,
pwfxIn
,
16
);
if
(
ACMWrapper_IsSupported
(
&
wfx
,(
WAVEFORMATEX
*
)
pwfxIn
)
)
{
TRACE
(
"compressed audio - can be decoded to 16bit
\n
"
);
return
S_OK
;
}
TRACE
(
"unhandled audio %04x
\n
"
,(
unsigned
)
pwfxIn
->
wFormatTag
);
return
E_FAIL
;
}
return
S_OK
;
}
static
HRESULT
ACMWrapper_GetOutputTypes
(
CTransformBaseImpl
*
pImpl
,
const
AM_MEDIA_TYPE
*
pmtIn
,
const
AM_MEDIA_TYPE
**
ppmtAcceptTypes
,
ULONG
*
pcAcceptTypes
)
{
CACMWrapperImpl
*
This
=
pImpl
->
m_pUserData
;
HRESULT
hr
;
const
WAVEFORMATEX
*
pwfxIn
;
AM_MEDIA_TYPE
*
pmtTry
;
WAVEFORMATEX
*
pwfxTry
;
FIXME
(
"(%p)
\n
"
,
This
);
hr
=
ACMWrapper_CheckMediaType
(
pImpl
,
pmtIn
,
NULL
);
if
(
FAILED
(
hr
)
)
return
hr
;
pwfxIn
=
(
const
WAVEFORMATEX
*
)
pmtIn
->
pbFormat
;
ACMWrapper_CleanupMTypes
(
This
);
This
->
pmtOuts
=
QUARTZ_AllocMem
(
sizeof
(
AM_MEDIA_TYPE
)
*
2
);
if
(
This
->
pmtOuts
==
NULL
)
return
E_OUTOFMEMORY
;
This
->
cOuts
=
0
;
pmtTry
=
&
This
->
pmtOuts
[
This
->
cOuts
];
hr
=
ACMWrapper_SetupAudioFmt
(
pmtTry
,
sizeof
(
WAVEFORMATEX
),
1
,
(
pwfxIn
->
nChannels
*
8
)
>>
3
);
if
(
FAILED
(
hr
)
)
goto
err
;
pwfxTry
=
(
WAVEFORMATEX
*
)
pmtTry
->
pbFormat
;
ACMWrapper_FillFmtPCM
(
pwfxTry
,
pwfxIn
,
8
);
if
(
ACMWrapper_IsSupported
(
pwfxTry
,
(
WAVEFORMATEX
*
)
pwfxIn
)
)
This
->
cOuts
++
;
pmtTry
=
&
This
->
pmtOuts
[
This
->
cOuts
];
hr
=
ACMWrapper_SetupAudioFmt
(
pmtTry
,
sizeof
(
WAVEFORMATEX
),
1
,
(
pwfxIn
->
nChannels
*
16
)
>>
3
);
if
(
FAILED
(
hr
)
)
goto
err
;
pwfxTry
=
(
WAVEFORMATEX
*
)
pmtTry
->
pbFormat
;
ACMWrapper_FillFmtPCM
(
pwfxTry
,
pwfxIn
,
16
);
if
(
ACMWrapper_IsSupported
(
pwfxTry
,
(
WAVEFORMATEX
*
)
pwfxIn
)
)
This
->
cOuts
++
;
*
ppmtAcceptTypes
=
This
->
pmtOuts
;
*
pcAcceptTypes
=
This
->
cOuts
;
return
E_NOTIMPL
;
return
S_OK
;
err:
ACMWrapper_CleanupMTypes
(
This
);
return
hr
;
}
static
HRESULT
ACMWrapper_GetConvBufSize
(
CTransformBaseImpl
*
pImpl
,
CACMWrapperImpl
*
This
,
DWORD
*
pcbInput
,
DWORD
*
pcbOutput
,
const
AM_MEDIA_TYPE
*
pmtOut
,
const
AM_MEDIA_TYPE
*
pmtIn
)
{
HRESULT
hr
;
const
WAVEFORMATEX
*
pwfxIn
;
const
WAVEFORMATEX
*
pwfxOut
;
HACMSTREAM
has
;
MMRESULT
mr
;
DWORD
cbInput
;
DWORD
cbOutput
;
if
(
This
==
NULL
)
return
E_UNEXPECTED
;
hr
=
ACMWrapper_CheckMediaType
(
pImpl
,
pmtIn
,
pmtOut
);
if
(
FAILED
(
hr
)
)
return
hr
;
pwfxIn
=
(
const
WAVEFORMATEX
*
)
pmtIn
->
pbFormat
;
pwfxOut
=
(
const
WAVEFORMATEX
*
)
pmtOut
->
pbFormat
;
hr
=
ACMWrapper_StreamOpen
(
&
has
,
(
WAVEFORMATEX
*
)
pwfxOut
,
(
WAVEFORMATEX
*
)
pwfxIn
);
if
(
FAILED
(
hr
)
)
return
hr
;
cbInput
=
(
pwfxIn
->
nAvgBytesPerSec
+
pwfxIn
->
nBlockAlign
-
1
)
/
pwfxIn
->
nBlockAlign
*
pwfxIn
->
nBlockAlign
;
cbOutput
=
0
;
mr
=
acmStreamSize
(
has
,
cbInput
,
&
cbOutput
,
ACM_STREAMSIZEF_SOURCE
);
acmStreamClose
(
has
,
0
);
if
(
mr
!=
MMSYSERR_NOERROR
||
cbOutput
==
0
)
return
E_FAIL
;
TRACE
(
"size %lu -> %lu
\n
"
,
cbInput
,
cbOutput
);
if
(
pcbInput
!=
NULL
)
*
pcbInput
=
cbInput
;
if
(
pcbOutput
!=
NULL
)
*
pcbOutput
=
cbOutput
;
return
S_OK
;
}
static
HRESULT
ACMWrapper_GetAllocProp
(
CTransformBaseImpl
*
pImpl
,
const
AM_MEDIA_TYPE
*
pmtIn
,
const
AM_MEDIA_TYPE
*
pmtOut
,
ALLOCATOR_PROPERTIES
*
pProp
,
BOOL
*
pbTransInPlace
,
BOOL
*
pbTryToReuseSample
)
{
CACMWrapperImpl
*
This
=
pImpl
->
m_pUserData
;
HRESULT
hr
;
DWORD
cbOutput
;
FIXM
E
(
"(%p)
\n
"
,
This
);
TRAC
E
(
"(%p)
\n
"
,
This
);
if
(
This
==
NULL
)
return
E_UNEXPECTED
;
hr
=
ACMWrapper_CheckMediaType
(
pImpl
,
pmtIn
,
pmtOut
);
hr
=
ACMWrapper_GetConvBufSize
(
pImpl
,
This
,
NULL
,
&
cbOutput
,
pmtOut
,
pmtIn
);
if
(
FAILED
(
hr
)
)
return
hr
;
pProp
->
cBuffers
=
1
;
pProp
->
cbBuffer
=
cbOutput
;
*
pbTransInPlace
=
FALSE
;
*
pbTryToReuseSample
=
FALSE
;
return
E_NOTIMPL
;
return
S_OK
;
}
static
HRESULT
ACMWrapper_BeginTransform
(
CTransformBaseImpl
*
pImpl
,
const
AM_MEDIA_TYPE
*
pmtIn
,
const
AM_MEDIA_TYPE
*
pmtOut
,
BOOL
bReuseSample
)
{
CACMWrapperImpl
*
This
=
pImpl
->
m_pUserData
;
HRESULT
hr
;
const
WAVEFORMATEX
*
pwfxIn
;
const
WAVEFORMATEX
*
pwfxOut
;
DWORD
cbInput
;
FIXME
(
"(%p,%p,%p,%d)
\n
"
,
This
,
pmtIn
,
pmtOut
,
bReuseSample
);
if
(
This
==
NULL
)
return
E_UNEXPECTED
;
return
E_NOTIMPL
;
ACMWrapper_Close
(
This
);
ACMWrapper_CleanupMTypes
(
This
);
ACMWrapper_CleanupConvBuf
(
This
);
hr
=
ACMWrapper_GetConvBufSize
(
pImpl
,
This
,
&
cbInput
,
NULL
,
pmtOut
,
pmtIn
);
if
(
FAILED
(
hr
)
)
return
hr
;
pwfxIn
=
(
const
WAVEFORMATEX
*
)
pmtIn
->
pbFormat
;
pwfxOut
=
(
const
WAVEFORMATEX
*
)
pmtOut
->
pbFormat
;
This
->
pConvBuf
=
(
BYTE
*
)
QUARTZ_AllocMem
(
cbInput
);
if
(
This
->
pConvBuf
==
NULL
)
return
E_OUTOFMEMORY
;
This
->
cbConvBlockSize
=
pwfxIn
->
nBlockAlign
;
This
->
cbConvCached
=
0
;
This
->
cbConvAllocated
=
cbInput
;
hr
=
ACMWrapper_StreamOpen
(
&
This
->
has
,
(
WAVEFORMATEX
*
)
pmtOut
,
(
WAVEFORMATEX
*
)
pmtIn
);
if
(
FAILED
(
hr
)
)
return
E_FAIL
;
return
S_OK
;
}
static
HRESULT
ACMWrapper_Convert
(
CTransformBaseImpl
*
pImpl
,
CACMWrapperImpl
*
This
,
BYTE
*
pbSrc
,
DWORD
cbSrcLen
,
DWORD
dwConvertFlags
)
{
ACMSTREAMHEADER
ash
;
MMRESULT
mr
;
HRESULT
hr
=
E_FAIL
;
DWORD
dwConvCallFlags
;
DWORD
cb
;
IMediaSample
*
pSampOut
=
NULL
;
BYTE
*
pOutBuf
;
LONG
lOutBufLen
;
TRACE
(
"()
\n
"
);
if
(
This
->
pConvBuf
==
NULL
)
return
E_UNEXPECTED
;
dwConvCallFlags
=
ACM_STREAMCONVERTF_BLOCKALIGN
;
if
(
dwConvertFlags
&
ACM_STREAMCONVERTF_START
)
{
dwConvCallFlags
|=
ACM_STREAMCONVERTF_START
;
This
->
cbConvCached
=
0
;
}
while
(
1
)
{
cb
=
cbSrcLen
+
This
->
cbConvCached
;
if
(
cb
>
This
->
cbConvAllocated
)
cb
=
This
->
cbConvAllocated
;
cb
-=
This
->
cbConvCached
;
if
(
cb
>
0
)
{
memcpy
(
This
->
pConvBuf
+
This
->
cbConvCached
,
pbSrc
,
cb
);
pbSrc
+=
cb
;
cbSrcLen
-=
cb
;
This
->
cbConvCached
+=
cb
;
}
cb
=
This
->
cbConvCached
/
This
->
cbConvBlockSize
*
This
->
cbConvBlockSize
;
if
(
cb
==
0
)
{
if
(
dwConvertFlags
&
ACM_STREAMCONVERTF_END
)
{
dwConvCallFlags
&=
~
ACM_STREAMCONVERTF_BLOCKALIGN
;
dwConvCallFlags
|=
ACM_STREAMCONVERTF_END
;
cb
=
This
->
cbConvCached
;
}
if
(
cb
==
0
)
{
hr
=
S_OK
;
break
;
}
}
ZeroMemory
(
&
ash
,
sizeof
(
ash
)
);
ash
.
cbStruct
=
sizeof
(
ash
);
ash
.
pbSrc
=
This
->
pConvBuf
;
ash
.
cbSrcLength
=
cb
;
hr
=
IMemAllocator_GetBuffer
(
pImpl
->
m_pOutPinAllocator
,
&
pSampOut
,
NULL
,
NULL
,
0
);
if
(
FAILED
(
hr
)
)
break
;
hr
=
IMediaSample_SetSyncPoint
(
pSampOut
,
TRUE
);
if
(
FAILED
(
hr
)
)
break
;
if
(
dwConvCallFlags
&
ACM_STREAMCONVERTF_START
)
{
hr
=
IMediaSample_SetDiscontinuity
(
pSampOut
,
TRUE
);
if
(
FAILED
(
hr
)
)
break
;
}
hr
=
IMediaSample_GetPointer
(
pSampOut
,
&
pOutBuf
);
if
(
FAILED
(
hr
)
)
break
;
lOutBufLen
=
IMediaSample_GetSize
(
pSampOut
);
if
(
lOutBufLen
<=
0
)
{
hr
=
E_FAIL
;
break
;
}
ash
.
pbDst
=
pOutBuf
;
ash
.
cbDstLength
=
lOutBufLen
;
mr
=
acmStreamPrepareHeader
(
This
->
has
,
&
ash
,
0
);
if
(
mr
==
MMSYSERR_NOERROR
)
mr
=
acmStreamConvert
(
This
->
has
,
&
ash
,
dwConvCallFlags
);
if
(
mr
==
MMSYSERR_NOERROR
)
mr
=
acmStreamUnprepareHeader
(
This
->
has
,
&
ash
,
0
);
if
(
mr
!=
MMSYSERR_NOERROR
||
ash
.
cbSrcLengthUsed
==
0
)
{
hr
=
E_FAIL
;
break
;
}
if
(
ash
.
cbDstLengthUsed
>
0
)
{
hr
=
IMediaSample_SetActualDataLength
(
pSampOut
,
ash
.
cbDstLengthUsed
);
if
(
FAILED
(
hr
)
)
break
;
hr
=
CPinBaseImpl_SendSample
(
&
pImpl
->
pOutPin
->
pin
,
pSampOut
);
if
(
FAILED
(
hr
)
)
break
;
}
if
(
This
->
cbConvCached
==
ash
.
cbSrcLengthUsed
)
{
This
->
cbConvCached
=
0
;
}
else
{
This
->
cbConvCached
-=
ash
.
cbSrcLengthUsed
;
memmove
(
This
->
pConvBuf
,
This
->
pConvBuf
+
ash
.
cbSrcLengthUsed
,
This
->
cbConvCached
);
}
IMediaSample_Release
(
pSampOut
);
pSampOut
=
NULL
;
dwConvCallFlags
&=
~
ACM_STREAMCONVERTF_START
;
}
if
(
pSampOut
!=
NULL
)
IMediaSample_Release
(
pSampOut
);
return
hr
;
}
static
HRESULT
ACMWrapper_ProcessReceive
(
CTransformBaseImpl
*
pImpl
,
IMediaSample
*
pSampIn
)
...
...
@@ -168,32 +626,47 @@ static HRESULT ACMWrapper_ProcessReceive( CTransformBaseImpl* pImpl, IMediaSampl
BYTE
*
pDataIn
=
NULL
;
LONG
lDataInLen
;
HRESULT
hr
;
DWORD
dwConvFlags
=
0
;
FIXME
(
"(%p)
\n
"
,
This
);
if
(
This
==
NULL
)
if
(
This
==
NULL
||
This
->
has
==
(
HACMSTREAM
)
NULL
)
return
E_UNEXPECTED
;
hr
=
IMediaSample_GetPointer
(
pSampIn
,
&
pDataIn
);
if
(
FAILED
(
hr
)
)
return
hr
;
lDataInLen
=
IMediaSample_GetActualDataLength
(
pSampIn
);
return
E_NOTIMPL
;
if
(
lDataInLen
<
0
)
return
E_FAIL
;
if
(
IMediaSample_IsDiscontinuity
(
pSampIn
)
!=
S_OK
)
dwConvFlags
|=
ACM_STREAMCONVERTF_START
;
return
ACMWrapper_Convert
(
pImpl
,
This
,
pDataIn
,
(
DWORD
)
lDataInLen
,
dwConvFlags
);
}
static
HRESULT
ACMWrapper_EndTransform
(
CTransformBaseImpl
*
pImpl
)
{
CACMWrapperImpl
*
This
=
pImpl
->
m_pUserData
;
HRESULT
hr
;
DWORD
dwConvFlags
=
ACM_STREAMCONVERTF_END
;
TRACE
(
"(%p)
\n
"
,
This
);
if
(
This
==
NULL
)
return
E_UNEXPECTED
;
hr
=
ACMWrapper_Convert
(
pImpl
,
This
,
NULL
,
0
,
dwConvFlags
);
ACMWrapper_Close
(
This
);
ACMWrapper_CleanupMTypes
(
This
);
ACMWrapper_CleanupConvBuf
(
This
);
return
S_OK
;
return
hr
;
}
static
const
TransformBaseHandlers
transhandlers
=
...
...
dlls/quartz/basefilt.c
View file @
0f1f42ea
...
...
@@ -99,6 +99,11 @@ CBaseFilterImpl_fnStop(IBaseFilter* iface)
hr
=
NOERROR
;
EnterCriticalSection
(
&
This
->
csFilter
);
if
(
This
->
bIntermediateState
)
{
LeaveCriticalSection
(
&
This
->
csFilter
);
return
VFW_S_STATE_INTERMEDIATE
;
/* FIXME? */
}
TRACE
(
"(%p) state = %d
\n
"
,
This
,
This
->
fstate
);
if
(
This
->
fstate
==
State_Running
)
...
...
@@ -132,6 +137,11 @@ CBaseFilterImpl_fnPause(IBaseFilter* iface)
hr
=
NOERROR
;
EnterCriticalSection
(
&
This
->
csFilter
);
if
(
This
->
bIntermediateState
)
{
LeaveCriticalSection
(
&
This
->
csFilter
);
return
VFW_E_WRONG_STATE
;
/* FIXME? */
}
TRACE
(
"(%p) state = %d
\n
"
,
This
,
This
->
fstate
);
if
(
This
->
fstate
!=
State_Paused
)
...
...
@@ -159,6 +169,11 @@ CBaseFilterImpl_fnRun(IBaseFilter* iface,REFERENCE_TIME rtStart)
hr
=
NOERROR
;
EnterCriticalSection
(
&
This
->
csFilter
);
if
(
This
->
bIntermediateState
)
{
LeaveCriticalSection
(
&
This
->
csFilter
);
return
VFW_E_WRONG_STATE
;
/* FIXME? */
}
TRACE
(
"(%p) state = %d
\n
"
,
This
,
This
->
fstate
);
This
->
rtStart
=
rtStart
;
...
...
dlls/quartz/fmap.c
View file @
0f1f42ea
/*
* Implementation of CLSID_FilterMapper and CLSID_FilterMapper2.
*
* FIXME - s
tub.
* FIXME - s
ome stubs
*
* Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*
...
...
@@ -22,6 +22,7 @@
#include "config.h"
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
...
...
@@ -840,6 +841,19 @@ err:
return
hr
;
}
struct
MATCHED_ITEM
{
IMoniker
*
pMonFilter
;
DWORD
dwMerit
;
};
static
int
sort_comp_merit
(
const
void
*
p1
,
const
void
*
p2
)
{
const
struct
MATCHED_ITEM
*
pItem1
=
(
const
struct
MATCHED_ITEM
*
)
p1
;
const
struct
MATCHED_ITEM
*
pItem2
=
(
const
struct
MATCHED_ITEM
*
)
p2
;
return
(
int
)
pItem2
->
dwMerit
-
(
int
)
pItem1
->
dwMerit
;
}
static
HRESULT
WINAPI
IFilterMapper2_fnEnumMatchingFilters
(
IFilterMapper2
*
iface
,
...
...
@@ -859,7 +873,10 @@ IFilterMapper2_fnEnumMatchingFilters(IFilterMapper2* iface,
BYTE
*
pbFilterData
=
NULL
;
DWORD
cbFilterData
=
0
;
REGFILTER2
*
prf2
=
NULL
;
QUARTZ_CompList
*
pList
=
NULL
;
QUARTZ_CompList
*
pListFilters
=
NULL
;
struct
MATCHED_ITEM
*
pItems
=
NULL
;
struct
MATCHED_ITEM
*
pItemsTmp
;
int
cItems
=
0
;
const
REGFILTERPINS2
*
pRegFilterPin
;
DWORD
n
;
BOOL
bMatch
;
...
...
@@ -995,32 +1012,44 @@ IFilterMapper2_fnEnumMatchingFilters(IFilterMapper2* iface,
}
/* matched - add pFilter to the list. */
if
(
pList
==
NULL
)
pItemsTmp
=
QUARTZ_ReallocMem
(
pItems
,
sizeof
(
struct
MATCHED_ITEM
)
*
(
cItems
+
1
)
);
if
(
pItemsTmp
==
NULL
)
{
pList
=
QUARTZ_CompList_Alloc
();
if
(
pList
==
NULL
)
{
hr
=
E_OUTOFMEMORY
;
goto
err
;
}
}
TRACE
(
"matched
\n
"
);
hr
=
QUARTZ_CompList_AddComp
(
pList
,
(
IUnknown
*
)
pFilter
,
NULL
,
0
);
if
(
FAILED
(
hr
)
)
hr
=
E_OUTOFMEMORY
;
goto
err
;
}
pItems
=
pItemsTmp
;
pItemsTmp
=
pItems
+
cItems
;
cItems
++
;
pItemsTmp
->
pMonFilter
=
pFilter
;
pFilter
=
NULL
;
pItemsTmp
->
dwMerit
=
prf2
->
dwMerit
;
}
}
if
(
p
List
==
NULL
)
if
(
p
Items
==
NULL
||
cItems
==
0
)
{
hr
=
S_FALSE
;
goto
err
;
}
FIXME
(
"create IEnumMoniker - not sorted
\n
"
);
/* FIXME - should be sorted?(in Merit order) */
hr
=
QUARTZ_CreateEnumUnknown
(
&
IID_IEnumMoniker
,
(
void
**
)
ppEnumMoniker
,
pList
);
/* FIXME - sort in Merit order */
TRACE
(
"sort in Merit order
\n
"
);
qsort
(
pItems
,
cItems
,
sizeof
(
struct
MATCHED_ITEM
),
sort_comp_merit
);
pListFilters
=
QUARTZ_CompList_Alloc
();
if
(
pListFilters
==
NULL
)
{
hr
=
E_OUTOFMEMORY
;
goto
err
;
}
for
(
n
=
0
;
n
<
cItems
;
n
++
)
{
TRACE
(
"merit %08lx
\n
"
,
pItems
[
n
].
dwMerit
);
hr
=
QUARTZ_CompList_AddComp
(
pListFilters
,
(
IUnknown
*
)
pItems
[
n
].
pMonFilter
,
NULL
,
0
);
if
(
FAILED
(
hr
)
)
goto
err
;
}
hr
=
QUARTZ_CreateEnumUnknown
(
&
IID_IEnumMoniker
,
(
void
**
)
ppEnumMoniker
,
pListFilters
);
if
(
FAILED
(
hr
)
)
goto
err
;
...
...
@@ -1040,8 +1069,17 @@ err:
QUARTZ_FreeMem
(
pbFilterData
);
if
(
prf2
!=
NULL
)
QUARTZ_FreeMem
(
prf2
);
if
(
pList
!=
NULL
)
QUARTZ_CompList_Free
(
pList
);
if
(
pItems
!=
NULL
&&
cItems
>
0
)
{
for
(
n
=
0
;
n
<
cItems
;
n
++
)
{
if
(
pItems
[
n
].
pMonFilter
!=
NULL
)
IMoniker_Release
(
pItems
[
n
].
pMonFilter
);
}
QUARTZ_FreeMem
(
pItems
);
}
if
(
pListFilters
!=
NULL
)
QUARTZ_CompList_Free
(
pListFilters
);
TRACE
(
"returns %08lx
\n
"
,
hr
);
...
...
dlls/quartz/main.c
View file @
0f1f42ea
...
...
@@ -108,6 +108,7 @@ static const QUARTZ_CLASSENTRY QUARTZ_ClassList[] =
{
&
CLSID_URLReader
,
&
QUARTZ_CreateURLReader
},
{
&
CLSID_AVIDec
,
&
QUARTZ_CreateAVIDec
},
{
&
CLSID_Colour
,
&
QUARTZ_CreateColour
},
{
&
CLSID_ACMWrapper
,
&
QUARTZ_CreateACMWrapper
},
{
&
CLSID_FileWriter
,
&
QUARTZ_CreateFileWriter
},
{
NULL
,
NULL
},
};
...
...
dlls/quartz/mpgparse.c
View file @
0f1f42ea
...
...
@@ -389,9 +389,18 @@ static HRESULT CMPGParseImpl_GetStreamType( CParserImpl* pImpl, ULONG nStreamInd
pmpg1wav
=
(
MPEG1WAVEFORMAT
*
)
pmt
->
pbFormat
;
switch
(
hdrbuf
[
1
]
&
0x6
)
{
case
0x6
:
pmpg1wav
->
fwHeadLayer
=
ACM_MPEG_LAYER1
;
case
0x4
:
pmpg1wav
->
fwHeadLayer
=
ACM_MPEG_LAYER2
;
case
0x2
:
pmpg1wav
->
fwHeadLayer
=
ACM_MPEG_LAYER3
;
case
0x6
:
TRACE
(
"layer 1
\n
"
);
pmpg1wav
->
fwHeadLayer
=
ACM_MPEG_LAYER1
;
break
;
case
0x4
:
TRACE
(
"layer 2
\n
"
);
pmpg1wav
->
fwHeadLayer
=
ACM_MPEG_LAYER2
;
break
;
case
0x2
:
TRACE
(
"layer 3
\n
"
);
pmpg1wav
->
fwHeadLayer
=
ACM_MPEG_LAYER3
;
break
;
default:
return
E_FAIL
;
}
...
...
@@ -412,10 +421,22 @@ static HRESULT CMPGParseImpl_GetStreamType( CParserImpl* pImpl, ULONG nStreamInd
switch
(
hdrbuf
[
3
]
&
0xc0
)
{
case
0x00
:
pmpg1wav
->
fwHeadMode
=
ACM_MPEG_STEREO
;
case
0x40
:
pmpg1wav
->
fwHeadMode
=
ACM_MPEG_JOINTSTEREO
;
case
0x80
:
pmpg1wav
->
fwHeadMode
=
ACM_MPEG_DUALCHANNEL
;
case
0xc0
:
pmpg1wav
->
fwHeadMode
=
ACM_MPEG_SINGLECHANNEL
;
case
0x00
:
TRACE
(
"STEREO
\n
"
);
pmpg1wav
->
fwHeadMode
=
ACM_MPEG_STEREO
;
break
;
case
0x40
:
TRACE
(
"JOINTSTEREO
\n
"
);
pmpg1wav
->
fwHeadMode
=
ACM_MPEG_JOINTSTEREO
;
break
;
case
0x80
:
TRACE
(
"DUALCHANNEL
\n
"
);
pmpg1wav
->
fwHeadMode
=
ACM_MPEG_DUALCHANNEL
;
break
;
case
0xc0
:
TRACE
(
"SINGLECHANNEL
\n
"
);
pmpg1wav
->
fwHeadMode
=
ACM_MPEG_SINGLECHANNEL
;
break
;
}
pmpg1wav
->
fwHeadModeExt
=
(
hdrbuf
[
3
]
&
0x30
)
>>
4
;
/* FIXME?? */
...
...
@@ -436,9 +457,18 @@ static HRESULT CMPGParseImpl_GetStreamType( CParserImpl* pImpl, ULONG nStreamInd
pmpg1wav
->
wfx
.
nChannels
=
(
pmpg1wav
->
fwHeadMode
!=
ACM_MPEG_SINGLECHANNEL
)
?
2
:
1
;
switch
(
hdrbuf
[
2
]
&
0x0c
)
{
case
0x00
:
pmpg1wav
->
wfx
.
nSamplesPerSec
=
44100
;
case
0x01
:
pmpg1wav
->
wfx
.
nSamplesPerSec
=
48000
;
case
0x02
:
pmpg1wav
->
wfx
.
nSamplesPerSec
=
32000
;
case
0x00
:
TRACE
(
"44100Hz
\n
"
);
pmpg1wav
->
wfx
.
nSamplesPerSec
=
44100
;
break
;
case
0x01
:
TRACE
(
"48000Hz
\n
"
);
pmpg1wav
->
wfx
.
nSamplesPerSec
=
48000
;
break
;
case
0x02
:
TRACE
(
"32000Hz
\n
"
);
pmpg1wav
->
wfx
.
nSamplesPerSec
=
32000
;
break
;
default:
return
E_FAIL
;
}
pmpg1wav
->
wfx
.
nAvgBytesPerSec
=
pmpg1wav
->
dwHeadBitrate
>>
3
;
...
...
dlls/quartz/parser.c
View file @
0f1f42ea
...
...
@@ -465,6 +465,10 @@ DWORD WINAPI CParserImplThread_Entry( LPVOID pv )
}
}
This
->
m_dwThreadId
=
0
;
This
->
basefilter
.
bIntermediateState
=
FALSE
;
SetEvent
(
This
->
m_hEventInit
);
return
0
;
}
...
...
@@ -579,12 +583,21 @@ HRESULT CParserImpl_BeginThread( CParserImpl* This )
(
LPVOID
)
This
,
0
,
&
This
->
m_dwThreadId
);
if
(
This
->
m_hThread
==
(
HANDLE
)
NULL
)
{
CloseHandle
(
This
->
m_hEventInit
);
This
->
m_hEventInit
=
(
HANDLE
)
NULL
;
return
E_FAIL
;
}
hEvents
[
0
]
=
This
->
m_hEventInit
;
hEvents
[
1
]
=
This
->
m_hThread
;
dwRes
=
WaitForMultipleObjects
(
2
,
hEvents
,
FALSE
,
INFINITE
);
ResetEvent
(
This
->
m_hEventInit
);
CloseHandle
(
This
->
m_hThread
);
This
->
m_hThread
=
(
HANDLE
)
NULL
;
if
(
dwRes
!=
WAIT_OBJECT_0
)
return
E_FAIL
;
...
...
@@ -592,25 +605,26 @@ HRESULT CParserImpl_BeginThread( CParserImpl* This )
}
static
void
CParserImpl_EndThread
(
CParserImpl
*
This
)
BOOL
CParserImpl_EndThread
(
CParserImpl
*
This
,
BOOL
bAsync
)
{
DWORD
dwThreadId
;
TRACE
(
"(%p)
\n
"
,
This
);
if
(
This
->
m_hThread
!=
(
HANDLE
)
NULL
)
{
if
(
PostThreadMessageA
(
This
->
m_dwThreadId
,
QUARTZ_MSG_EXITTHREAD
,
0
,
0
)
)
{
WaitForSingleObject
(
This
->
m_hThread
,
INFINITE
);
}
CloseHandle
(
This
->
m_hThread
);
This
->
m_hThread
=
(
HANDLE
)
NULL
;
This
->
m_dwThreadId
=
0
;
}
dwThreadId
=
This
->
m_dwThreadId
;
if
(
This
->
m_hEventInit
!=
(
HANDLE
)
NULL
)
{
if
(
dwThreadId
!=
0
)
/* FIXME? */
PostThreadMessageA
(
dwThreadId
,
QUARTZ_MSG_EXITTHREAD
,
0
,
0
);
if
(
bAsync
)
return
FALSE
;
WaitForSingleObject
(
This
->
m_hEventInit
,
INFINITE
);
CloseHandle
(
This
->
m_hEventInit
);
This
->
m_hEventInit
=
(
HANDLE
)
NULL
;
}
return
TRUE
;
}
static
...
...
@@ -713,7 +727,7 @@ static HRESULT CParserImpl_OnInactive( CBaseFilterImpl* pImpl )
hr
=
CParserImpl_BeginThread
(
This
);
if
(
FAILED
(
hr
)
)
{
CParserImpl_EndThread
(
This
);
CParserImpl_EndThread
(
This
,
FALSE
);
return
hr
;
}
...
...
@@ -726,8 +740,11 @@ static HRESULT CParserImpl_OnStop( CBaseFilterImpl* pImpl )
FIXME
(
"(%p)
\n
"
,
This
);
CParserImpl_EndThread
(
This
);
This
->
basefilter
.
bIntermediateState
=
TRUE
;
if
(
!
CParserImpl_EndThread
(
This
,
TRUE
)
)
return
VFW_S_STATE_INTERMEDIATE
;
This
->
basefilter
.
bIntermediateState
=
FALSE
;
return
NOERROR
;
}
...
...
@@ -857,8 +874,9 @@ static HRESULT CParserInPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
{
CParserInPinImpl_THIS
(
pImpl
,
pin
);
CParserImpl_OnInactive
(
&
This
->
pParser
->
basefilter
);
CParserImpl_OnStop
(
&
This
->
pParser
->
basefilter
);
/* assume the graph is already stopped */
/*CParserImpl_OnInactive(&This->pParser->basefilter);*/
/*CParserImpl_OnStop(&This->pParser->basefilter);*/
if
(
This
->
pParser
->
m_pHandler
->
pUninitParser
!=
NULL
)
This
->
pParser
->
m_pHandler
->
pUninitParser
(
This
->
pParser
);
CParserImpl_SetAsyncReader
(
This
->
pParser
,
NULL
);
...
...
dlls/quartz/xform.h
View file @
0f1f42ea
...
...
@@ -121,5 +121,6 @@ HRESULT QUARTZ_CreateTransformBaseOutPin(
HRESULT
QUARTZ_CreateAVIDec
(
IUnknown
*
punkOuter
,
void
**
ppobj
);
HRESULT
QUARTZ_CreateColour
(
IUnknown
*
punkOuter
,
void
**
ppobj
);
HRESULT
QUARTZ_CreateACMWrapper
(
IUnknown
*
punkOuter
,
void
**
ppobj
);
#endif
/* WINE_DSHOW_XFORM_H */
winedefault.reg
View file @
0f1f42ea
...
...
@@ -527,6 +527,46 @@
30,74,79,33,00,00,00,00,60,00,00,00,60,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
# CLSID_MPEG1Splitter
[HKEY_CLASSES_ROOT\CLSID\{336475D0-942A-11CE-A870-00AA002FEAB5}]
@="MPEG1 Splitter"
[HKEY_CLASSES_ROOT\CLSID\{336475D0-942A-11CE-A870-00AA002FEAB5}\InprocServer32]
@="quartz.dll"
"ThreadingModel"="Both"
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{336475D0-942A-11CE-A870-00AA002FEAB5}]
"CLSID"="{336475D0-942A-11CE-A870-00AA002FEAB5}"
"FriendlyName"="MPEG1 Splitter"
# FilterData of generic transform filter.
"FilterData"=hex:02,00,00,00,00,00,60,00,02,00,00,00,00,00,00,00,\
30,70,69,33,00,00,00,00,00,00,00,00,\
01,00,00,00,00,00,00,00,00,00,00,00,\
30,74,79,33,00,00,00,00,60,00,00,00,60,00,00,00,\
31,70,69,33,08,00,00,00,00,00,00,00,\
01,00,00,00,00,00,00,00,00,00,00,00,\
30,74,79,33,00,00,00,00,60,00,00,00,60,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
# CLSID_ACMWrapper
[HKEY_CLASSES_ROOT\CLSID\{6A08CF80-0E18-11CF-A24D-0020AFD79767}]
@="ACM Wrapper"
[HKEY_CLASSES_ROOT\CLSID\{6A08CF80-0E18-11CF-A24D-0020AFD79767}\InprocServer32]
@="quartz.dll"
"ThreadingModel"="Both"
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{6A08CF80-0E18-11CF-A24D-0020AFD79767}]
"CLSID"="{6A08CF80-0E18-11CF-A24D-0020AFD79767}"
"FriendlyName"="ACM Wrapper"
# FilterData of generic transform filter.
"FilterData"=hex:02,00,00,00,00,00,60,00,02,00,00,00,00,00,00,00,\
30,70,69,33,00,00,00,00,00,00,00,00,\
01,00,00,00,00,00,00,00,00,00,00,00,\
30,74,79,33,00,00,00,00,60,00,00,00,60,00,00,00,\
31,70,69,33,08,00,00,00,00,00,00,00,\
01,00,00,00,00,00,00,00,00,00,00,00,\
30,74,79,33,00,00,00,00,60,00,00,00,60,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
#
...
...
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