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
b0719b12
Commit
b0719b12
authored
Oct 21, 2002
by
Michael Günnewig
Committed by
Alexandre Julliard
Oct 21, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New AVI streamhandlers for audio and video streams.
parent
115260c4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1711 additions
and
5 deletions
+1711
-5
Makefile.in
dlls/avifil32/Makefile.in
+2
-0
acmstream.c
dlls/avifil32/acmstream.c
+733
-0
factory.c
dlls/avifil32/factory.c
+5
-5
icmstream.c
dlls/avifil32/icmstream.c
+971
-0
No files found.
dlls/avifil32/Makefile.in
View file @
b0719b12
...
...
@@ -11,11 +11,13 @@ LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE
=
$(MODULE)
.tmp.o
C_SRCS
=
\
acmstream.c
\
api.c
\
avifile.c
\
extrachunk.c
\
factory.c
\
getframe.c
\
icmstream.c
\
wavfile.c
RC_SRCS
=
\
...
...
dlls/avifil32/acmstream.c
0 → 100644
View file @
b0719b12
/*
* Copyright 2002 Michael Gnnewig
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
#include "winerror.h"
#include "windowsx.h"
#include "mmsystem.h"
#include "vfw.h"
#include "msacm.h"
#include "avifile_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
avifile
);
/***********************************************************************/
static
HRESULT
WINAPI
ACMStream_fnQueryInterface
(
IAVIStream
*
iface
,
REFIID
refiid
,
LPVOID
*
obj
);
static
ULONG
WINAPI
ACMStream_fnAddRef
(
IAVIStream
*
iface
);
static
ULONG
WINAPI
ACMStream_fnRelease
(
IAVIStream
*
iface
);
static
HRESULT
WINAPI
ACMStream_fnCreate
(
IAVIStream
*
iface
,
LPARAM
lParam1
,
LPARAM
lParam2
);
static
HRESULT
WINAPI
ACMStream_fnInfo
(
IAVIStream
*
iface
,
AVISTREAMINFOW
*
psi
,
LONG
size
);
static
LONG
WINAPI
ACMStream_fnFindSample
(
IAVIStream
*
iface
,
LONG
pos
,
LONG
flags
);
static
HRESULT
WINAPI
ACMStream_fnReadFormat
(
IAVIStream
*
iface
,
LONG
pos
,
LPVOID
format
,
LONG
*
formatsize
);
static
HRESULT
WINAPI
ACMStream_fnSetFormat
(
IAVIStream
*
iface
,
LONG
pos
,
LPVOID
format
,
LONG
formatsize
);
static
HRESULT
WINAPI
ACMStream_fnRead
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
,
LPVOID
buffer
,
LONG
buffersize
,
LONG
*
bytesread
,
LONG
*
samplesread
);
static
HRESULT
WINAPI
ACMStream_fnWrite
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
,
LPVOID
buffer
,
LONG
buffersize
,
DWORD
flags
,
LONG
*
sampwritten
,
LONG
*
byteswritten
);
static
HRESULT
WINAPI
ACMStream_fnDelete
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
);
static
HRESULT
WINAPI
ACMStream_fnReadData
(
IAVIStream
*
iface
,
DWORD
fcc
,
LPVOID
lp
,
LONG
*
lpread
);
static
HRESULT
WINAPI
ACMStream_fnWriteData
(
IAVIStream
*
iface
,
DWORD
fcc
,
LPVOID
lp
,
LONG
size
);
static
HRESULT
WINAPI
ACMStream_fnSetInfo
(
IAVIStream
*
iface
,
AVISTREAMINFOW
*
info
,
LONG
infolen
);
struct
ICOM_VTABLE
(
IAVIStream
)
iacmst
=
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ACMStream_fnQueryInterface
,
ACMStream_fnAddRef
,
ACMStream_fnRelease
,
ACMStream_fnCreate
,
ACMStream_fnInfo
,
ACMStream_fnFindSample
,
ACMStream_fnReadFormat
,
ACMStream_fnSetFormat
,
ACMStream_fnRead
,
ACMStream_fnWrite
,
ACMStream_fnDelete
,
ACMStream_fnReadData
,
ACMStream_fnWriteData
,
ACMStream_fnSetInfo
};
typedef
struct
_IAVIStreamImpl
{
/* IUnknown stuff */
ICOM_VFIELD
(
IAVIStream
);
DWORD
ref
;
/* IAVIStream stuff */
PAVISTREAM
pStream
;
AVISTREAMINFOW
sInfo
;
HACMSTREAM
has
;
LPWAVEFORMATEX
lpInFormat
;
LONG
cbInFormat
;
LPWAVEFORMATEX
lpOutFormat
;
LONG
cbOutFormat
;
ACMSTREAMHEADER
acmStreamHdr
;
}
IAVIStreamImpl
;
/***********************************************************************/
#define CONVERT_STREAM_to_THIS(a) { \
acmStreamSize(This->has,(a)*This->lpInFormat->nBlockAlign,\
&(a), ACM_STREAMSIZEF_SOURCE); \
(a) /= This->lpOutFormat->nBlockAlign; }
#define CONVERT_THIS_to_STREAM(a) { \
acmStreamSize(This->has,(a)*This->lpOutFormat->nBlockAlign,\
&(a), ACM_STREAMSIZEF_DESTINATION); \
(a) /= This->lpInFormat->nBlockAlign; }
static
HRESULT
AVIFILE_OpenCompressor
(
IAVIStreamImpl
*
This
);
HRESULT
AVIFILE_CreateACMStream
(
REFIID
riid
,
LPVOID
*
ppv
)
{
IAVIStreamImpl
*
pstream
;
HRESULT
hr
;
assert
(
riid
!=
NULL
&&
ppv
!=
NULL
);
*
ppv
=
NULL
;
pstream
=
(
IAVIStreamImpl
*
)
LocalAlloc
(
LPTR
,
sizeof
(
IAVIStreamImpl
));
if
(
pstream
==
NULL
)
return
AVIERR_MEMORY
;
ICOM_VTBL
(
pstream
)
=
&
iacmst
;
hr
=
IUnknown_QueryInterface
((
IUnknown
*
)
pstream
,
riid
,
ppv
);
if
(
FAILED
(
hr
))
LocalFree
((
HLOCAL
)
pstream
);
return
hr
;
}
static
HRESULT
WINAPI
ACMStream_fnQueryInterface
(
IAVIStream
*
iface
,
REFIID
refiid
,
LPVOID
*
obj
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%s,%p)
\n
"
,
iface
,
debugstr_guid
(
refiid
),
obj
);
if
(
IsEqualGUID
(
&
IID_IUnknown
,
refiid
)
||
IsEqualGUID
(
&
IID_IAVIStream
,
refiid
))
{
*
obj
=
This
;
IAVIStream_AddRef
(
iface
);
return
S_OK
;
}
return
OLE_E_ENUM_NOMORE
;
}
static
ULONG
WINAPI
ACMStream_fnAddRef
(
IAVIStream
*
iface
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p) -> %ld
\n
"
,
iface
,
This
->
ref
+
1
);
/* also add reference to the nested stream */
if
(
This
->
pStream
!=
NULL
)
IAVIStream_AddRef
(
This
->
pStream
);
return
++
(
This
->
ref
);
}
static
ULONG
WINAPI
ACMStream_fnRelease
(
IAVIStream
*
iface
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p) -> %ld
\n
"
,
iface
,
This
->
ref
-
1
);
if
(
This
->
ref
==
0
)
{
/* destruct */
if
(
This
->
has
!=
(
HACMSTREAM
)
NULL
)
{
if
(
This
->
acmStreamHdr
.
fdwStatus
&
ACMSTREAMHEADER_STATUSF_PREPARED
)
acmStreamUnprepareHeader
(
This
->
has
,
&
This
->
acmStreamHdr
,
0
);
acmStreamClose
(
This
->
has
,
0
);
This
->
has
=
(
HACMSTREAM
)
NULL
;
}
if
(
This
->
acmStreamHdr
.
pbSrc
!=
NULL
)
{
GlobalFreePtr
(
This
->
acmStreamHdr
.
pbSrc
);
This
->
acmStreamHdr
.
pbSrc
=
NULL
;
}
if
(
This
->
acmStreamHdr
.
pbDst
!=
NULL
)
{
GlobalFreePtr
(
This
->
acmStreamHdr
.
pbDst
);
This
->
acmStreamHdr
.
pbDst
=
NULL
;
}
if
(
This
->
lpInFormat
!=
NULL
)
{
GlobalFreePtr
(
This
->
lpInFormat
);
This
->
lpInFormat
=
NULL
;
This
->
cbInFormat
=
0
;
}
if
(
This
->
lpOutFormat
!=
NULL
)
{
GlobalFreePtr
(
This
->
lpOutFormat
);
This
->
lpOutFormat
=
NULL
;
This
->
cbOutFormat
=
0
;
}
if
(
This
->
pStream
!=
NULL
)
{
IAVIStream_Release
(
This
->
pStream
);
This
->
pStream
=
NULL
;
}
LocalFree
((
HLOCAL
)
This
);
return
0
;
}
/* also release reference to the nested stream */
if
(
This
->
pStream
!=
NULL
)
IAVIStream_Release
(
This
->
pStream
);
return
--
This
->
ref
;
}
/* lParam1: PAVISTREAM
* lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
*/
static
HRESULT
WINAPI
ACMStream_fnCreate
(
IAVIStream
*
iface
,
LPARAM
lParam1
,
LPARAM
lParam2
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,0x%08lX,0x%08lX)
\n
"
,
iface
,
lParam1
,
lParam2
);
/* check for swapped parameters */
if
((
LPVOID
)
lParam1
!=
NULL
&&
((
LPAVICOMPRESSOPTIONS
)
lParam1
)
->
fccType
==
streamtypeAUDIO
)
{
register
LPARAM
tmp
=
lParam1
;
lParam1
=
lParam2
;
lParam2
=
tmp
;
}
if
((
LPVOID
)
lParam1
==
NULL
)
return
AVIERR_BADPARAM
;
IAVIStream_Info
((
PAVISTREAM
)
lParam1
,
&
This
->
sInfo
,
sizeof
(
This
->
sInfo
));
if
(
This
->
sInfo
.
fccType
!=
streamtypeAUDIO
)
return
AVIERR_ERROR
;
/* error in registry or AVIMakeCompressedStream */
This
->
sInfo
.
fccHandler
=
0
;
/* be paranoid */
/* FIXME: check ACM version? Which version does we need? */
if
((
LPVOID
)
lParam2
!=
NULL
)
{
/* We only need the format from the compress-options */
if
(((
LPAVICOMPRESSOPTIONS
)
lParam2
)
->
fccType
==
streamtypeAUDIO
)
lParam2
=
(
LPARAM
)((
LPAVICOMPRESSOPTIONS
)
lParam2
)
->
lpFormat
;
if
(((
LPWAVEFORMATEX
)
lParam2
)
->
wFormatTag
!=
WAVE_FORMAT_PCM
)
This
->
cbOutFormat
=
sizeof
(
WAVEFORMATEX
)
+
((
LPWAVEFORMATEX
)
lParam2
)
->
cbSize
;
else
This
->
cbOutFormat
=
sizeof
(
PCMWAVEFORMAT
);
This
->
lpOutFormat
=
(
LPWAVEFORMATEX
)
GlobalAllocPtr
(
GHND
,
This
->
cbOutFormat
);
if
(
This
->
lpOutFormat
==
NULL
)
return
AVIERR_MEMORY
;
memcpy
(
This
->
lpOutFormat
,
(
LPVOID
)
lParam2
,
This
->
cbOutFormat
);
}
else
{
This
->
lpOutFormat
=
NULL
;
This
->
cbOutFormat
=
0
;
}
This
->
pStream
=
(
PAVISTREAM
)
lParam1
;
IAVIStream_AddRef
(
This
->
pStream
);
return
AVIERR_OK
;
}
static
HRESULT
WINAPI
ACMStream_fnInfo
(
IAVIStream
*
iface
,
LPAVISTREAMINFOW
psi
,
LONG
size
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%p,%ld)
\n
"
,
iface
,
psi
,
size
);
if
(
psi
==
NULL
)
return
AVIERR_BADPARAM
;
if
(
size
<
0
)
return
AVIERR_BADSIZE
;
/* Need codec to correct some values in structure */
if
(
This
->
has
==
(
HACMSTREAM
)
NULL
)
{
HRESULT
hr
=
AVIFILE_OpenCompressor
(
This
);
if
(
FAILED
(
hr
))
return
hr
;
}
memcpy
(
psi
,
&
This
->
sInfo
,
min
(
size
,
sizeof
(
This
->
sInfo
)));
if
(
size
<
sizeof
(
This
->
sInfo
))
return
AVIERR_BUFFERTOOSMALL
;
return
AVIERR_OK
;
}
static
LONG
WINAPI
ACMStream_fnFindSample
(
IAVIStream
*
iface
,
LONG
pos
,
LONG
flags
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%ld,0x%08lX)
\n
"
,
iface
,
pos
,
flags
);
if
(
flags
&
FIND_FROM_START
)
{
pos
=
This
->
sInfo
.
dwStart
;
flags
&=
~
(
FIND_FROM_START
|
FIND_PREV
);
flags
|=
FIND_NEXT
;
}
/* convert pos from our 'space' to This->pStream's one */
CONVERT_THIS_to_STREAM
(
pos
);
/* ask stream */
pos
=
IAVIStream_FindSample
(
This
->
pStream
,
pos
,
flags
);
if
(
pos
!=
-
1
)
{
/* convert pos back to our 'space' if it's no size or physical pos */
if
((
flags
&
FIND_RET
)
==
0
)
CONVERT_STREAM_to_THIS
(
pos
);
}
return
pos
;
}
static
HRESULT
WINAPI
ACMStream_fnReadFormat
(
IAVIStream
*
iface
,
LONG
pos
,
LPVOID
format
,
LONG
*
formatsize
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%ld,%p,%p)
\n
"
,
iface
,
pos
,
format
,
formatsize
);
if
(
formatsize
==
NULL
)
return
AVIERR_BADPARAM
;
if
(
This
->
has
==
(
HACMSTREAM
)
NULL
)
{
HRESULT
hr
=
AVIFILE_OpenCompressor
(
This
);
if
(
FAILED
(
hr
))
return
hr
;
}
/* only interested in needed buffersize? */
if
(
format
==
NULL
||
*
formatsize
<=
0
)
{
*
formatsize
=
This
->
cbOutFormat
;
return
AVIERR_OK
;
}
/* copy initial format (only as much as will fit) */
memcpy
(
format
,
This
->
lpOutFormat
,
min
(
*
formatsize
,
This
->
cbOutFormat
));
if
(
*
formatsize
<
This
->
cbOutFormat
)
{
*
formatsize
=
This
->
cbOutFormat
;
return
AVIERR_BUFFERTOOSMALL
;
}
*
formatsize
=
This
->
cbOutFormat
;
return
AVIERR_OK
;
}
static
HRESULT
WINAPI
ACMStream_fnSetFormat
(
IAVIStream
*
iface
,
LONG
pos
,
LPVOID
format
,
LONG
formatsize
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
HRESULT
hr
;
TRACE
(
"(%p,%ld,%p,%ld)
\n
"
,
iface
,
pos
,
format
,
formatsize
);
/* check parameters */
if
(
format
==
NULL
||
formatsize
<=
0
)
return
AVIERR_BADPARAM
;
/* Input format already known?
* Changing is unsupported, but be quiet if it's the same */
if
(
This
->
lpInFormat
!=
NULL
)
{
if
(
This
->
cbInFormat
!=
formatsize
||
memcmp
(
format
,
This
->
lpInFormat
,
formatsize
)
!=
0
)
return
AVIERR_UNSUPPORTED
;
return
AVIERR_OK
;
}
/* Does the nested stream support writing? */
if
((
This
->
sInfo
.
dwCaps
&
AVIFILECAPS_CANWRITE
)
==
0
)
return
AVIERR_READONLY
;
This
->
lpInFormat
=
(
LPWAVEFORMATEX
)
GlobalAllocPtr
(
GMEM_MOVEABLE
,
formatsize
);
if
(
This
->
lpInFormat
==
NULL
)
return
AVIERR_MEMORY
;
This
->
cbInFormat
=
formatsize
;
memcpy
(
This
->
lpInFormat
,
format
,
formatsize
);
/* initialize formats and get compressor */
hr
=
AVIFILE_OpenCompressor
(
This
);
if
(
FAILED
(
hr
))
return
hr
;
CONVERT_THIS_to_STREAM
(
pos
);
/* tell the nested stream the new format */
return
IAVIStream_SetFormat
(
This
->
pStream
,
pos
,
This
->
lpOutFormat
,
This
->
cbOutFormat
);
}
static
HRESULT
WINAPI
ACMStream_fnRead
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
,
LPVOID
buffer
,
LONG
buffersize
,
LPLONG
bytesread
,
LPLONG
samplesread
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
HRESULT
hr
;
LONG
size
;
TRACE
(
"(%p,%ld,%ld,%p,%ld,%p,%p)
\n
"
,
iface
,
start
,
samples
,
buffer
,
buffersize
,
bytesread
,
samplesread
);
/* clear return parameters if given */
if
(
bytesread
!=
NULL
)
*
bytesread
=
0
;
if
(
samplesread
!=
NULL
)
*
samplesread
=
0
;
/* Do we have our compressor? */
if
(
This
->
has
==
(
HACMSTREAM
)
NULL
)
{
hr
=
AVIFILE_OpenCompressor
(
This
);
if
(
FAILED
(
hr
))
return
hr
;
}
/* only need to pass through? */
if
(
This
->
cbInFormat
==
This
->
cbOutFormat
&&
memcmp
(
This
->
lpInFormat
,
This
->
lpOutFormat
,
This
->
cbInFormat
)
==
0
)
{
return
IAVIStream_Read
(
This
->
pStream
,
start
,
samples
,
buffer
,
buffersize
,
bytesread
,
samplesread
);
}
/* read as much as fit? */
if
(
samples
==
-
1
)
samples
=
buffersize
/
This
->
lpOutFormat
->
nBlockAlign
;
/* limit to buffersize */
if
(
samples
*
This
->
lpOutFormat
->
nBlockAlign
>
buffersize
)
samples
=
buffersize
/
This
->
lpOutFormat
->
nBlockAlign
;
/* only return needed size? */
if
(
buffer
==
NULL
||
buffersize
<=
0
||
samples
==
0
)
{
if
(
bytesread
==
NULL
&&
samplesread
==
NULL
)
return
AVIERR_BADPARAM
;
if
(
bytesread
!=
NULL
)
*
bytesread
=
samples
*
This
->
lpOutFormat
->
nBlockAlign
;
if
(
samplesread
!=
NULL
)
*
samplesread
=
samples
;
return
AVIERR_OK
;
}
/* map our positions to pStream positions */
CONVERT_THIS_to_STREAM
(
start
);
/* our needed internal buffersize */
size
=
samples
*
This
->
lpInFormat
->
nBlockAlign
;
/* Need to free destination buffer used for writing? */
if
(
This
->
acmStreamHdr
.
pbDst
!=
NULL
)
{
GlobalFreePtr
(
This
->
acmStreamHdr
.
pbDst
);
This
->
acmStreamHdr
.
pbDst
=
NULL
;
This
->
acmStreamHdr
.
dwDstUser
=
0
;
}
/* need bigger source buffer? */
if
(
This
->
acmStreamHdr
.
pbSrc
==
NULL
||
This
->
acmStreamHdr
.
dwSrcUser
<
size
)
{
This
->
acmStreamHdr
.
pbSrc
=
GlobalReAllocPtr
(
This
->
acmStreamHdr
.
pbSrc
,
size
,
GMEM_MOVEABLE
);
if
(
This
->
acmStreamHdr
.
pbSrc
==
NULL
)
return
AVIERR_MEMORY
;
This
->
acmStreamHdr
.
dwSrcUser
=
size
;
}
This
->
acmStreamHdr
.
cbStruct
=
sizeof
(
This
->
acmStreamHdr
);
This
->
acmStreamHdr
.
cbSrcLengthUsed
=
0
;
This
->
acmStreamHdr
.
cbDstLengthUsed
=
0
;
This
->
acmStreamHdr
.
cbSrcLength
=
size
;
/* read source data */
hr
=
IAVIStream_Read
(
This
->
pStream
,
start
,
-
1
,
This
->
acmStreamHdr
.
pbSrc
,
This
->
acmStreamHdr
.
cbSrcLength
,
&
This
->
acmStreamHdr
.
cbSrcLength
,
NULL
);
if
(
FAILED
(
hr
)
||
This
->
acmStreamHdr
.
cbSrcLength
==
0
)
return
hr
;
/* need to prepare stream? */
This
->
acmStreamHdr
.
pbDst
=
buffer
;
This
->
acmStreamHdr
.
cbDstLength
=
buffersize
;
if
((
This
->
acmStreamHdr
.
fdwStatus
&
ACMSTREAMHEADER_STATUSF_PREPARED
)
==
0
)
{
if
(
acmStreamPrepareHeader
(
This
->
has
,
&
This
->
acmStreamHdr
,
0
)
!=
S_OK
)
{
This
->
acmStreamHdr
.
pbDst
=
NULL
;
This
->
acmStreamHdr
.
cbDstLength
=
0
;
return
AVIERR_COMPRESSOR
;
}
}
/* now do the conversion */
/* FIXME: use ACM_CONVERTF_* flags */
if
(
acmStreamConvert
(
This
->
has
,
&
This
->
acmStreamHdr
,
0
)
!=
S_OK
)
hr
=
AVIERR_COMPRESSOR
;
This
->
acmStreamHdr
.
pbDst
=
NULL
;
This
->
acmStreamHdr
.
cbDstLength
=
0
;
/* fill out return parameters if given */
if
(
bytesread
!=
NULL
)
*
bytesread
=
This
->
acmStreamHdr
.
cbDstLengthUsed
;
if
(
samplesread
!=
NULL
)
*
samplesread
=
This
->
acmStreamHdr
.
cbDstLengthUsed
/
This
->
lpOutFormat
->
nBlockAlign
;
return
hr
;
}
static
HRESULT
WINAPI
ACMStream_fnWrite
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
,
LPVOID
buffer
,
LONG
buffersize
,
DWORD
flags
,
LPLONG
sampwritten
,
LPLONG
byteswritten
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
HRESULT
hr
;
LONG
size
;
TRACE
(
"(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)
\n
"
,
iface
,
start
,
samples
,
buffer
,
buffersize
,
flags
,
sampwritten
,
byteswritten
);
/* clear return parameters if given */
if
(
sampwritten
!=
NULL
)
*
sampwritten
=
0
;
if
(
byteswritten
!=
NULL
)
*
byteswritten
=
0
;
/* check parameters */
if
(
buffer
==
NULL
&&
(
buffersize
>
0
||
samples
>
0
))
return
AVIERR_BADPARAM
;
/* Have we write capability? */
if
((
This
->
sInfo
.
dwCaps
&
AVIFILECAPS_CANWRITE
)
==
0
)
return
AVIERR_READONLY
;
/* also need a compressor */
if
(
This
->
has
==
(
HACMSTREAM
)
NULL
)
return
AVIERR_NOCOMPRESSOR
;
/* map our sizes to pStream sizes */
size
=
buffersize
;
CONVERT_THIS_to_STREAM
(
size
);
CONVERT_THIS_to_STREAM
(
start
);
/* no bytes to write? -- short circuit */
if
(
size
==
0
)
{
return
IAVIStream_Write
(
This
->
pStream
,
-
1
,
samples
,
buffer
,
size
,
flags
,
sampwritten
,
byteswritten
);
}
/* Need to free source buffer used for reading? */
if
(
This
->
acmStreamHdr
.
pbSrc
!=
NULL
)
{
GlobalFreePtr
(
This
->
acmStreamHdr
.
pbSrc
);
This
->
acmStreamHdr
.
pbSrc
=
NULL
;
This
->
acmStreamHdr
.
dwSrcUser
=
0
;
}
/* Need bigger destination buffer? */
if
(
This
->
acmStreamHdr
.
pbDst
==
NULL
||
This
->
acmStreamHdr
.
dwDstUser
<
size
)
{
This
->
acmStreamHdr
.
pbDst
=
GlobalReAllocPtr
(
This
->
acmStreamHdr
.
pbDst
,
size
,
GMEM_MOVEABLE
);
if
(
This
->
acmStreamHdr
.
pbDst
==
NULL
)
return
AVIERR_MEMORY
;
This
->
acmStreamHdr
.
dwDstUser
=
size
;
}
This
->
acmStreamHdr
.
cbStruct
=
sizeof
(
This
->
acmStreamHdr
);
This
->
acmStreamHdr
.
cbSrcLengthUsed
=
0
;
This
->
acmStreamHdr
.
cbDstLengthUsed
=
0
;
This
->
acmStreamHdr
.
cbDstLength
=
This
->
acmStreamHdr
.
dwDstUser
;
/* need to prepare stream? */
This
->
acmStreamHdr
.
pbSrc
=
buffer
;
This
->
acmStreamHdr
.
cbSrcLength
=
buffersize
;
if
((
This
->
acmStreamHdr
.
fdwStatus
&
ACMSTREAMHEADER_STATUSF_PREPARED
)
==
0
)
{
if
(
acmStreamPrepareHeader
(
This
->
has
,
&
This
->
acmStreamHdr
,
0
)
!=
S_OK
)
{
This
->
acmStreamHdr
.
pbSrc
=
NULL
;
This
->
acmStreamHdr
.
cbSrcLength
=
0
;
return
AVIERR_COMPRESSOR
;
}
}
/* now do the conversion */
/* FIXME: use ACM_CONVERTF_* flags */
if
(
acmStreamConvert
(
This
->
has
,
&
This
->
acmStreamHdr
,
0
)
!=
S_OK
)
hr
=
AVIERR_COMPRESSOR
;
else
hr
=
AVIERR_OK
;
This
->
acmStreamHdr
.
pbSrc
=
NULL
;
This
->
acmStreamHdr
.
cbSrcLength
=
0
;
if
(
FAILED
(
hr
))
return
hr
;
return
IAVIStream_Write
(
This
->
pStream
,
-
1
,
This
->
acmStreamHdr
.
cbDstLengthUsed
/
This
->
lpOutFormat
->
nBlockAlign
,
This
->
acmStreamHdr
.
pbDst
,
This
->
acmStreamHdr
.
cbDstLengthUsed
,
flags
,
sampwritten
,
byteswritten
);
}
static
HRESULT
WINAPI
ACMStream_fnDelete
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%ld,%ld)
\n
"
,
iface
,
start
,
samples
);
/* check parameters */
if
(
start
<
0
||
samples
<
0
)
return
AVIERR_BADPARAM
;
/* Delete before start of stream? */
if
(
start
+
samples
<
This
->
sInfo
.
dwStart
)
return
AVIERR_OK
;
/* Delete after end of stream? */
if
(
start
>
This
->
sInfo
.
dwLength
)
return
AVIERR_OK
;
/* For the rest we need write capability */
if
((
This
->
sInfo
.
dwCaps
&
AVIFILECAPS_CANWRITE
)
==
0
)
return
AVIERR_READONLY
;
/* A compressor is also neccessary */
if
(
This
->
has
==
(
HACMSTREAM
)
NULL
)
return
AVIERR_NOCOMPRESSOR
;
/* map our positions to pStream positions */
CONVERT_THIS_to_STREAM
(
start
);
CONVERT_THIS_to_STREAM
(
samples
);
return
IAVIStream_Delete
(
This
->
pStream
,
start
,
samples
);
}
static
HRESULT
WINAPI
ACMStream_fnReadData
(
IAVIStream
*
iface
,
DWORD
fcc
,
LPVOID
lp
,
LPLONG
lpread
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,0x%08lX,%p,%p)
\n
"
,
iface
,
fcc
,
lp
,
lpread
);
assert
(
This
->
pStream
!=
NULL
);
return
IAVIStream_ReadData
(
This
->
pStream
,
fcc
,
lp
,
lpread
);
}
static
HRESULT
WINAPI
ACMStream_fnWriteData
(
IAVIStream
*
iface
,
DWORD
fcc
,
LPVOID
lp
,
LONG
size
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,0x%08lx,%p,%ld)
\n
"
,
iface
,
fcc
,
lp
,
size
);
assert
(
This
->
pStream
!=
NULL
);
return
IAVIStream_WriteData
(
This
->
pStream
,
fcc
,
lp
,
size
);
}
static
HRESULT
WINAPI
ACMStream_fnSetInfo
(
IAVIStream
*
iface
,
LPAVISTREAMINFOW
info
,
LONG
infolen
)
{
FIXME
(
"(%p,%p,%ld): stub
\n
"
,
iface
,
info
,
infolen
);
return
E_FAIL
;
}
/***********************************************************************/
static
HRESULT
AVIFILE_OpenCompressor
(
IAVIStreamImpl
*
This
)
{
HRESULT
hr
;
/* pre-conditions */
assert
(
This
!=
NULL
);
assert
(
This
->
pStream
!=
NULL
);
if
(
This
->
has
!=
(
HACMSTREAM
)
NULL
)
return
AVIERR_OK
;
if
(
This
->
lpInFormat
==
NULL
)
{
/* decode or encode the data from pStream */
hr
=
AVIStreamFormatSize
(
This
->
pStream
,
This
->
sInfo
.
dwStart
,
&
This
->
cbInFormat
);
if
(
FAILED
(
hr
))
return
hr
;
This
->
lpInFormat
=
(
LPWAVEFORMATEX
)
GlobalAllocPtr
(
GMEM_MOVEABLE
,
This
->
cbInFormat
);
if
(
This
->
lpInFormat
==
NULL
)
return
AVIERR_MEMORY
;
hr
=
IAVIStream_ReadFormat
(
This
->
pStream
,
This
->
sInfo
.
dwStart
,
This
->
lpInFormat
,
&
This
->
cbInFormat
);
if
(
FAILED
(
hr
))
return
hr
;
if
(
This
->
lpOutFormat
==
NULL
)
{
/* we must decode to default format */
This
->
cbOutFormat
=
sizeof
(
PCMWAVEFORMAT
);
This
->
lpOutFormat
=
(
LPWAVEFORMATEX
)
GlobalAllocPtr
(
GHND
,
This
->
cbOutFormat
);
if
(
This
->
lpOutFormat
==
NULL
)
return
AVIERR_MEMORY
;
This
->
lpOutFormat
->
wFormatTag
=
WAVE_FORMAT_PCM
;
if
(
acmFormatSuggest
(
NULL
,
This
->
lpInFormat
,
This
->
lpOutFormat
,
This
->
cbOutFormat
,
ACM_FORMATSUGGESTF_WFORMATTAG
)
!=
S_OK
)
return
AVIERR_NOCOMPRESSOR
;
}
}
else
if
(
This
->
lpOutFormat
==
NULL
)
return
AVIERR_ERROR
;
/* To what should I encode? */
if
(
acmStreamOpen
(
&
This
->
has
,
NULL
,
This
->
lpInFormat
,
This
->
lpOutFormat
,
NULL
,
0
,
0
,
ACM_STREAMOPENF_NONREALTIME
)
!=
S_OK
)
return
AVIERR_NOCOMPRESSOR
;
/* update AVISTREAMINFO structure */
This
->
sInfo
.
dwSampleSize
=
This
->
lpOutFormat
->
nBlockAlign
;
This
->
sInfo
.
dwScale
=
This
->
lpOutFormat
->
nBlockAlign
;
This
->
sInfo
.
dwRate
=
This
->
lpOutFormat
->
nAvgBytesPerSec
;
This
->
sInfo
.
dwQuality
=
ICQUALITY_DEFAULT
;
SetRectEmpty
(
&
This
->
sInfo
.
rcFrame
);
/* convert positions ansd sizes to output format */
CONVERT_STREAM_to_THIS
(
This
->
sInfo
.
dwStart
);
CONVERT_STREAM_to_THIS
(
This
->
sInfo
.
dwLength
);
CONVERT_STREAM_to_THIS
(
This
->
sInfo
.
dwSuggestedBufferSize
);
return
AVIERR_OK
;
}
dlls/avifil32/factory.c
View file @
b0719b12
...
...
@@ -127,7 +127,7 @@ static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,
{
ICOM_THIS
(
IClassFactoryImpl
,
iface
);
FIXME
(
"(%p,%p,%s,%p): partial stub!
\n
"
,
iface
,
pOuter
,
debugstr_guid
(
riid
),
TRACE
(
"(%p,%p,%s,%p)
\n
"
,
iface
,
pOuter
,
debugstr_guid
(
riid
),
ppobj
);
if
(
ppobj
==
NULL
||
pOuter
!=
NULL
)
...
...
@@ -136,12 +136,12 @@ static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,
if
(
IsEqualGUID
(
&
CLSID_AVIFile
,
&
This
->
clsid
))
return
AVIFILE_CreateAVIFile
(
riid
,
ppobj
);
/* if (IsEqualGUID(&CLSID_ICMStream, &This->clsid)) */
/* return AVIFILE_CreateICMStream(riid,ppobj); */
if
(
IsEqualGUID
(
&
CLSID_ICMStream
,
&
This
->
clsid
))
return
AVIFILE_CreateICMStream
(
riid
,
ppobj
);
if
(
IsEqualGUID
(
&
CLSID_WAVFile
,
&
This
->
clsid
))
return
AVIFILE_CreateWAVFile
(
riid
,
ppobj
);
/* if (IsEqualGUID(&CLSID_ACMStream, &This->clsid)) */
/* return AVIFILE_CreateACMStream(riid,ppobj); */
if
(
IsEqualGUID
(
&
CLSID_ACMStream
,
&
This
->
clsid
))
return
AVIFILE_CreateACMStream
(
riid
,
ppobj
);
return
E_NOINTERFACE
;
}
...
...
dlls/avifil32/icmstream.c
0 → 100644
View file @
b0719b12
/*
* Copyright 2002 Michael Gnnewig
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
#include "winerror.h"
#include "windowsx.h"
#include "mmsystem.h"
#include "vfw.h"
#include "msacm.h"
#include "avifile_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
avifile
);
#define MAX_FRAMESIZE (16 * 1024 * 1024)
#define MAX_FRAMESIZE_DIFF 512
/***********************************************************************/
static
HRESULT
WINAPI
ICMStream_fnQueryInterface
(
IAVIStream
*
iface
,
REFIID
refiid
,
LPVOID
*
obj
);
static
ULONG
WINAPI
ICMStream_fnAddRef
(
IAVIStream
*
iface
);
static
ULONG
WINAPI
ICMStream_fnRelease
(
IAVIStream
*
iface
);
static
HRESULT
WINAPI
ICMStream_fnCreate
(
IAVIStream
*
iface
,
LPARAM
lParam1
,
LPARAM
lParam2
);
static
HRESULT
WINAPI
ICMStream_fnInfo
(
IAVIStream
*
iface
,
AVISTREAMINFOW
*
psi
,
LONG
size
);
static
LONG
WINAPI
ICMStream_fnFindSample
(
IAVIStream
*
iface
,
LONG
pos
,
LONG
flags
);
static
HRESULT
WINAPI
ICMStream_fnReadFormat
(
IAVIStream
*
iface
,
LONG
pos
,
LPVOID
format
,
LONG
*
formatsize
);
static
HRESULT
WINAPI
ICMStream_fnSetFormat
(
IAVIStream
*
iface
,
LONG
pos
,
LPVOID
format
,
LONG
formatsize
);
static
HRESULT
WINAPI
ICMStream_fnRead
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
,
LPVOID
buffer
,
LONG
buffersize
,
LONG
*
bytesread
,
LONG
*
samplesread
);
static
HRESULT
WINAPI
ICMStream_fnWrite
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
,
LPVOID
buffer
,
LONG
buffersize
,
DWORD
flags
,
LONG
*
sampwritten
,
LONG
*
byteswritten
);
static
HRESULT
WINAPI
ICMStream_fnDelete
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
);
static
HRESULT
WINAPI
ICMStream_fnReadData
(
IAVIStream
*
iface
,
DWORD
fcc
,
LPVOID
lp
,
LONG
*
lpread
);
static
HRESULT
WINAPI
ICMStream_fnWriteData
(
IAVIStream
*
iface
,
DWORD
fcc
,
LPVOID
lp
,
LONG
size
);
static
HRESULT
WINAPI
ICMStream_fnSetInfo
(
IAVIStream
*
iface
,
AVISTREAMINFOW
*
info
,
LONG
infolen
);
struct
ICOM_VTABLE
(
IAVIStream
)
iicmst
=
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ICMStream_fnQueryInterface
,
ICMStream_fnAddRef
,
ICMStream_fnRelease
,
ICMStream_fnCreate
,
ICMStream_fnInfo
,
ICMStream_fnFindSample
,
ICMStream_fnReadFormat
,
ICMStream_fnSetFormat
,
ICMStream_fnRead
,
ICMStream_fnWrite
,
ICMStream_fnDelete
,
ICMStream_fnReadData
,
ICMStream_fnWriteData
,
ICMStream_fnSetInfo
};
typedef
struct
_IAVIStreamImpl
{
/* IUnknown stuff */
ICOM_VFIELD
(
IAVIStream
);
DWORD
ref
;
/* IAVIStream stuff */
PAVISTREAM
pStream
;
AVISTREAMINFOW
sInfo
;
PGETFRAME
pg
;
HIC
hic
;
DWORD
dwICMFlags
;
LONG
lCurrent
;
LONG
lLastKey
;
LONG
lKeyFrameEvery
;
DWORD
dwLastQuality
;
DWORD
dwBytesPerFrame
;
DWORD
dwUnusedBytes
;
LPBITMAPINFOHEADER
lpbiCur
;
/* current frame */
LPVOID
lpCur
;
LPBITMAPINFOHEADER
lpbiPrev
;
/* previous frame */
LPVOID
lpPrev
;
LPBITMAPINFOHEADER
lpbiOutput
;
/* output format of codec */
LONG
cbOutput
;
LPBITMAPINFOHEADER
lpbiInput
;
/* input format for codec */
LONG
cbInput
;
}
IAVIStreamImpl
;
/***********************************************************************/
static
HRESULT
AVIFILE_EncodeFrame
(
IAVIStreamImpl
*
This
,
LPBITMAPINFOHEADER
lpbi
,
LPVOID
lpBits
);
static
HRESULT
AVIFILE_OpenGetFrame
(
IAVIStreamImpl
*
This
);
inline
void
AVIFILE_Reset
(
IAVIStreamImpl
*
This
)
{
This
->
lCurrent
=
-
1
;
This
->
lLastKey
=
0
;
This
->
dwLastQuality
=
ICQUALITY_HIGH
;
This
->
dwUnusedBytes
=
0
;
}
HRESULT
AVIFILE_CreateICMStream
(
REFIID
riid
,
LPVOID
*
ppv
)
{
IAVIStreamImpl
*
pstream
;
HRESULT
hr
;
assert
(
riid
!=
NULL
&&
ppv
!=
NULL
);
*
ppv
=
NULL
;
pstream
=
(
IAVIStreamImpl
*
)
LocalAlloc
(
LPTR
,
sizeof
(
IAVIStreamImpl
));
if
(
pstream
==
NULL
)
return
AVIERR_MEMORY
;
ICOM_VTBL
(
pstream
)
=
&
iicmst
;
AVIFILE_Reset
(
pstream
);
hr
=
IUnknown_QueryInterface
((
IUnknown
*
)
pstream
,
riid
,
ppv
);
if
(
FAILED
(
hr
))
LocalFree
((
HLOCAL
)
pstream
);
return
hr
;
}
static
HRESULT
WINAPI
ICMStream_fnQueryInterface
(
IAVIStream
*
iface
,
REFIID
refiid
,
LPVOID
*
obj
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%s,%p)
\n
"
,
iface
,
debugstr_guid
(
refiid
),
obj
);
if
(
IsEqualGUID
(
&
IID_IUnknown
,
refiid
)
||
IsEqualGUID
(
&
IID_IAVIStream
,
refiid
))
{
*
obj
=
This
;
IAVIStream_AddRef
(
iface
);
return
S_OK
;
}
return
OLE_E_ENUM_NOMORE
;
}
static
ULONG
WINAPI
ICMStream_fnAddRef
(
IAVIStream
*
iface
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p) -> %ld
\n
"
,
iface
,
This
->
ref
+
1
);
/* also add reference to the nested stream */
if
(
This
->
pStream
!=
NULL
)
IAVIStream_AddRef
(
This
->
pStream
);
return
++
(
This
->
ref
);
}
static
ULONG
WINAPI
ICMStream_fnRelease
(
IAVIStream
*
iface
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p) -> %ld
\n
"
,
iface
,
This
->
ref
-
1
);
if
(
This
->
ref
==
0
)
{
/* destruct */
if
(
This
->
pg
!=
NULL
)
{
AVIStreamGetFrameClose
(
This
->
pg
);
This
->
pg
=
NULL
;
}
if
(
This
->
pStream
!=
NULL
)
{
IAVIStream_Release
(
This
->
pStream
);
This
->
pStream
=
NULL
;
}
if
(
This
->
hic
!=
(
HIC
)
NULL
)
{
if
(
This
->
lpbiPrev
!=
NULL
)
{
ICDecompressEnd
(
This
->
hic
);
GlobalFreePtr
(
This
->
lpbiPrev
);
This
->
lpbiPrev
=
NULL
;
This
->
lpPrev
=
NULL
;
}
ICCompressEnd
(
This
->
hic
);
This
->
hic
=
(
HIC
)
NULL
;
}
if
(
This
->
lpbiCur
!=
NULL
)
{
GlobalFreePtr
(
This
->
lpbiCur
);
This
->
lpbiCur
=
NULL
;
This
->
lpCur
=
NULL
;
}
if
(
This
->
lpbiOutput
!=
NULL
)
{
GlobalFreePtr
(
This
->
lpbiOutput
);
This
->
lpbiOutput
=
NULL
;
This
->
cbOutput
=
0
;
}
if
(
This
->
lpbiInput
!=
NULL
)
{
GlobalFreePtr
(
This
->
lpbiInput
);
This
->
lpbiInput
=
NULL
;
This
->
cbInput
=
0
;
}
LocalFree
((
HLOCAL
)
This
);
return
0
;
}
/* also release reference to the nested stream */
if
(
This
->
pStream
!=
NULL
)
IAVIStream_Release
(
This
->
pStream
);
return
--
This
->
ref
;
}
/* lParam1: PAVISTREAM
* lParam2: LPAVICOMPRESSOPTIONS
*/
static
HRESULT
WINAPI
ICMStream_fnCreate
(
IAVIStream
*
iface
,
LPARAM
lParam1
,
LPARAM
lParam2
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
ICINFO
icinfo
;
ICCOMPRESSFRAMES
icFrames
;
LPAVICOMPRESSOPTIONS
pco
=
(
LPAVICOMPRESSOPTIONS
)
lParam2
;
TRACE
(
"(%p,0x%08lX,0x%08lX)
\n
"
,
iface
,
lParam1
,
lParam2
);
/* check parameter */
if
((
LPVOID
)
lParam1
==
NULL
)
return
AVIERR_BADPARAM
;
/* get infos from stream */
IAVIStream_Info
((
PAVISTREAM
)
lParam1
,
&
This
->
sInfo
,
sizeof
(
This
->
sInfo
));
if
(
This
->
sInfo
.
fccType
!=
streamtypeVIDEO
)
return
AVIERR_ERROR
;
/* error in registry or AVIMakeCompressedStream */
/* add reference to the stream */
This
->
pStream
=
(
PAVISTREAM
)
lParam1
;
IAVIStream_AddRef
(
This
->
pStream
);
AVIFILE_Reset
(
This
);
if
(
pco
!=
NULL
&&
pco
->
fccHandler
!=
comptypeDIB
)
{
/* we should compress */
This
->
sInfo
.
fccHandler
=
pco
->
fccHandler
;
This
->
hic
=
ICOpen
(
ICTYPE_VIDEO
,
pco
->
fccHandler
,
ICMODE_COMPRESS
);
if
(
This
->
hic
==
(
HIC
)
NULL
)
return
AVIERR_NOCOMPRESSOR
;
/* restore saved state of codec */
if
(
pco
->
cbParms
>
0
&&
pco
->
lpParms
!=
NULL
)
{
ICSetState
(
This
->
hic
,
pco
->
lpParms
,
pco
->
cbParms
);
}
/* set quality -- resolve default quality */
This
->
sInfo
.
dwQuality
=
pco
->
dwQuality
;
if
(
pco
->
dwQuality
==
ICQUALITY_DEFAULT
)
This
->
sInfo
.
dwQuality
=
ICGetDefaultQuality
(
This
->
hic
);
/* get capabilities of codec */
ICGetInfo
(
This
->
hic
,
&
icinfo
,
sizeof
(
icinfo
));
This
->
dwICMFlags
=
icinfo
.
dwFlags
;
/* use keyframes? */
if
((
pco
->
dwFlags
&
AVICOMPRESSF_KEYFRAMES
)
&&
(
icinfo
.
dwFlags
&
(
VIDCF_TEMPORAL
|
VIDCF_FASTTEMPORALC
)))
{
This
->
lKeyFrameEvery
=
pco
->
dwKeyFrameEvery
;
}
else
This
->
lKeyFrameEvery
=
1
;
/* use datarate? */
if
((
pco
->
dwFlags
&
AVICOMPRESSF_DATARATE
))
{
/* Do we have a chance to reduce size to desired one? */
if
((
icinfo
.
dwFlags
&
(
VIDCF_CRUNCH
|
VIDCF_QUALITY
))
==
0
)
return
AVIERR_NOCOMPRESSOR
;
assert
(
This
->
sInfo
.
dwRate
!=
0
);
This
->
dwBytesPerFrame
=
MulDiv
(
pco
->
dwBytesPerSecond
,
This
->
sInfo
.
dwScale
,
This
->
sInfo
.
dwRate
);
}
else
{
pco
->
dwBytesPerSecond
=
0
;
This
->
dwBytesPerFrame
=
0
;
}
if
(
icinfo
.
dwFlags
&
VIDCF_COMPRESSFRAMES
)
{
memset
(
&
icFrames
,
0
,
sizeof
(
icFrames
));
icFrames
.
lpbiOutput
=
This
->
lpbiOutput
;
icFrames
.
lpbiInput
=
This
->
lpbiInput
;
icFrames
.
lFrameCount
=
This
->
sInfo
.
dwLength
;
icFrames
.
lQuality
=
This
->
sInfo
.
dwQuality
;
icFrames
.
lDataRate
=
pco
->
dwBytesPerSecond
;
icFrames
.
lKeyRate
=
This
->
lKeyFrameEvery
;
icFrames
.
dwRate
=
This
->
sInfo
.
dwRate
;
icFrames
.
dwScale
=
This
->
sInfo
.
dwScale
;
ICSendMessage
(
This
->
hic
,
ICM_COMPRESS_FRAMES_INFO
,
(
LPARAM
)
&
icFrames
,
(
LPARAM
)
sizeof
(
icFrames
));
}
}
else
This
->
sInfo
.
fccHandler
=
comptypeDIB
;
return
AVIERR_OK
;
}
static
HRESULT
WINAPI
ICMStream_fnInfo
(
IAVIStream
*
iface
,
LPAVISTREAMINFOW
psi
,
LONG
size
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%p,%ld)
\n
"
,
iface
,
psi
,
size
);
if
(
psi
==
NULL
)
return
AVIERR_BADPARAM
;
if
(
size
<
0
)
return
AVIERR_BADSIZE
;
memcpy
(
psi
,
&
This
->
sInfo
,
min
(
size
,
sizeof
(
This
->
sInfo
)));
if
(
size
<
sizeof
(
This
->
sInfo
))
return
AVIERR_BUFFERTOOSMALL
;
return
AVIERR_OK
;
}
static
LONG
WINAPI
ICMStream_fnFindSample
(
IAVIStream
*
iface
,
LONG
pos
,
LONG
flags
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%ld,0x%08lX)
\n
"
,
iface
,
pos
,
flags
);
if
(
flags
&
FIND_FROM_START
)
{
pos
=
This
->
sInfo
.
dwStart
;
flags
&=
~
(
FIND_FROM_START
|
FIND_PREV
);
flags
|=
FIND_NEXT
;
}
if
(
flags
&
FIND_RET
)
WARN
(
": FIND_RET flags will be ignored!
\n
"
);
if
(
flags
&
FIND_KEY
)
{
if
(
This
->
hic
==
(
HIC
)
NULL
)
return
pos
;
/* we decompress so every frame is a keyframe */
if
(
flags
&
FIND_PREV
)
{
/* need to read old or new frames? */
if
(
This
->
lLastKey
<=
pos
||
pos
<
This
->
lCurrent
)
IAVIStream_Read
(
iface
,
pos
,
1
,
NULL
,
0
,
NULL
,
NULL
);
return
This
->
lLastKey
;
}
}
else
if
(
flags
&
FIND_ANY
)
{
return
pos
;
/* We really don't know, reread is to expensive, so guess. */
}
else
if
(
flags
&
FIND_FORMAT
)
{
if
(
flags
&
FIND_PREV
)
return
0
;
}
return
-
1
;
}
static
HRESULT
WINAPI
ICMStream_fnReadFormat
(
IAVIStream
*
iface
,
LONG
pos
,
LPVOID
format
,
LONG
*
formatsize
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
LPBITMAPINFOHEADER
lpbi
;
HRESULT
hr
;
TRACE
(
"(%p,%ld,%p,%p)
\n
"
,
iface
,
pos
,
format
,
formatsize
);
if
(
formatsize
==
NULL
)
return
AVIERR_BADPARAM
;
if
(
This
->
pg
==
NULL
)
{
hr
=
AVIFILE_OpenGetFrame
(
This
);
if
(
FAILED
(
hr
))
return
hr
;
}
lpbi
=
(
LPBITMAPINFOHEADER
)
AVIStreamGetFrame
(
This
->
pg
,
pos
);
if
(
lpbi
==
NULL
)
return
AVIERR_MEMORY
;
if
(
This
->
hic
==
(
HIC
)
NULL
)
{
LONG
size
=
lpbi
->
biSize
+
lpbi
->
biClrUsed
*
sizeof
(
RGBQUAD
);
if
(
size
>
0
)
{
if
(
This
->
sInfo
.
dwSuggestedBufferSize
<
lpbi
->
biSizeImage
)
This
->
sInfo
.
dwSuggestedBufferSize
=
lpbi
->
biSizeImage
;
This
->
cbOutput
=
size
;
if
(
format
!=
NULL
)
{
if
(
This
->
lpbiOutput
!=
NULL
)
memcpy
(
format
,
This
->
lpbiOutput
,
min
(
*
formatsize
,
This
->
cbOutput
));
else
memcpy
(
format
,
lpbi
,
min
(
*
formatsize
,
size
));
}
}
}
else
if
(
format
!=
NULL
)
memcpy
(
format
,
This
->
lpbiOutput
,
min
(
*
formatsize
,
This
->
cbOutput
));
if
(
*
formatsize
<
This
->
cbOutput
)
hr
=
AVIERR_BUFFERTOOSMALL
;
else
hr
=
AVIERR_OK
;
*
formatsize
=
This
->
cbOutput
;
return
hr
;
}
static
HRESULT
WINAPI
ICMStream_fnSetFormat
(
IAVIStream
*
iface
,
LONG
pos
,
LPVOID
format
,
LONG
formatsize
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%ld,%p,%ld)
\n
"
,
iface
,
pos
,
format
,
formatsize
);
/* check parameters */
if
(
format
==
NULL
||
formatsize
<=
0
)
return
AVIERR_BADPARAM
;
/* We can only accept RGB data for writing */
if
(((
LPBITMAPINFOHEADER
)
format
)
->
biCompression
!=
BI_RGB
)
{
WARN
(
": need RGB data as input
\n
"
);
return
AVIERR_UNSUPPORTED
;
}
/* Input format already known?
* Changing of palette is supported, but be quiet if it's the same */
if
(
This
->
lpbiInput
!=
NULL
)
{
if
(
This
->
cbInput
!=
formatsize
)
return
AVIERR_UNSUPPORTED
;
if
(
memcmp
(
format
,
This
->
lpbiInput
,
formatsize
)
==
0
)
return
AVIERR_OK
;
}
/* Does the nested stream support writing? */
if
((
This
->
sInfo
.
dwCaps
&
AVIFILECAPS_CANWRITE
)
==
0
)
return
AVIERR_READONLY
;
/* check if frame is already written */
if
(
This
->
sInfo
.
dwLength
+
This
->
sInfo
.
dwStart
>
pos
)
return
AVIERR_UNSUPPORTED
;
/* check if we should compress */
if
(
This
->
sInfo
.
fccHandler
==
0
||
This
->
sInfo
.
fccHandler
==
mmioFOURCC
(
'N'
,
'O'
,
'N'
,
'E'
))
This
->
sInfo
.
fccHandler
=
comptypeDIB
;
/* only pass through? */
if
(
This
->
sInfo
.
fccHandler
==
comptypeDIB
)
return
IAVIStream_SetFormat
(
This
->
pStream
,
pos
,
format
,
formatsize
);
/* initial format setting? */
if
(
This
->
lpbiInput
==
NULL
)
{
LONG
size
;
assert
(
This
->
hic
!=
(
HIC
)
NULL
);
/* get memory for input format */
This
->
lpbiInput
=
(
LPBITMAPINFOHEADER
)
GlobalAllocPtr
(
GHND
,
formatsize
);
if
(
This
->
lpbiInput
==
NULL
)
return
AVIERR_MEMORY
;
This
->
cbInput
=
formatsize
;
memcpy
(
This
->
lpbiInput
,
format
,
formatsize
);
/* get output format */
size
=
ICCompressGetFormatSize
(
This
->
hic
,
This
->
lpbiInput
);
if
(
size
<
sizeof
(
BITMAPINFOHEADER
))
return
AVIERR_COMPRESSOR
;
This
->
lpbiOutput
=
(
LPBITMAPINFOHEADER
)
GlobalAllocPtr
(
GHND
,
size
);
if
(
This
->
lpbiOutput
==
NULL
)
return
AVIERR_MEMORY
;
This
->
cbOutput
=
size
;
if
(
ICCompressGetFormat
(
This
->
hic
,
This
->
lpbiInput
,
This
->
lpbiOutput
)
<
S_OK
)
return
AVIERR_COMPRESSOR
;
/* update AVISTREAMINFO structure */
This
->
sInfo
.
rcFrame
.
right
=
This
->
sInfo
.
rcFrame
.
left
+
This
->
lpbiOutput
->
biWidth
;
This
->
sInfo
.
rcFrame
.
bottom
=
This
->
sInfo
.
rcFrame
.
top
+
This
->
lpbiOutput
->
biHeight
;
/* prepare codec for compression */
if
(
ICCompressBegin
(
This
->
hic
,
This
->
lpbiInput
,
This
->
lpbiOutput
)
!=
S_OK
)
return
AVIERR_COMPRESSOR
;
/* allocate memory for compressed frame */
size
=
ICCompressGetSize
(
This
->
hic
,
This
->
lpbiInput
,
This
->
lpbiOutput
);
This
->
lpbiCur
=
(
LPBITMAPINFOHEADER
)
GlobalAllocPtr
(
GMEM_MOVEABLE
,
This
->
cbOutput
+
size
);
if
(
This
->
lpbiCur
==
NULL
)
return
AVIERR_MEMORY
;
memcpy
(
This
->
lpbiCur
,
This
->
lpbiOutput
,
This
->
cbOutput
);
This
->
lpCur
=
DIBPTR
(
This
->
lpbiCur
);
/* allocate memory for last frame if needed */
if
(
This
->
lKeyFrameEvery
!=
1
&&
(
This
->
dwICMFlags
&
VIDCF_FASTTEMPORALC
)
==
0
)
{
size
=
ICDecompressGetFormatSize
(
This
->
hic
,
This
->
lpbiOutput
);
This
->
lpbiPrev
=
(
LPBITMAPINFOHEADER
)
GlobalAllocPtr
(
GHND
,
size
);
if
(
This
->
lpbiPrev
==
NULL
)
return
AVIERR_MEMORY
;
if
(
ICDecompressGetFormat
(
This
->
hic
,
This
->
lpbiOutput
,
This
->
lpbiPrev
)
<
S_OK
)
return
AVIERR_COMPRESSOR
;
if
(
This
->
lpbiPrev
->
biSizeImage
==
0
)
{
This
->
lpbiPrev
->
biSizeImage
=
DIBWIDTHBYTES
(
*
This
->
lpbiPrev
)
*
This
->
lpbiPrev
->
biHeight
;
}
/* get memory for format and picture */
size
+=
This
->
lpbiPrev
->
biSizeImage
;
This
->
lpbiPrev
=
(
LPBITMAPINFOHEADER
)
GlobalReAllocPtr
(
This
->
lpbiPrev
,
size
,
GMEM_MOVEABLE
);
if
(
This
->
lpbiPrev
==
NULL
)
return
AVIERR_MEMORY
;
This
->
lpPrev
=
DIBPTR
(
This
->
lpbiPrev
);
/* prepare codec also for decompression */
if
(
ICDecompressBegin
(
This
->
hic
,
This
->
lpbiOutput
,
This
->
lpbiPrev
)
!=
S_OK
)
return
AVIERR_COMPRESSOR
;
}
}
else
{
/* format change -- check that's only the palette */
LPBITMAPINFOHEADER
lpbi
=
(
LPBITMAPINFOHEADER
)
format
;
if
(
lpbi
->
biSize
!=
This
->
lpbiInput
->
biSize
||
lpbi
->
biWidth
!=
This
->
lpbiInput
->
biWidth
||
lpbi
->
biHeight
!=
This
->
lpbiInput
->
biHeight
||
lpbi
->
biBitCount
!=
This
->
lpbiInput
->
biBitCount
||
lpbi
->
biPlanes
!=
This
->
lpbiInput
->
biPlanes
||
lpbi
->
biCompression
!=
This
->
lpbiInput
->
biCompression
||
lpbi
->
biClrUsed
!=
This
->
lpbiInput
->
biClrUsed
)
return
AVIERR_UNSUPPORTED
;
/* get new output format */
if
(
ICCompressGetFormat
(
This
->
hic
,
lpbi
,
This
->
lpbiOutput
)
<
S_OK
)
return
AVIERR_BADFORMAT
;
/* restart compression */
ICCompressEnd
(
This
->
hic
);
if
(
ICCompressBegin
(
This
->
hic
,
lpbi
,
This
->
lpbiOutput
)
!=
S_OK
)
return
AVIERR_COMPRESSOR
;
/* check if we need to restart decompresion also */
if
(
This
->
lKeyFrameEvery
!=
1
&&
(
This
->
dwICMFlags
&
VIDCF_FASTTEMPORALC
)
==
0
)
{
ICDecompressEnd
(
This
->
hic
);
if
(
ICDecompressGetFormat
(
This
->
hic
,
This
->
lpbiOutput
,
This
->
lpbiPrev
)
<
S_OK
)
return
AVIERR_COMPRESSOR
;
if
(
ICDecompressBegin
(
This
->
hic
,
This
->
lpbiOutput
,
This
->
lpbiPrev
)
!=
S_OK
)
return
AVIERR_COMPRESSOR
;
}
}
/* tell nested stream the new format */
return
IAVIStream_SetFormat
(
This
->
pStream
,
pos
,
This
->
lpbiOutput
,
This
->
cbOutput
);
}
static
HRESULT
WINAPI
ICMStream_fnRead
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
,
LPVOID
buffer
,
LONG
buffersize
,
LPLONG
bytesread
,
LPLONG
samplesread
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
LPBITMAPINFOHEADER
lpbi
;
TRACE
(
"(%p,%ld,%ld,%p,%ld,%p,%p)
\n
"
,
iface
,
start
,
samples
,
buffer
,
buffersize
,
bytesread
,
samplesread
);
/* clear return parameters if given */
if
(
bytesread
!=
NULL
)
*
bytesread
=
0
;
if
(
samplesread
!=
NULL
)
*
samplesread
=
0
;
if
(
samples
==
0
)
return
AVIERR_OK
;
/* check parameters */
if
(
samples
!=
1
&&
(
bytesread
==
NULL
&&
samplesread
==
NULL
))
return
AVIERR_BADPARAM
;
if
(
samples
==
-
1
)
/* read as much as we could */
samples
=
1
;
if
(
This
->
pg
==
NULL
)
{
HRESULT
hr
=
AVIFILE_OpenGetFrame
(
This
);
if
(
FAILED
(
hr
))
return
hr
;
}
/* compress or decompress? */
if
(
This
->
hic
==
(
HIC
)
NULL
)
{
/* decompress */
lpbi
=
(
LPBITMAPINFOHEADER
)
AVIStreamGetFrame
(
This
->
pg
,
start
);
if
(
lpbi
==
NULL
)
return
AVIERR_MEMORY
;
if
(
buffer
!=
NULL
&&
buffersize
>
0
)
{
/* check buffersize */
if
(
buffersize
<
lpbi
->
biSizeImage
)
return
AVIERR_BUFFERTOOSMALL
;
memcpy
(
buffer
,
DIBPTR
(
lpbi
),
lpbi
->
biSizeImage
);
}
/* fill out return parameters if given */
if
(
bytesread
!=
NULL
)
*
bytesread
=
lpbi
->
biSizeImage
;
}
else
{
/* compress */
if
(
This
->
lCurrent
>
start
)
AVIFILE_Reset
(
This
);
while
(
start
>
This
->
lCurrent
)
{
HRESULT
hr
;
lpbi
=
(
LPBITMAPINFOHEADER
)
AVIStreamGetFrame
(
This
->
pg
,
++
This
->
lCurrent
);
if
(
lpbi
==
NULL
)
{
AVIFILE_Reset
(
This
);
return
AVIERR_MEMORY
;
}
hr
=
AVIFILE_EncodeFrame
(
This
,
lpbi
,
DIBPTR
(
lpbi
));
if
(
FAILED
(
hr
))
{
AVIFILE_Reset
(
This
);
return
hr
;
}
}
if
(
buffer
!=
NULL
&&
buffersize
>
0
)
{
/* check buffersize */
if
(
This
->
lpbiCur
->
biSizeImage
>
buffersize
)
return
AVIERR_BUFFERTOOSMALL
;
memcpy
(
buffer
,
This
->
lpCur
,
This
->
lpbiCur
->
biSizeImage
);
}
/* fill out return parameters if given */
if
(
bytesread
!=
NULL
)
*
bytesread
=
This
->
lpbiCur
->
biSizeImage
;
}
/* fill out return parameters if given */
if
(
samplesread
!=
NULL
)
*
samplesread
=
1
;
return
AVIERR_OK
;
}
static
HRESULT
WINAPI
ICMStream_fnWrite
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
,
LPVOID
buffer
,
LONG
buffersize
,
DWORD
flags
,
LPLONG
sampwritten
,
LPLONG
byteswritten
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
HRESULT
hr
;
TRACE
(
"(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)
\n
"
,
iface
,
start
,
samples
,
buffer
,
buffersize
,
flags
,
sampwritten
,
byteswritten
);
/* clear return parameters if given */
if
(
sampwritten
!=
NULL
)
*
sampwritten
=
0
;
if
(
byteswritten
!=
NULL
)
*
byteswritten
=
0
;
/* check parameters */
if
(
buffer
==
NULL
&&
(
buffersize
>
0
||
samples
>
0
))
return
AVIERR_BADPARAM
;
if
(
This
->
sInfo
.
fccHandler
==
comptypeDIB
)
{
/* only pass through */
flags
|=
AVIIF_KEYFRAME
;
return
IAVIStream_Write
(
This
->
pStream
,
start
,
samples
,
buffer
,
buffersize
,
flags
,
sampwritten
,
byteswritten
);
}
else
{
/* compress data before writing to pStream */
if
(
samples
!=
1
&&
(
sampwritten
==
NULL
&&
byteswritten
==
NULL
))
return
AVIERR_UNSUPPORTED
;
This
->
lCurrent
=
start
;
hr
=
AVIFILE_EncodeFrame
(
This
,
This
->
lpbiInput
,
buffer
);
if
(
FAILED
(
hr
))
return
hr
;
if
(
This
->
lLastKey
==
start
)
flags
|=
AVIIF_KEYFRAME
;
return
IAVIStream_Write
(
This
->
pStream
,
start
,
samples
,
This
->
lpCur
,
This
->
lpbiCur
->
biSizeImage
,
flags
,
byteswritten
,
sampwritten
);
}
}
static
HRESULT
WINAPI
ICMStream_fnDelete
(
IAVIStream
*
iface
,
LONG
start
,
LONG
samples
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,%ld,%ld)
\n
"
,
iface
,
start
,
samples
);
return
IAVIStream_Delete
(
This
->
pStream
,
start
,
samples
);
}
static
HRESULT
WINAPI
ICMStream_fnReadData
(
IAVIStream
*
iface
,
DWORD
fcc
,
LPVOID
lp
,
LPLONG
lpread
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,0x%08lX,%p,%p)
\n
"
,
iface
,
fcc
,
lp
,
lpread
);
assert
(
This
->
pStream
!=
NULL
);
return
IAVIStream_ReadData
(
This
->
pStream
,
fcc
,
lp
,
lpread
);
}
static
HRESULT
WINAPI
ICMStream_fnWriteData
(
IAVIStream
*
iface
,
DWORD
fcc
,
LPVOID
lp
,
LONG
size
)
{
ICOM_THIS
(
IAVIStreamImpl
,
iface
);
TRACE
(
"(%p,0x%08lx,%p,%ld)
\n
"
,
iface
,
fcc
,
lp
,
size
);
assert
(
This
->
pStream
!=
NULL
);
return
IAVIStream_WriteData
(
This
->
pStream
,
fcc
,
lp
,
size
);
}
static
HRESULT
WINAPI
ICMStream_fnSetInfo
(
IAVIStream
*
iface
,
LPAVISTREAMINFOW
info
,
LONG
infolen
)
{
FIXME
(
"(%p,%p,%ld): stub
\n
"
,
iface
,
info
,
infolen
);
return
E_FAIL
;
}
/***********************************************************************/
static
HRESULT
AVIFILE_EncodeFrame
(
IAVIStreamImpl
*
This
,
LPBITMAPINFOHEADER
lpbi
,
LPVOID
lpBits
)
{
DWORD
dwMinQual
,
dwMaxQual
,
dwCurQual
;
DWORD
dwRequest
;
DWORD
icmFlags
=
0
;
DWORD
idxFlags
=
0
;
BOOL
bDecreasedQual
=
FALSE
;
BOOL
doSizeCheck
;
BOOL
noPrev
;
/* make lKeyFrameEvery and at start a keyframe */
if
((
This
->
lKeyFrameEvery
!=
0
&&
(
This
->
lCurrent
-
This
->
lLastKey
)
>=
This
->
lKeyFrameEvery
)
||
This
->
lCurrent
==
This
->
sInfo
.
dwStart
)
{
idxFlags
=
AVIIF_KEYFRAME
;
icmFlags
=
ICCOMPRESS_KEYFRAME
;
}
if
(
This
->
lKeyFrameEvery
!=
0
)
{
if
(
This
->
lCurrent
==
This
->
sInfo
.
dwStart
)
{
if
(
idxFlags
&
AVIIF_KEYFRAME
)
{
/* for keyframes allow to consume all unused bytes */
dwRequest
=
This
->
dwBytesPerFrame
+
This
->
dwUnusedBytes
;
This
->
dwUnusedBytes
=
0
;
}
else
{
/* for non-keyframes only allow something of the unused bytes to be consumed */
DWORD
tmp1
=
0
;
DWORD
tmp2
;
if
(
This
->
dwBytesPerFrame
>=
This
->
dwUnusedBytes
)
tmp1
=
This
->
dwBytesPerFrame
/
This
->
lKeyFrameEvery
;
tmp2
=
(
This
->
dwUnusedBytes
+
tmp1
)
/
This
->
lKeyFrameEvery
;
dwRequest
=
This
->
dwBytesPerFrame
-
tmp1
+
tmp2
;
This
->
dwUnusedBytes
-=
tmp2
;
}
}
else
dwRequest
=
MAX_FRAMESIZE
;
}
else
{
/* only one keyframe at start desired */
if
(
This
->
lCurrent
==
This
->
sInfo
.
dwStart
)
{
dwRequest
=
This
->
dwBytesPerFrame
+
This
->
dwUnusedBytes
;
This
->
dwUnusedBytes
=
0
;
}
else
dwRequest
=
MAX_FRAMESIZE
;
}
/* must we check for framesize to gain requested
* datarate or could we trust codec? */
doSizeCheck
=
(
dwRequest
!=
0
&&
((
This
->
dwICMFlags
&
(
VIDCF_CRUNCH
|
VIDCF_QUALITY
))
==
0
));
dwMaxQual
=
dwCurQual
=
This
->
sInfo
.
dwQuality
;
dwMinQual
=
ICQUALITY_LOW
;
noPrev
=
TRUE
;
if
((
icmFlags
&
ICCOMPRESS_KEYFRAME
)
==
0
&&
(
This
->
dwICMFlags
&
VIDCF_FASTTEMPORALC
)
==
0
)
noPrev
=
FALSE
;
do
{
DWORD
idxCkid
=
0
;
HRESULT
hr
;
hr
=
ICCompress
(
This
->
hic
,
icmFlags
,
This
->
lpbiCur
,
This
->
lpCur
,
lpbi
,
lpBits
,
&
idxCkid
,
&
idxFlags
,
This
->
lCurrent
,
dwRequest
,
dwCurQual
,
noPrev
?
NULL
:
This
->
lpbiPrev
,
noPrev
?
NULL
:
This
->
lpPrev
);
if
(
hr
==
ICERR_NEWPALETTE
)
{
FIXME
(
": codec has changed palette -- unhandled!
\n
"
);
}
else
if
(
hr
!=
ICERR_OK
)
return
AVIERR_COMPRESSOR
;
/* need to check for framesize */
if
(
!
doSizeCheck
)
break
;
if
(
dwRequest
>=
This
->
lpbiCur
->
biSizeImage
)
{
/* frame is smaller -- try to maximize quality */
if
(
dwMaxQual
-
dwCurQual
>
10
)
{
DWORD
tmp
=
dwRequest
/
8
;
if
(
tmp
<
MAX_FRAMESIZE_DIFF
)
tmp
=
MAX_FRAMESIZE_DIFF
;
if
(
tmp
<
dwRequest
-
This
->
lpbiCur
->
biSizeImage
&&
bDecreasedQual
)
{
tmp
=
dwCurQual
;
dwCurQual
=
(
dwMinQual
+
dwMaxQual
)
/
2
;
dwMinQual
=
tmp
;
continue
;
}
}
else
break
;
}
else
if
(
dwMaxQual
-
dwMinQual
<=
1
)
{
break
;
}
else
{
dwMaxQual
=
dwCurQual
;
if
(
bDecreasedQual
||
dwCurQual
==
This
->
dwLastQuality
)
dwCurQual
=
(
dwMinQual
+
dwMaxQual
)
/
2
;
else
FIXME
(
": no new quality computed min=%lu cur=%lu max=%lu last=%lu
\n
"
,
dwMinQual
,
dwCurQual
,
dwMaxQual
,
This
->
dwLastQuality
);
bDecreasedQual
=
TRUE
;
}
}
while
(
TRUE
);
/* remember some values */
This
->
dwLastQuality
=
dwCurQual
;
This
->
dwUnusedBytes
=
dwRequest
-
This
->
lpbiCur
->
biSizeImage
;
if
(
icmFlags
&
ICCOMPRESS_KEYFRAME
)
This
->
lLastKey
=
This
->
lCurrent
;
/* Does we manage previous frame? */
if
(
This
->
lpPrev
!=
NULL
&&
This
->
lKeyFrameEvery
!=
1
)
ICDecompress
(
This
->
hic
,
0
,
This
->
lpbiCur
,
This
->
lpCur
,
This
->
lpbiPrev
,
This
->
lpPrev
);
return
AVIERR_OK
;
}
static
HRESULT
AVIFILE_OpenGetFrame
(
IAVIStreamImpl
*
This
)
{
LPBITMAPINFOHEADER
lpbi
;
LONG
size
;
/* pre-conditions */
assert
(
This
!=
NULL
);
assert
(
This
->
pStream
!=
NULL
);
assert
(
This
->
pg
==
NULL
);
This
->
pg
=
AVIStreamGetFrameOpen
(
This
->
pStream
,
NULL
);
if
(
This
->
pg
==
NULL
)
return
AVIERR_ERROR
;
/* When we only decompress this is enough */
if
(
This
->
sInfo
.
fccHandler
==
comptypeDIB
)
return
AVIERR_OK
;
assert
(
This
->
hic
!=
(
HIC
)
NULL
);
assert
(
This
->
lpbiOutput
==
NULL
);
/* get input format */
lpbi
=
(
LPBITMAPINFOHEADER
)
AVIStreamGetFrame
(
This
->
pg
,
This
->
sInfo
.
dwStart
);
if
(
lpbi
==
NULL
)
return
AVIERR_MEMORY
;
/* get memory for output format */
size
=
ICCompressGetFormatSize
(
This
->
hic
,
lpbi
);
if
(
size
<
sizeof
(
BITMAPINFOHEADER
))
return
AVIERR_COMPRESSOR
;
This
->
lpbiOutput
=
(
LPBITMAPINFOHEADER
)
GlobalAllocPtr
(
GHND
,
size
);
if
(
This
->
lpbiOutput
==
NULL
)
return
AVIERR_MEMORY
;
This
->
cbOutput
=
size
;
if
(
ICCompressGetFormat
(
This
->
hic
,
lpbi
,
This
->
lpbiOutput
)
<
S_OK
)
return
AVIERR_BADFORMAT
;
/* update AVISTREAMINFO structure */
This
->
sInfo
.
rcFrame
.
right
=
This
->
sInfo
.
rcFrame
.
left
+
This
->
lpbiOutput
->
biWidth
;
This
->
sInfo
.
rcFrame
.
bottom
=
This
->
sInfo
.
rcFrame
.
top
+
This
->
lpbiOutput
->
biHeight
;
This
->
sInfo
.
dwSuggestedBufferSize
=
ICCompressGetSize
(
This
->
hic
,
lpbi
,
This
->
lpbiOutput
);
/* prepare codec for compression */
if
(
ICCompressBegin
(
This
->
hic
,
lpbi
,
This
->
lpbiOutput
)
!=
S_OK
)
return
AVIERR_COMPRESSOR
;
/* allocate memory for current frame */
size
+=
This
->
sInfo
.
dwSuggestedBufferSize
;
This
->
lpbiCur
=
(
LPBITMAPINFOHEADER
)
GlobalAllocPtr
(
GMEM_MOVEABLE
,
size
);
if
(
This
->
lpbiCur
==
NULL
)
return
AVIERR_MEMORY
;
memcpy
(
This
->
lpbiCur
,
This
->
lpbiOutput
,
This
->
cbOutput
);
This
->
lpCur
=
DIBPTR
(
This
->
lpbiCur
);
/* allocate memory for last frame if needed */
if
(
This
->
lKeyFrameEvery
!=
1
&&
(
This
->
dwICMFlags
&
VIDCF_FASTTEMPORALC
)
==
0
)
{
size
=
ICDecompressGetFormatSize
(
This
->
hic
,
This
->
lpbiOutput
);
This
->
lpbiPrev
=
(
LPBITMAPINFOHEADER
)
GlobalAllocPtr
(
GHND
,
size
);
if
(
This
->
lpbiPrev
==
NULL
)
return
AVIERR_MEMORY
;
if
(
ICDecompressGetFormat
(
This
->
hic
,
This
->
lpbiOutput
,
This
->
lpbiPrev
)
<
S_OK
)
return
AVIERR_COMPRESSOR
;
if
(
This
->
lpbiPrev
->
biSizeImage
==
0
)
{
This
->
lpbiPrev
->
biSizeImage
=
DIBWIDTHBYTES
(
*
This
->
lpbiPrev
)
*
This
->
lpbiPrev
->
biHeight
;
}
/* get memory for format and picture */
size
+=
This
->
lpbiPrev
->
biSizeImage
;
This
->
lpbiPrev
=
(
LPBITMAPINFOHEADER
)
GlobalReAllocPtr
(
This
->
lpbiPrev
,
size
,
GMEM_MOVEABLE
);
if
(
This
->
lpbiPrev
==
NULL
)
return
AVIERR_MEMORY
;
This
->
lpPrev
=
DIBPTR
(
This
->
lpbiPrev
);
/* prepare codec also for decompression */
if
(
ICDecompressBegin
(
This
->
hic
,
This
->
lpbiOutput
,
This
->
lpbiPrev
)
!=
S_OK
)
return
AVIERR_COMPRESSOR
;
}
return
AVIERR_OK
;
}
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