here is a quick summary...
Kent
intern/bsp/intern/BSP_CSGMesh_CFIterator.h
removed tri_index (unused variable)
intern/bsp/intern/CSG_BooleanOps.cpp
removed extra ;
intern/string/intern/STR_String.cpp
added <ctype.h>
source/blender/blenkernel/BKE_writeavi.h
moved things around so not doing forward declarations
source/blender/renderconverter/intern/convertBlenderScene.c
changed render.h to render_types.h
source/blender/src/blenderbuttons.c
source/blender/src/editgroup.c
source/blender/src/meshtools.c
added newline
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
commented out include "PIL_time.h" code that requires it is commented out
reading blender/src/writeavicodec.c
(struct keyword to a couple of lines that needed it)
and added:
extern struct Render R;
blender/renderconverter/intern/convertBlenderScene.c
added extern Render R;
added #include "rendercore.h" to get rid of undeclared shade_material_loop
(Not sure if this is right but it fixes it.
Did not fix this problem, is it alright to just pass NULL here or should we chan
ge it to something else:
init_render_materials' : too few
gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
removed argument to dHashSpaceCreate
commented out dWorldQuickStep since it does not exist
832 lines
22 KiB
C
832 lines
22 KiB
C
/**
|
|
* Functions for writing windows avi-format files.
|
|
*
|
|
* $Id$
|
|
*
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version. The Blender
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
* about this.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
* All rights reserved.
|
|
*
|
|
* The Original Code is: all of this file.
|
|
*
|
|
* Contributor(s): none yet.
|
|
*
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
*
|
|
*/
|
|
|
|
#if defined(_WIN32) && !defined(FREE_WINDOWS)
|
|
|
|
#define INC_OLE2
|
|
#include <windows.h>
|
|
#undef rad1
|
|
#undef rad2
|
|
|
|
#include <windowsx.h>
|
|
#include <memory.h>
|
|
#include <mmsystem.h>
|
|
#include <vfw.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
#include "BLI_blenlib.h"
|
|
#include "DNA_userdef_types.h"
|
|
|
|
#include "BKE_global.h"
|
|
#include "BKE_scene.h"
|
|
#include "BKE_writeavi.h"
|
|
|
|
#include "BIF_toolbox.h"
|
|
|
|
// this defines the compression type for
|
|
// the output video stream
|
|
|
|
AVICOMPRESSOPTIONS opts;
|
|
|
|
static int sframe;
|
|
static PAVIFILE pfile = NULL;
|
|
static int avifileinitdone = 0;
|
|
static PAVISTREAM psUncompressed = NULL, psCompressed = NULL;
|
|
|
|
// function definitions
|
|
static void init_bmi(BITMAPINFOHEADER *bmi);
|
|
static void opts_to_acd(struct AviCodecData *acd);
|
|
static void acd_to_opts(struct AviCodecData *acd);
|
|
static void free_opts_data();
|
|
static int open_avi_codec_file(char * name);
|
|
extern struct Render R;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// silly default parameters
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
#define DEFAULT_WIDTH 240
|
|
#define DEFAULT_HEIGHT 120
|
|
#define DEFAULT_LENGTH 100
|
|
#define DEFAULT_SIZE 6
|
|
#define DEFAULT_COLOR RGB(255,0,0)
|
|
#define XSPEED 7
|
|
#define YSPEED 5
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// useful macros
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
#define ALIGNULONG(i) ((i+3)&(~3)) /* ULONG aligned ! */
|
|
#define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
|
|
#define DIBWIDTHBYTES(bi) (int)WIDTHBYTES((int)(bi).biWidth * (int)(bi).biBitCount)
|
|
#define DIBPTR(lpbi) ((LPBYTE)(lpbi) + \
|
|
(int)(lpbi)->biSize + \
|
|
(int)(lpbi)->biClrUsed * sizeof(RGBQUAD) )
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// custom video stream instance structure
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct {
|
|
|
|
//
|
|
// The Vtbl must come first
|
|
//
|
|
IAVIStreamVtbl * lpvtbl;
|
|
|
|
//
|
|
// private ball instance data
|
|
//
|
|
ULONG ulRefCount;
|
|
|
|
DWORD fccType; // is this audio/video
|
|
|
|
int width; // size in pixels of each frame
|
|
int height;
|
|
int length; // length in frames of the pretend AVI movie
|
|
int size;
|
|
COLORREF color; // ball color
|
|
|
|
} AVIBALL, * PAVIBALL;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// custom stream methods
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT STDMETHODCALLTYPE AVIBallQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID * ppvObj);
|
|
HRESULT STDMETHODCALLTYPE AVIBallCreate (PAVISTREAM ps, LONG lParam1, LONG lParam2);
|
|
ULONG STDMETHODCALLTYPE AVIBallAddRef (PAVISTREAM ps);
|
|
ULONG STDMETHODCALLTYPE AVIBallRelease (PAVISTREAM ps);
|
|
HRESULT STDMETHODCALLTYPE AVIBallInfo (PAVISTREAM ps, AVISTREAMINFOW * psi, LONG lSize);
|
|
LONG STDMETHODCALLTYPE AVIBallFindSample (PAVISTREAM ps, LONG lPos, LONG lFlags);
|
|
HRESULT STDMETHODCALLTYPE AVIBallReadFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG *lpcbFormat);
|
|
HRESULT STDMETHODCALLTYPE AVIBallSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat);
|
|
HRESULT STDMETHODCALLTYPE AVIBallRead (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, LONG * plBytes,LONG * plSamples);
|
|
HRESULT STDMETHODCALLTYPE AVIBallWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG *plSampWritten, LONG *plBytesWritten);
|
|
HRESULT STDMETHODCALLTYPE AVIBallDelete (PAVISTREAM ps, LONG lStart, LONG lSamples);
|
|
HRESULT STDMETHODCALLTYPE AVIBallReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG *lpcb);
|
|
HRESULT STDMETHODCALLTYPE AVIBallWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG cb);
|
|
|
|
IAVIStreamVtbl AVIBallHandler = {
|
|
AVIBallQueryInterface,
|
|
AVIBallAddRef,
|
|
AVIBallRelease,
|
|
AVIBallCreate,
|
|
AVIBallInfo,
|
|
AVIBallFindSample,
|
|
AVIBallReadFormat,
|
|
AVIBallSetFormat,
|
|
AVIBallRead,
|
|
AVIBallWrite,
|
|
AVIBallDelete,
|
|
AVIBallReadData,
|
|
AVIBallWriteData
|
|
};
|
|
|
|
|
|
//
|
|
// This is the function an application would call to create a PAVISTREAM to
|
|
// reference the ball. Then the standard AVIStream function calls can be
|
|
// used to work with this stream.
|
|
//
|
|
PAVISTREAM WINAPI NewBall(void)
|
|
{
|
|
static AVIBALL ball;
|
|
PAVIBALL pball = &ball;
|
|
|
|
//
|
|
// Fill the function table
|
|
//
|
|
pball->lpvtbl = &AVIBallHandler;
|
|
|
|
//
|
|
// Call our own create code to create a new instance (calls AVIBallCreate)
|
|
// For now, don't use any lParams.
|
|
//
|
|
pball->lpvtbl->Create((PAVISTREAM) pball, 0, 0);
|
|
|
|
return (PAVISTREAM) pball;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// This function is called to initialize an instance of the bouncing ball.
|
|
//
|
|
// When called, we look at the information possibly passed in <lParam1>,
|
|
// if any, and use it to determine the length of movie they want. (Not
|
|
// supported by NewBall right now, but it could be).
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
HRESULT STDMETHODCALLTYPE AVIBallCreate(PAVISTREAM ps, LONG lParam1, LONG lParam2)
|
|
{
|
|
PAVIBALL pball = (PAVIBALL) ps;
|
|
|
|
//
|
|
// what type of data are we? (audio/video/other stream)
|
|
//
|
|
pball->fccType = streamtypeVIDEO;
|
|
|
|
//
|
|
// We define lParam1 as being the length of movie they want us to pretend
|
|
// to be.
|
|
//
|
|
if (lParam1)
|
|
pball->length = (int) lParam1;
|
|
else
|
|
pball->length = DEFAULT_LENGTH;
|
|
|
|
switch (pball->fccType) {
|
|
|
|
case streamtypeVIDEO:
|
|
pball->color = DEFAULT_COLOR;
|
|
pball->width = DEFAULT_WIDTH;
|
|
pball->height = DEFAULT_HEIGHT;
|
|
pball->size = DEFAULT_SIZE;
|
|
pball->ulRefCount = 1; // note that we are opened once
|
|
return AVIERR_OK; // success
|
|
|
|
case streamtypeAUDIO:
|
|
return ResultFromScode(AVIERR_UNSUPPORTED); // we don't do audio
|
|
|
|
default:
|
|
return ResultFromScode(AVIERR_UNSUPPORTED); // or anything else
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Increment our reference count
|
|
//
|
|
ULONG STDMETHODCALLTYPE AVIBallAddRef(PAVISTREAM ps)
|
|
{
|
|
PAVIBALL pball = (PAVIBALL) ps;
|
|
return (++pball->ulRefCount);
|
|
}
|
|
|
|
|
|
//
|
|
// Decrement our reference count
|
|
//
|
|
ULONG STDMETHODCALLTYPE AVIBallRelease(PAVISTREAM ps)
|
|
{
|
|
PAVIBALL pball = (PAVIBALL) ps;
|
|
if (--pball->ulRefCount)
|
|
return pball->ulRefCount;
|
|
|
|
// Free any data we're keeping around - like our private structure
|
|
GlobalFreePtr(pball);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Fills an AVISTREAMINFO structure
|
|
//
|
|
HRESULT STDMETHODCALLTYPE AVIBallInfo(PAVISTREAM ps, AVISTREAMINFOW * psi, LONG lSize)
|
|
{
|
|
PAVIBALL pball = (PAVIBALL) ps;
|
|
|
|
if (lSize < sizeof(AVISTREAMINFO))
|
|
return ResultFromScode(AVIERR_BUFFERTOOSMALL);
|
|
|
|
_fmemset(psi, 0, (int)lSize);
|
|
|
|
// Fill out a stream header with information about us.
|
|
psi->fccType = pball->fccType;
|
|
psi->fccHandler = mmioFOURCC('B','a','l','l');
|
|
psi->dwScale = 1;
|
|
psi->dwRate = 15;
|
|
psi->dwLength = pball->length;
|
|
psi->dwSuggestedBufferSize = pball->height * ALIGNULONG(pball->width);
|
|
psi->rcFrame.right = pball->width;
|
|
psi->rcFrame.bottom = pball->height;
|
|
CopyMemory((PVOID)psi->szName,
|
|
(PVOID)L"Bouncing ball video",
|
|
sizeof(L"Bouncing ball video"));
|
|
|
|
return AVIERR_OK;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// AVIBallReadFormat: needs to return the format of our data.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
HRESULT STDMETHODCALLTYPE AVIBallReadFormat (PAVISTREAM ps, LONG lPos,LPVOID lpFormat,LONG *lpcbFormat)
|
|
{
|
|
PAVIBALL pball = (PAVIBALL) ps;
|
|
LPBITMAPINFO lpbi = (LPBITMAPINFO) lpFormat;
|
|
|
|
if (lpFormat == NULL || *lpcbFormat == 0) {
|
|
*lpcbFormat = sizeof(BITMAPINFOHEADER);
|
|
return AVIERR_OK;
|
|
}
|
|
|
|
if (*lpcbFormat < sizeof(BITMAPINFOHEADER))
|
|
return ResultFromScode(AVIERR_BUFFERTOOSMALL);
|
|
|
|
// This is a relatively silly example: we build up our
|
|
// format from scratch every time.
|
|
|
|
/*
|
|
lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
lpbi->bmiHeader.biCompression = BI_RGB;
|
|
lpbi->bmiHeader.biWidth = pball->width;
|
|
lpbi->bmiHeader.biHeight = pball->height;
|
|
lpbi->bmiHeader.biBitCount = 8;
|
|
lpbi->bmiHeader.biPlanes = 1;
|
|
lpbi->bmiHeader.biClrUsed = 2;
|
|
lpbi->bmiHeader.biSizeImage = pball->height * DIBWIDTHBYTES(lpbi->bmiHeader);
|
|
*/
|
|
|
|
//init_bmi(&lpbi->bmiHeader);
|
|
|
|
memset(&lpbi->bmiHeader, 0, sizeof(BITMAPINFOHEADER));
|
|
lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
lpbi->bmiHeader.biWidth = pball->width;
|
|
lpbi->bmiHeader.biHeight = pball->height;
|
|
lpbi->bmiHeader.biPlanes = 1;
|
|
lpbi->bmiHeader.biBitCount = 24;
|
|
lpbi->bmiHeader.biSizeImage = pball->width * pball->height * sizeof(RGBTRIPLE);
|
|
|
|
/*
|
|
lpbi->bmiColors[0].rgbRed = 0;
|
|
lpbi->bmiColors[0].rgbGreen = 0;
|
|
lpbi->bmiColors[0].rgbBlue = 0;
|
|
lpbi->bmiColors[1].rgbRed = GetRValue(pball->color);
|
|
lpbi->bmiColors[1].rgbGreen = GetGValue(pball->color);
|
|
lpbi->bmiColors[1].rgbBlue = GetBValue(pball->color);
|
|
*/
|
|
|
|
*lpcbFormat = sizeof(BITMAPINFOHEADER);
|
|
|
|
return AVIERR_OK;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// AVIBallRead: needs to return the data for a particular frame.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
HRESULT STDMETHODCALLTYPE AVIBallRead (PAVISTREAM ps, LONG lStart,LONG lSamples,LPVOID lpBuffer,LONG cbBuffer,LONG * plBytes,LONG * plSamples)
|
|
{
|
|
PAVIBALL pball = (PAVIBALL) ps;
|
|
LONG lSize = pball->height * ALIGNULONG(pball->width); // size of frame
|
|
// in bytes
|
|
int x, y;
|
|
HPSTR hp = lpBuffer;
|
|
int xPos, yPos;
|
|
|
|
// Reject out of range values
|
|
if (lStart < 0 || lStart >= pball->length)
|
|
return ResultFromScode(AVIERR_BADPARAM);
|
|
|
|
// Did they just want to know the size of our data?
|
|
if (lpBuffer == NULL || cbBuffer == 0)
|
|
goto exit;
|
|
|
|
// Will our frame fit in the buffer passed?
|
|
if (lSize > cbBuffer)
|
|
return ResultFromScode(AVIERR_BUFFERTOOSMALL);
|
|
|
|
// Figure out the position of the ball.
|
|
// It just bounces back and forth.
|
|
|
|
xPos = 5 + XSPEED * (int) lStart; // x = x0 + vt
|
|
xPos = xPos % ((pball->width - pball->size) * 2); // limit to 2xwidth
|
|
if (xPos > (pball->width - pball->size)) // reflect if
|
|
xPos = 2 * (pball->width - pball->size) - xPos; // needed
|
|
|
|
yPos = 5 + YSPEED * (int) lStart;
|
|
yPos = yPos % ((pball->height - pball->size) * 2);
|
|
if (yPos > (pball->height - pball->size))
|
|
yPos = 2 * (pball->height - pball->size) - yPos;
|
|
|
|
//
|
|
// Build a DIB from scratch by writing in 1's where the ball is, 0's
|
|
// where it isn't.
|
|
//
|
|
// Notice that we just build it in the buffer we've been passed.
|
|
//
|
|
// This is pretty ugly, I have to admit.
|
|
//
|
|
for (y = 0; y < pball->height; y++)
|
|
{
|
|
if (y >= yPos && y < yPos + pball->size)
|
|
{
|
|
for (x = 0; x < pball->width; x++)
|
|
{
|
|
*hp++ = (BYTE) ((x >= xPos && x < xPos + pball->size) ? 1 : 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (x = 0; x < pball->width; x++)
|
|
{
|
|
*hp++ = 0;
|
|
}
|
|
}
|
|
|
|
hp += pball->width - ALIGNULONG(pball->width);
|
|
}
|
|
|
|
exit:
|
|
// We always return exactly one frame
|
|
if (plSamples)
|
|
*plSamples = 1;
|
|
|
|
// Return the size of our frame
|
|
if (plBytes)
|
|
*plBytes = lSize;
|
|
|
|
return AVIERR_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE AVIBallQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
PAVIBALL pball = (PAVIBALL) ps;
|
|
|
|
// We support the Unknown interface (everybody does) and our Stream
|
|
// interface.
|
|
|
|
if (_fmemcmp(riid, &IID_IUnknown, sizeof(GUID)) == 0)
|
|
*ppvObj = (LPVOID)pball;
|
|
|
|
else if (_fmemcmp(riid, &IID_IAVIStream, sizeof(GUID)) == 0)
|
|
*ppvObj = (LPVOID)pball;
|
|
|
|
else {
|
|
*ppvObj = NULL;
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
AVIBallAddRef(ps);
|
|
|
|
return AVIERR_OK;
|
|
}
|
|
|
|
LONG STDMETHODCALLTYPE AVIBallFindSample (PAVISTREAM ps, LONG lPos, LONG lFlags)
|
|
{
|
|
// The only format change is frame 0
|
|
if ((lFlags & FIND_TYPE) == FIND_FORMAT) {
|
|
if ((lFlags & FIND_DIR) == FIND_NEXT && lPos > 0)
|
|
return -1; // no more format changes
|
|
else
|
|
return 0;
|
|
|
|
// FIND_KEY and FIND_ANY always return the same position because
|
|
// every frame is non-empty and a key frame
|
|
} else
|
|
return lPos;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE AVIBallReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG *lpcb)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE AVIBallSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE AVIBallWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG cb)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE AVIBallWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG *plSampWritten, LONG *plBytesWritten)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE AVIBallDelete (PAVISTREAM ps, LONG lStart, LONG lSamples)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////
|
|
static void init_bmi(BITMAPINFOHEADER *bmi)
|
|
{
|
|
memset(bmi, 0, sizeof(BITMAPINFOHEADER));
|
|
bmi->biSize = sizeof(BITMAPINFOHEADER);
|
|
bmi->biWidth = R.rectx;
|
|
bmi->biHeight = R.recty;
|
|
bmi->biPlanes = 1;
|
|
bmi->biBitCount = 24;
|
|
bmi->biSizeImage = bmi->biWidth * bmi->biHeight * sizeof(RGBTRIPLE);
|
|
}
|
|
|
|
|
|
static void opts_to_acd(struct AviCodecData *acd)
|
|
{
|
|
HIC hic;
|
|
ICINFO icinfo;
|
|
|
|
acd->fccType = opts.fccType;
|
|
acd->fccHandler = opts.fccHandler;
|
|
acd->dwKeyFrameEvery = opts.dwKeyFrameEvery;
|
|
acd->dwQuality = opts.dwQuality;
|
|
acd->dwBytesPerSecond = opts.dwBytesPerSecond;
|
|
acd->dwFlags = opts.dwFlags;
|
|
acd->dwInterleaveEvery = opts.dwInterleaveEvery;
|
|
acd->cbFormat = opts.cbFormat;
|
|
acd->cbParms = opts.cbParms;
|
|
|
|
if (opts.lpFormat && opts.cbFormat) {
|
|
acd->lpFormat = MEM_mallocN(opts.cbFormat, "avi.lpFormat");
|
|
memcpy(acd->lpFormat, opts.lpFormat, opts.cbFormat);
|
|
}
|
|
|
|
if (opts.lpParms && opts.cbParms) {
|
|
acd->lpParms = MEM_mallocN(opts.cbParms, "avi.lpParms");
|
|
memcpy(acd->lpParms, opts.lpParms, opts.cbParms);
|
|
}
|
|
|
|
if ((hic=ICOpen(ICTYPE_VIDEO,acd->fccHandler,ICMODE_QUERY))!=NULL) {
|
|
icinfo.dwSize=sizeof(ICINFO);
|
|
if (ICGetInfo(hic,&icinfo,sizeof(ICINFO))) {
|
|
WideCharToMultiByte(CP_ACP,0,icinfo.szDescription,-1,acd->avicodecname,128,NULL,NULL);
|
|
} else
|
|
sprintf(acd->avicodecname, "undefined");
|
|
if (ICClose(hic)!=ICERR_OK)
|
|
;// return 0;
|
|
} else {
|
|
sprintf(acd->avicodecname, "Full Frames (Uncompressed)"); //heh, nasty
|
|
}
|
|
}
|
|
|
|
|
|
static void acd_to_opts(struct AviCodecData *acd)
|
|
{
|
|
memset(&opts, 0, sizeof(opts));
|
|
if (acd) {
|
|
opts.fccType = acd->fccType;
|
|
opts.fccHandler = acd->fccHandler;
|
|
opts.dwKeyFrameEvery = acd->dwKeyFrameEvery;
|
|
opts.dwQuality = acd->dwQuality;
|
|
opts.dwBytesPerSecond = acd->dwBytesPerSecond;
|
|
opts.dwFlags = acd->dwFlags;
|
|
opts.dwInterleaveEvery = acd->dwInterleaveEvery;
|
|
opts.cbFormat = acd->cbFormat;
|
|
opts.cbParms = acd->cbParms;
|
|
|
|
if (acd->lpFormat && acd->cbFormat) {
|
|
opts.lpFormat = MEM_mallocN(opts.cbFormat, "opts lpFormat");
|
|
memcpy(opts.lpFormat, acd->lpFormat, opts.cbFormat);
|
|
}
|
|
|
|
if (acd->lpParms && acd->cbParms) {
|
|
opts.lpParms = MEM_mallocN(opts.cbParms, "opts.cbParms");
|
|
memcpy(opts.lpParms, acd->lpParms, opts.cbParms);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void free_opts_data()
|
|
{
|
|
if (opts.lpFormat) {
|
|
MEM_freeN(opts.lpFormat);
|
|
opts.lpFormat = NULL;
|
|
}
|
|
if (opts.lpParms) {
|
|
MEM_freeN(opts.lpParms);
|
|
opts.lpParms = NULL;
|
|
}
|
|
}
|
|
|
|
static int open_avi_codec_file(char * name)
|
|
{
|
|
HRESULT hr;
|
|
WORD wVer;
|
|
BITMAPINFOHEADER bmi;
|
|
AVISTREAMINFO strhdr;
|
|
int ret_val = 0;
|
|
|
|
wVer = HIWORD(VideoForWindowsVersion());
|
|
if (wVer < 0x010a){
|
|
// this is probably an obsolete check...
|
|
ret_val = 1;
|
|
} else {
|
|
AVIFileInit();
|
|
avifileinitdone++;
|
|
|
|
hr = AVIFileOpen(&pfile, // returned file pointer
|
|
name, // file name
|
|
OF_WRITE | OF_CREATE, // mode to open file with
|
|
NULL); // use handler determined
|
|
|
|
if (hr != AVIERR_OK) {
|
|
ret_val = 1;
|
|
} else {
|
|
// initialize the BITMAPINFOHEADER
|
|
init_bmi(&bmi);
|
|
// and associate a stream with the input images
|
|
memset(&strhdr, 0, sizeof(strhdr));
|
|
strhdr.fccType = streamtypeVIDEO; // stream type
|
|
if (G.scene->r.avicodecdata) {
|
|
strhdr.fccHandler = G.scene->r.avicodecdata->fccHandler;
|
|
}
|
|
strhdr.dwScale = 1;
|
|
strhdr.dwRate = R.r.frs_sec;
|
|
strhdr.dwSuggestedBufferSize = bmi.biSizeImage;
|
|
SetRect(&strhdr.rcFrame, 0, 0, // rectangle for stream
|
|
(int) bmi.biWidth,
|
|
(int) bmi.biHeight);
|
|
|
|
// And create the stream
|
|
hr = AVIFileCreateStream(
|
|
pfile, // file pointer
|
|
&psUncompressed,// returned stream pointer
|
|
&strhdr); // stream header
|
|
|
|
if (hr != AVIERR_OK) {
|
|
ret_val = 1;
|
|
} else {
|
|
acd_to_opts(G.scene->r.avicodecdata);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(ret_val);
|
|
}
|
|
|
|
|
|
void end_avi_codec(void)
|
|
{
|
|
#if 0
|
|
free_opts_data();
|
|
|
|
if (psUncompressed) {
|
|
AVIStreamClose(psUncompressed);
|
|
psUncompressed = NULL;
|
|
}
|
|
|
|
if (psCompressed) {
|
|
AVIStreamClose(psCompressed);
|
|
psCompressed = NULL;
|
|
}
|
|
|
|
if (pfile) {
|
|
AVIFileClose(pfile);
|
|
pfile = NULL;
|
|
}
|
|
|
|
if (avifileinitdone > 0) {
|
|
AVIFileExit();
|
|
avifileinitdone--;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void start_avi_codec(void)
|
|
{
|
|
#if 0
|
|
HRESULT hr;
|
|
BITMAPINFOHEADER bmi;
|
|
char name[2048];
|
|
char bakname[2048];
|
|
|
|
makeavistring(name);
|
|
sframe = (G.scene->r.sfra);
|
|
|
|
strcpy(bakname, name);
|
|
strcat(bakname, ".bak");
|
|
|
|
if (BLI_exists(name)) {
|
|
BLI_move(name, bakname);
|
|
}
|
|
|
|
// initialize the BITMAPINFOHEADER
|
|
init_bmi(&bmi);
|
|
|
|
if (open_avi_codec_file(name)) {
|
|
error("Can not open file %s", name);
|
|
G.afbreek = 1;
|
|
} else {
|
|
// now create a compressed stream from the uncompressed
|
|
// stream and the compression options
|
|
hr = AVIMakeCompressedStream(
|
|
&psCompressed, // returned stream pointer
|
|
psUncompressed, // uncompressed stream
|
|
&opts, // compression options
|
|
NULL); // Unknown...
|
|
if (hr != AVIERR_OK) {
|
|
error("Codec is locked or not supported.");
|
|
G.afbreek = 1;
|
|
} else {
|
|
hr = AVIStreamSetFormat(psCompressed, 0,
|
|
&bmi, // stream format
|
|
bmi.biSize + // format size
|
|
bmi.biClrUsed * sizeof(RGBQUAD)); // plus size of colormap
|
|
if (hr != AVIERR_OK) {
|
|
error("Codec is locked or not supported.");
|
|
G.afbreek = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (G.afbreek != 1) {
|
|
printf("Created win avi: %s\n", name);
|
|
if (BLI_exists(bakname)) {
|
|
BLI_delete(bakname, 0, 0);
|
|
}
|
|
} else {
|
|
// close the darn thing and remove it.
|
|
end_avi_codec();
|
|
if (BLI_exists(name)) {
|
|
BLI_delete(name, 0, 0);
|
|
}
|
|
if (BLI_exists(bakname)) {
|
|
BLI_move(bakname, name);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void append_avi_codec(int frame)
|
|
{
|
|
#if 0
|
|
HRESULT hr;
|
|
BITMAPINFOHEADER bmi;
|
|
RGBTRIPLE *buffer, *to;
|
|
int x, y;
|
|
unsigned char *from;
|
|
|
|
if (psCompressed) {
|
|
// initialize the BITMAPINFOHEADER
|
|
init_bmi(&bmi);
|
|
|
|
// copy pixels
|
|
buffer = MEM_mallocN(bmi.biSizeImage, "append_win_avi");
|
|
to = buffer;
|
|
from = (unsigned char *) R.rectot;
|
|
for (y = R.recty; y > 0 ; y--) {
|
|
for (x = R.rectx; x > 0 ; x--) {
|
|
to->rgbtRed = from[0];
|
|
to->rgbtGreen = from[1];
|
|
to->rgbtBlue = from[2];
|
|
to++; from += 4;
|
|
}
|
|
}
|
|
|
|
hr = AVIStreamWrite(
|
|
psCompressed, // stream pointer
|
|
frame - sframe, // frame number
|
|
1, // number to write
|
|
(LPBYTE) buffer,// pointer to data
|
|
bmi.biSizeImage,// size of this frame
|
|
AVIIF_KEYFRAME, // flags....
|
|
NULL,
|
|
NULL);
|
|
|
|
MEM_freeN(buffer);
|
|
|
|
if (hr != AVIERR_OK) {
|
|
G.afbreek = 1;
|
|
} else {
|
|
printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
int get_avicodec_settings(void)
|
|
{
|
|
#if 0
|
|
int ret_val = 0;
|
|
AVICOMPRESSOPTIONS *aopts[1] = {&opts};
|
|
AviCodecData *acd = G.scene->r.avicodecdata;
|
|
static PAVISTREAM psdummy;
|
|
UINT uiFlags;
|
|
|
|
acd_to_opts(G.scene->r.avicodecdata);
|
|
|
|
psdummy = NewBall();
|
|
|
|
if(U.uiflag & USER_ALLWINCODECS)
|
|
uiFlags = ICMF_CHOOSE_ALLCOMPRESSORS;
|
|
else
|
|
uiFlags = ICMF_CHOOSE_KEYFRAME | ICMF_CHOOSE_DATARATE;
|
|
|
|
if (psdummy == NULL) {
|
|
ret_val = 1;
|
|
} else {
|
|
if (!AVISaveOptions(NULL,
|
|
uiFlags,
|
|
// ICMF_CHOOSE_KEYFRAME | ICMF_CHOOSE_DATARATE,
|
|
// ICMF_CHOOSE_ALLCOMPRESSORS,
|
|
1,
|
|
&psdummy,
|
|
(LPAVICOMPRESSOPTIONS *) &aopts))
|
|
{
|
|
ret_val = 1;
|
|
} else {
|
|
if (acd) {
|
|
free_avicodecdata(acd);
|
|
} else {
|
|
acd = G.scene->r.avicodecdata = MEM_callocN(sizeof(AviCodecData), "AviCodecData");
|
|
}
|
|
|
|
opts_to_acd(acd);
|
|
|
|
AVISaveOptionsFree(1, aopts);
|
|
memset(&opts, 0, sizeof(opts));
|
|
}
|
|
}
|
|
|
|
return(ret_val);
|
|
#endif
|
|
}
|
|
|
|
#endif // _WIN32
|