1619 lines
No EOL
38 KiB
C++
1619 lines
No EOL
38 KiB
C++
#include "TRACK.h"
|
||
#include "MEDIA.h"
|
||
#include "SCENE.h"
|
||
|
||
//#define FRAME_BY_FRAME
|
||
//#define SHOWFRAMENUM
|
||
|
||
char EncoderBuffer[512*512*4];
|
||
char EncoderBufferRes[512*512*4];
|
||
|
||
extern "C" {
|
||
#include "JPEG\INTERFCE.H"
|
||
};
|
||
|
||
BOOL SaveJPEG(MAP *src, char *filename)
|
||
{
|
||
JPEGDATA jData;
|
||
char Filenamecorrected[2048];
|
||
unsigned char *ptr;
|
||
unsigned char *basePtr = (unsigned char *)src->GetBase();
|
||
|
||
memset(&jData, 0, sizeof(jData));
|
||
if (GetFileNameExtend(filename) != '.JPG')
|
||
{
|
||
sprintf(Filenamecorrected,"%s.JPG",filename);
|
||
filename = Filenamecorrected;
|
||
}
|
||
|
||
|
||
ptr = jData.ptr = (unsigned char *)EncoderBuffer;
|
||
for (int counter=0; counter < src->PITCH*src->SY; counter++)
|
||
{
|
||
*(ptr + 0) = *(basePtr + 2);
|
||
*(ptr + 1) = *(basePtr + 1);
|
||
*(ptr + 2) = *(basePtr + 0);
|
||
basePtr +=4;
|
||
ptr +=3;
|
||
}
|
||
|
||
// Invert Image
|
||
for (u32 Y = 0 ; Y < src->SY >> 1 ; Y++ )
|
||
{
|
||
char Swap[8192*4];
|
||
memcpy(Swap, jData.ptr + Y*src->SX*3, src->SX*3);
|
||
memcpy(jData.ptr + Y*src->SX*3, jData.ptr + (src->SY-Y-1)*src->SX*3, src->SX*3);
|
||
memcpy(jData.ptr + (src->SY-Y-1)*src->SX*3, Swap, src->SX*3);
|
||
}
|
||
|
||
jData.width = src->SX;
|
||
jData.height = src->SY;
|
||
jData.quality = 200;
|
||
jData.components = 3;
|
||
|
||
lJADE_JPEG_INPOUT_FILE_LENGHT = 0;
|
||
ucJADE_JPEG_INPOUT_FILE = (unsigned char *)EncoderBufferRes;
|
||
|
||
jData.output_file = ucJADE_JPEG_INPOUT_FILE;
|
||
JpegWrite(&jData);
|
||
|
||
FILE *jpgFile;
|
||
jpgFile = CC_fopen(filename, "wb");
|
||
|
||
if (jpgFile)
|
||
{
|
||
if (fwrite(ucJADE_JPEG_INPOUT_FILE, 1, lJADE_JPEG_INPOUT_FILE_LENGHT, jpgFile) == lJADE_JPEG_INPOUT_FILE_LENGHT)
|
||
{
|
||
CC_fclose(jpgFile);
|
||
return true;
|
||
}
|
||
CC_fclose(jpgFile);
|
||
DeleteFile(filename);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
int LoadJPEG(MAP *dst, char *filename)
|
||
{
|
||
u32 Fl;
|
||
u8 *Fi;
|
||
Fl = GetFileLenght(filename);
|
||
if (Fl)
|
||
{
|
||
FILE *F;
|
||
JPEGDATA stJPD;
|
||
Fi = (u8*)CC_malloc(Fl);
|
||
F = GetSceneFileHanler(filename);
|
||
if (F)
|
||
{
|
||
fread( Fi, sizeof( char ), Fl, F );
|
||
CC_fclose(F);
|
||
}
|
||
lJADE_JPEG_INPOUT_FILE_LENGHT = Fl;
|
||
ucJADE_JPEG_INPOUT_FILE = Fi;
|
||
JpegInfo(&stJPD);
|
||
dst->SetSize(stJPD.width, stJPD.height);
|
||
stJPD.ptr = (u8*)dst->GetBase();
|
||
lJADE_JPEG_INPOUT_FILE_LENGHT = Fl;
|
||
ucJADE_JPEG_INPOUT_FILE = Fi;
|
||
JpegRead(&stJPD);
|
||
|
||
CC_free(Fi);
|
||
|
||
/* 24 -> 32 */
|
||
u8 *SRC,*DST;
|
||
u32 Counter;
|
||
Counter = dst->SX * dst->SY;
|
||
SRC = ((u8*)dst->GetBase()) + dst->SX * dst->SY * 3 - 3;
|
||
DST = ((u8*)dst->GetBase()) + dst->SX * dst->SY * 4 - 4;
|
||
while (Counter--)
|
||
{
|
||
*(DST + 3) = 0xff000000;
|
||
*(DST + 2) = *(SRC + 0);
|
||
*(DST + 1) = *(SRC + 1);
|
||
*(DST + 0) = *(SRC + 2);
|
||
SRC-=3;
|
||
DST-=4;
|
||
}
|
||
|
||
/***** Flip V *****/
|
||
s32 *pBASE = dst->GetBase();
|
||
for (u32 X = 0 ; X < dst->SX ; X++ )
|
||
for (u32 Y = 0 ; Y < dst->SY >> 1 ; Y++ )
|
||
{
|
||
u32 Swap;
|
||
Swap = *(pBASE + X + Y * dst->SX);
|
||
*(pBASE + X + Y * dst->SX) = *(pBASE + X + (dst->SY - Y - 1) * dst->SX);
|
||
*(pBASE + X + (dst->SY - Y - 1) * dst->SX) = Swap;
|
||
}
|
||
/***** Flip V *****/
|
||
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
#include <windows.h>
|
||
#include <atlcomcli.h>
|
||
#include <dshow.h>
|
||
#include <qedit.h>
|
||
|
||
#include "CODEC.h"
|
||
#include "process.h"
|
||
|
||
HRESULT AddToGraphEdit(IUnknown *pUnkGraph, DWORD *pdwRegister)
|
||
{
|
||
IMoniker *pMoniker;
|
||
IRunningObjectTable *pROT;
|
||
if (FAILED(GetRunningObjectTable(0, &pROT))) {
|
||
return E_FAIL;
|
||
}
|
||
WCHAR wsz[256];
|
||
wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
|
||
HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
|
||
if (SUCCEEDED(hr)) {
|
||
hr = pROT->Register(0, pUnkGraph, pMoniker, pdwRegister);
|
||
pMoniker->Release();
|
||
}
|
||
pROT->Release();
|
||
return hr;
|
||
}
|
||
|
||
void RemoveFromGraphEdit(DWORD pdwRegister)
|
||
{
|
||
IRunningObjectTable *pROT;
|
||
if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
|
||
pROT->Revoke(pdwRegister);
|
||
pROT->Release();
|
||
}
|
||
}
|
||
|
||
#if 1
|
||
|
||
class CSampleGrabberCB : public ISampleGrabberCB
|
||
{
|
||
public:
|
||
IMediaControl *mediaControl;
|
||
u32 NewFrame;
|
||
volatile u32 copying;
|
||
BYTE *imgBuffer;
|
||
|
||
STDMETHODIMP_(ULONG) AddRef() { return 2; }
|
||
STDMETHODIMP_(ULONG) Release() { return 1; }
|
||
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv)
|
||
{
|
||
if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown )
|
||
{
|
||
*ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
|
||
return NOERROR;
|
||
}
|
||
|
||
return E_NOINTERFACE;
|
||
}
|
||
STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample )
|
||
{
|
||
return 0;
|
||
}
|
||
STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize )
|
||
{
|
||
NewFrame = 1;
|
||
if (!imgBuffer)
|
||
imgBuffer = (BYTE *)CC_malloc(lBufferSize);
|
||
while (copying)
|
||
Sleep(2);
|
||
copying = 1;
|
||
memcpy(imgBuffer, pBuffer, lBufferSize);
|
||
copying = 0;
|
||
/*
|
||
if (FrameByFrame && !Locked)
|
||
{
|
||
if (mediaControl)
|
||
{
|
||
mediaControl->Pause();
|
||
}
|
||
}//*/
|
||
return 0;
|
||
}
|
||
|
||
};
|
||
|
||
|
||
class VideoWrapper {
|
||
|
||
public :
|
||
CComPtr<ICaptureGraphBuilder2> graphBuilder;
|
||
|
||
CComPtr<IFilterGraph2> filterGraph;
|
||
CComPtr<ISampleGrabber> sampleGrabber;
|
||
CComPtr<IBaseFilter> sourceFilter;
|
||
CComPtr<IBaseFilter> grabberFilter;
|
||
CComPtr<IBaseFilter> nullRenderer;
|
||
|
||
CComPtr<IBasicAudio> audioConfig;
|
||
CComPtr<IMediaSeeking> mediaSeeking;
|
||
CComPtr<IMediaPosition> mediaPosition;
|
||
CComPtr<IMediaControl> mediaControl;
|
||
CComPtr<IMediaEvent> mediaEvent;
|
||
|
||
CSampleGrabberCB CB;
|
||
|
||
bool videoInitialized;
|
||
double dAvgFramePerSecond;
|
||
int videoWidth;
|
||
int videoHeight;
|
||
|
||
long *frameBuffer;
|
||
long bufferSize;
|
||
int StatePausedLocker;
|
||
|
||
DWORD grabberNum;
|
||
INPUT_IO *pDad;
|
||
|
||
/** G3D Texture object */
|
||
|
||
VideoWrapper() {
|
||
// This must be callled before
|
||
// interfaces can be accessed
|
||
CoInitialize(NULL);
|
||
videoInitialized = false;
|
||
frameBuffer = NULL;
|
||
grabberNum = 0;
|
||
}
|
||
|
||
~VideoWrapper() {
|
||
// Technically, uninit ever init
|
||
CoUninitialize();
|
||
}
|
||
|
||
bool loadVideoFile(char *TheFile, bool loadWithSound);
|
||
|
||
int grabFrameTexture();
|
||
|
||
void uninitVideo();
|
||
|
||
int ConnectPins(IBaseFilter* outputFilter,
|
||
unsigned int outputNum,
|
||
IBaseFilter* inputFilter,
|
||
unsigned int inputNum);
|
||
bool ConnectToFreePin(IBaseFilter* inputFilter,
|
||
unsigned int inputNum);
|
||
|
||
|
||
void FindPin(IBaseFilter* baseFilter,
|
||
PIN_DIRECTION direction,
|
||
int pinNumber,
|
||
IPin** destPin);
|
||
|
||
int FindFreePin(PIN_DIRECTION direction, int number,
|
||
IPin** destPin);
|
||
};
|
||
|
||
|
||
class AVI_Redirect
|
||
{
|
||
char redirPath[1024];
|
||
char redirBase[1024];
|
||
|
||
public:
|
||
BOOL isRedirect;
|
||
int curFrame;
|
||
int nbFrames;
|
||
|
||
public:
|
||
AVI_Redirect() {memset(this, 0, sizeof(AVI_Redirect));};
|
||
int GenRedirFiles(char *theFile, VideoWrapper *vw, MAP *dstImg, TrackPlayer* tracks);
|
||
BOOL GetImage(int frame, MAP *dstImg);
|
||
};
|
||
|
||
|
||
class AVI_Grabber:public INPUT_IO
|
||
{
|
||
VideoWrapper *vw;
|
||
WORLD * pScn;
|
||
HRESULT hrinit;
|
||
|
||
DWORD sTimer;
|
||
double lastTime;
|
||
float volume;
|
||
float rate;
|
||
|
||
AVI_Redirect aviRedirect;
|
||
|
||
public:
|
||
u32 UseAlphaMode;
|
||
int INIT (WORLD *pScene);
|
||
int FRAME ();
|
||
int END ();
|
||
IOTYPE GetType() {return IOtype_AVI;};
|
||
void SetData(int dataIdx, void *data);
|
||
void * GetData(int dataIdx);
|
||
};
|
||
|
||
|
||
bool VideoWrapper::loadVideoFile(char *TheFile, bool loadWithSound) {
|
||
if (videoInitialized) {
|
||
uninitVideo();
|
||
}
|
||
StatePausedLocker = 0;
|
||
|
||
// Create the main object that runs the graph
|
||
graphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder2);
|
||
|
||
filterGraph.CoCreateInstance(CLSID_FilterGraph);
|
||
|
||
CB.NewFrame = 0;
|
||
CB.imgBuffer = NULL;
|
||
CB.copying = 0;
|
||
|
||
graphBuilder->SetFiltergraph(filterGraph);
|
||
|
||
// This takes the absolute filename path and
|
||
// Loads the appropriate file reader and splitter
|
||
// Depending in the file type.
|
||
WCHAR filename[ 1024 ];
|
||
MultiByteToWideChar(CP_ACP,0,TheFile,-1,filename,1024);
|
||
filterGraph->AddSourceFilter(filename,//(LPCWSTR )filename,
|
||
L"Video Source",
|
||
&sourceFilter);
|
||
|
||
// Create the Sample Grabber which we will use
|
||
// To take each frame for texture generation
|
||
grabberFilter.CoCreateInstance(CLSID_SampleGrabber);
|
||
grabberFilter->QueryInterface(IID_ISampleGrabber, reinterpret_cast<void**>(&sampleGrabber));
|
||
|
||
// We have to set the 24-bit RGB desire here
|
||
// So that the proper conversion filters
|
||
// Are added automatically.
|
||
AM_MEDIA_TYPE desiredType;
|
||
memset(&desiredType, 0, sizeof(desiredType));
|
||
desiredType.majortype = MEDIATYPE_Video;
|
||
desiredType.subtype = MEDIASUBTYPE_RGB32;
|
||
desiredType.formattype = FORMAT_VideoInfo;
|
||
sampleGrabber->SetMediaType(&desiredType);
|
||
sampleGrabber->SetBufferSamples(TRUE);
|
||
|
||
|
||
filterGraph->AddFilter(grabberFilter, L"Sample Grabber");
|
||
//sampleGrabber->SetOneShot(TRUE);
|
||
// Use pin connection methods instead of
|
||
// ICaptureGraphBuilder::RenderStream because of
|
||
// the SampleGrabber setting we're using.
|
||
int pinNum = 0;
|
||
while (true)
|
||
{
|
||
int res = ConnectPins(sourceFilter, pinNum++, grabberFilter, 0);
|
||
if (res > 0)
|
||
break;
|
||
if (res < 0)
|
||
{
|
||
uninitVideo();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// A Null Renderer does not display the video
|
||
// But it allows the Sample Grabber to run
|
||
// And it will keep proper playback timing
|
||
// Unless specified otherwise.
|
||
nullRenderer.CoCreateInstance(CLSID_NullRenderer);
|
||
filterGraph->AddFilter(nullRenderer, L"Null Renderer");
|
||
|
||
if (ConnectPins(grabberFilter, 0, nullRenderer, 0) <= 0) {
|
||
uninitVideo();
|
||
return false;
|
||
}//*/
|
||
|
||
|
||
if (loadWithSound)
|
||
{
|
||
CComPtr<IPin> outputPin;
|
||
if (FindFreePin(PINDIR_OUTPUT, 0, &outputPin))
|
||
{
|
||
filterGraph->Render(outputPin);
|
||
}
|
||
outputPin.Release();
|
||
}
|
||
// test function to get generated direct show graph
|
||
AddToGraphEdit(filterGraph, &grabberNum);
|
||
|
||
// Just a little trick so that we don't have to know
|
||
// The video resolution when calling this method.
|
||
bool mediaConnected = false;
|
||
AM_MEDIA_TYPE connectedType;
|
||
|
||
if (SUCCEEDED(sampleGrabber->GetConnectedMediaType(&connectedType))) {
|
||
if (connectedType.formattype == FORMAT_VideoInfo) {
|
||
VIDEOINFOHEADER* infoHeader = (VIDEOINFOHEADER*)connectedType.pbFormat;
|
||
videoWidth = infoHeader->bmiHeader.biWidth;
|
||
videoHeight = infoHeader->bmiHeader.biHeight;
|
||
//if (infoHeader->AvgTimePerFrame)
|
||
// dAvgFramePerSecond = (double) 10000000 / infoHeader->AvgTimePerFrame;
|
||
//else
|
||
dAvgFramePerSecond = 30.0;
|
||
mediaConnected = true;
|
||
}
|
||
CoTaskMemFree(connectedType.pbFormat);
|
||
}
|
||
|
||
|
||
if (!mediaConnected) {
|
||
uninitVideo();
|
||
return false;
|
||
}
|
||
|
||
sampleGrabber->SetCallback(&CB,1);
|
||
|
||
|
||
filterGraph->QueryInterface(IID_IBasicAudio, (void **)&audioConfig);
|
||
filterGraph->QueryInterface(IID_IMediaSeeking, (void **)&mediaSeeking);
|
||
filterGraph->QueryInterface(IID_IMediaPosition, (void **)&mediaPosition);
|
||
|
||
//if (CB.FrameByFrame)
|
||
//mediaSeeking->SetRate(5.0);
|
||
|
||
if (S_OK == mediaSeeking->IsFormatSupported(&TIME_FORMAT_MEDIA_TIME ))
|
||
mediaSeeking->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME );
|
||
|
||
filterGraph->QueryInterface(IID_IMediaControl, (void **)&mediaControl);
|
||
filterGraph->QueryInterface(IID_IMediaEvent, (void **)&mediaEvent);
|
||
|
||
CB.mediaControl = mediaControl;
|
||
|
||
if (SUCCEEDED(mediaControl->Run())) {
|
||
videoInitialized = true;
|
||
return true;
|
||
} else {
|
||
uninitVideo();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/** For a later time but probably faster displays. */
|
||
|
||
int VideoWrapper::grabFrameTexture() {
|
||
if (videoInitialized) {
|
||
// Only need to do this once
|
||
if (!frameBuffer) {
|
||
// The Sample Grabber requires an arbitrary buffer
|
||
// That we only know at runtime.
|
||
// (width * height * 3) bytes will not work.
|
||
bufferSize =4*videoWidth*videoHeight;
|
||
sampleGrabber->GetCurrentBuffer(&bufferSize, NULL);
|
||
frameBuffer = new long[bufferSize];
|
||
}
|
||
sampleGrabber->GetCurrentBuffer(&bufferSize, (long*)frameBuffer);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void VideoWrapper::uninitVideo() {
|
||
if (videoInitialized) {
|
||
if (mediaControl) mediaControl->Stop();
|
||
|
||
if (grabberNum)
|
||
RemoveFromGraphEdit(grabberNum);
|
||
grabberNum = 0;
|
||
|
||
mediaControl.Release();
|
||
mediaSeeking.Release();
|
||
mediaPosition.Release();
|
||
audioConfig.Release();
|
||
grabberFilter.Release();
|
||
sourceFilter.Release();
|
||
nullRenderer.Release();
|
||
sampleGrabber.Release();
|
||
filterGraph.Release();
|
||
graphBuilder.Release();
|
||
CB.mediaControl = NULL;
|
||
}
|
||
videoInitialized = false;
|
||
|
||
|
||
if (frameBuffer) delete[] frameBuffer;
|
||
frameBuffer = NULL;
|
||
}
|
||
|
||
int VideoWrapper::ConnectPins(IBaseFilter* outputFilter,
|
||
unsigned int outputNum,
|
||
IBaseFilter* inputFilter,
|
||
unsigned int inputNum) {
|
||
|
||
CComPtr<IPin> inputPin;
|
||
CComPtr<IPin> outputPin;
|
||
|
||
if (!outputFilter || !inputFilter) {
|
||
return -1;
|
||
}
|
||
|
||
FindPin(outputFilter, PINDIR_OUTPUT, outputNum, &outputPin);
|
||
FindPin(inputFilter, PINDIR_INPUT, inputNum, &inputPin);
|
||
|
||
if (inputPin && outputPin) {
|
||
return SUCCEEDED(filterGraph->Connect(outputPin, inputPin));
|
||
} else {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
bool VideoWrapper::ConnectToFreePin(IBaseFilter* inputFilter,
|
||
unsigned int inputNum) {
|
||
|
||
CComPtr<IPin> inputPin;
|
||
CComPtr<IPin> outputPin;
|
||
|
||
if (!inputFilter) {
|
||
return false;
|
||
}
|
||
|
||
int number = 0;
|
||
bool funcReturn = false;
|
||
|
||
FindPin(inputFilter, PINDIR_INPUT, inputNum, &inputPin);
|
||
while (true)
|
||
{
|
||
funcReturn = FindFreePin(PINDIR_OUTPUT, number++, &outputPin);
|
||
if (!funcReturn)
|
||
return false;
|
||
|
||
if (inputPin && outputPin) {
|
||
funcReturn = SUCCEEDED(filterGraph->Connect(outputPin, inputPin));
|
||
if (funcReturn)
|
||
return funcReturn;
|
||
} else {
|
||
return false;
|
||
}
|
||
outputPin.Release();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
void VideoWrapper::FindPin(IBaseFilter* baseFilter,
|
||
PIN_DIRECTION direction,
|
||
int pinNumber,
|
||
IPin** destPin) {
|
||
|
||
CComPtr<IEnumPins> enumPins;
|
||
|
||
*destPin = NULL;
|
||
|
||
if (SUCCEEDED(baseFilter->EnumPins(&enumPins))) {
|
||
ULONG numFound;
|
||
IPin* tmpPin;
|
||
|
||
while (SUCCEEDED(enumPins->Next(1, &tmpPin, &numFound)) && numFound > 0) {
|
||
PIN_DIRECTION pinDirection;
|
||
|
||
tmpPin->QueryDirection(&pinDirection);
|
||
if (pinDirection == direction) {
|
||
if (pinNumber == 0) {
|
||
// Return the pin's interface
|
||
*destPin = tmpPin;
|
||
break;
|
||
}
|
||
pinNumber--;
|
||
}
|
||
tmpPin->Release();
|
||
}
|
||
enumPins.Release();
|
||
}
|
||
}
|
||
|
||
int VideoWrapper::FindFreePin(PIN_DIRECTION direction, int number,
|
||
IPin** destPin)
|
||
{
|
||
CComPtr<IEnumFilters> enumFilters;
|
||
CComPtr<IEnumPins> enumPins;
|
||
CComPtr<IBaseFilter> currentFilter;
|
||
|
||
IPin *filterPin;
|
||
IPin *connectedPin;
|
||
|
||
ULONG numFilterFound;
|
||
ULONG numPinFound;
|
||
|
||
filterGraph->EnumFilters(&enumFilters);
|
||
while (SUCCEEDED(enumFilters->Next(1,¤tFilter,&numFilterFound)) && numFilterFound > 0)
|
||
{
|
||
//FILTER_INFO infoFilter;
|
||
//currentFilter->QueryFilterInfo(&infoFilter);
|
||
if (SUCCEEDED(currentFilter->EnumPins(&enumPins)))
|
||
{
|
||
ULONG numFound2;
|
||
while (SUCCEEDED(enumPins->Next(1, &filterPin, &numFound2)) && numFound2 > 0)
|
||
{
|
||
PIN_DIRECTION pinDirection;
|
||
filterPin->QueryDirection(&pinDirection);
|
||
if (pinDirection == direction)
|
||
{
|
||
if (S_OK != filterPin->ConnectedTo(&connectedPin))
|
||
{
|
||
if (number == 0)
|
||
{
|
||
// ajouter test du type
|
||
*destPin = filterPin;
|
||
return 1;
|
||
}
|
||
number--;
|
||
} else {
|
||
connectedPin->Release();
|
||
}
|
||
}
|
||
filterPin->Release();
|
||
}
|
||
enumPins.Release();
|
||
}
|
||
currentFilter.Release();
|
||
numFilterFound = numFilterFound;
|
||
}
|
||
enumFilters.Release();
|
||
return 0;
|
||
}
|
||
|
||
int AVI_Redirect::GenRedirFiles(char *theFile, VideoWrapper *vw, MAP *dstImg, TrackPlayer* tracks)
|
||
{
|
||
char * lastChar;
|
||
char spChar;
|
||
char pathFile[1024];
|
||
char pathFileDst[1024];
|
||
INPUT_IO *Ret;
|
||
FILE *fileBuffer;
|
||
|
||
if (isRedirect) return nbFrames;
|
||
|
||
for (lastChar=theFile; strchr(lastChar, '.') != NULL; lastChar=strchr(lastChar, '.')+1);
|
||
strncpy(redirPath, theFile, lastChar-theFile-1);
|
||
redirPath[lastChar-theFile] = 0;
|
||
|
||
if (strchr(redirPath, '/') != NULL)
|
||
spChar = '/';
|
||
else
|
||
spChar = '\\';
|
||
for (lastChar=redirPath; strchr(lastChar, spChar) != NULL; lastChar=strchr(lastChar, spChar)+1);
|
||
strcpy(redirBase, lastChar);
|
||
|
||
CreateDirectory(redirPath, 0);
|
||
|
||
sprintf(pathFile, "%s\\%s_%06i.jpg", redirPath, redirBase, 1);
|
||
if (IsExist(pathFile)) {
|
||
if (!vw)
|
||
{
|
||
u32 Fl;
|
||
u8 *Fi;
|
||
FILE *F;
|
||
JPEGDATA stJPD;
|
||
|
||
Fl = GetFileLenght((char*)pathFile);
|
||
Fi = (u8*)CC_malloc(Fl);
|
||
F = GetSceneFileHanler((char*)pathFile);
|
||
if (F)
|
||
{
|
||
fread( Fi, sizeof( char ), Fl, F );
|
||
CC_fclose(F);
|
||
}
|
||
lJADE_JPEG_INPOUT_FILE_LENGHT = Fl;
|
||
ucJADE_JPEG_INPOUT_FILE = Fi;
|
||
JpegInfo(&stJPD);
|
||
if (stJPD.status)
|
||
{
|
||
CC_free(Fi);
|
||
return 0;
|
||
}
|
||
dstImg->PITCH =
|
||
dstImg->SX = stJPD.width;
|
||
dstImg->SY = stJPD.height;
|
||
CC_free(Fi);
|
||
}
|
||
|
||
sprintf(pathFile,"%s\\%s_*.jpg", redirPath, redirBase);
|
||
|
||
WIN32_FIND_DATA FD;
|
||
HANDLE HHH = FindFirstFile(pathFile,&FD);
|
||
|
||
nbFrames = 1;
|
||
if (HHH != INVALID_HANDLE_VALUE)
|
||
{
|
||
do
|
||
{
|
||
strcpy(pathFile, FD.cFileName + (strlen(FD.cFileName) - 10));
|
||
pathFile[6] = 0;
|
||
|
||
int frm = atoi(pathFile);
|
||
if (nbFrames < frm)
|
||
nbFrames = frm;
|
||
} while (FindNextFile(HHH,&FD));
|
||
FindClose(HHH);
|
||
}
|
||
|
||
curFrame = -1;
|
||
isRedirect = true;
|
||
|
||
|
||
return nbFrames;
|
||
}
|
||
|
||
if (!vw)
|
||
return 0;
|
||
|
||
int lastTrkFrame = -1;
|
||
int currTrkFrame = -1;
|
||
double lastTrkTime = -1.0;
|
||
double currTrkTime;
|
||
|
||
vw->mediaSeeking->SetRate(0.5);
|
||
vw->mediaControl->Stop();
|
||
vw->mediaPosition->put_CurrentPosition(0);
|
||
vw->mediaControl->Run();
|
||
nbFrames = 1;
|
||
|
||
BOOL bEnd = false;
|
||
while (!bEnd)
|
||
{
|
||
long lEventCode, lParam1, lParam2;
|
||
while (E_ABORT != vw->mediaEvent->GetEvent(&lEventCode, &lParam1, &lParam2, 0))
|
||
{
|
||
if (lEventCode == EC_COMPLETE)
|
||
bEnd = true;
|
||
vw->mediaEvent->FreeEventParams(lEventCode, lParam1, lParam2);
|
||
}
|
||
|
||
vw->mediaPosition->get_CurrentPosition(&currTrkTime);
|
||
currTrkFrame = TIME_TO_FRAME(currTrkTime, vw->dAvgFramePerSecond);
|
||
|
||
if (lastTrkTime >= currTrkTime)
|
||
{
|
||
Sleep(3); continue;
|
||
}
|
||
lastTrkTime = currTrkTime;
|
||
if (currTrkFrame == lastTrkFrame)
|
||
{
|
||
Sleep(3); continue;
|
||
}
|
||
for (int currTrkIn = lastTrkFrame + 1; currTrkIn < currTrkFrame; currTrkIn++)
|
||
{
|
||
sprintf(pathFile, "%s\\%s_%06i.jpg", redirPath, redirBase, lastTrkFrame);
|
||
sprintf(pathFileDst,"%s\\%s_%06i.jpg", redirPath, redirBase, currTrkIn);
|
||
CopyFile(pathFile, pathFileDst, 0);
|
||
}
|
||
lastTrkFrame = currTrkFrame;
|
||
|
||
vw->grabFrameTexture();
|
||
memcpy(dstImg->GetBase() , (s32*)vw->frameBuffer , vw->videoWidth * vw->videoHeight * 4);
|
||
if (vw->videoWidth > dstImg->SX)
|
||
{
|
||
int i,j,IncX,AddX,IncY,AddY;
|
||
unsigned long *SRC_512,*SRC_640,*SRC_LAST;
|
||
SRC_512 = SRC_640 = (unsigned long*)dstImg->GetBase();
|
||
IncY = 0;
|
||
AddY = (dstImg->SY<<16) / vw->videoHeight;
|
||
AddX = (dstImg->SX<<16) / vw->videoWidth;
|
||
for (i = 0,j = 0 ; i < vw->videoHeight; i++)
|
||
{
|
||
SRC_LAST = SRC_640 + vw->videoWidth;
|
||
IncX = 0;
|
||
while (SRC_640 < SRC_LAST)
|
||
{
|
||
*(SRC_512+(IncX>>16)) = *(SRC_640++);
|
||
IncX += AddX;
|
||
}
|
||
IncY += AddY;
|
||
SRC_512 = (unsigned long*)dstImg->GetBase() + ((IncY>>16) * dstImg->SX);
|
||
j++;
|
||
}
|
||
}
|
||
|
||
sprintf(pathFile, "%s\\%s_%06i.jpg", redirPath, redirBase, currTrkFrame);
|
||
SaveJPEG(dstImg, pathFile);
|
||
tracks->GetDescriptor(currTrkFrame)->ImageMarker = GET_MARKER(dstImg);
|
||
nbFrames = currTrkFrame;
|
||
}
|
||
if (!nbFrames)
|
||
nbFrames = 1;
|
||
curFrame = 0;
|
||
isRedirect = true;
|
||
return nbFrames;
|
||
}
|
||
|
||
|
||
BOOL AVI_Redirect::GetImage(int frame, MAP *dstImg)
|
||
{
|
||
char pathFile[1024];
|
||
FILE *fileBuffer;
|
||
|
||
if (!isRedirect || redirPath[0] == 0) return false;
|
||
if (frame == curFrame) return true;
|
||
|
||
//frame = frame % nbFrames;
|
||
if (frame > nbFrames) frame = nbFrames;
|
||
if (frame < 0) frame = nbFrames - 1;
|
||
|
||
curFrame = frame;
|
||
|
||
sprintf(pathFile, "%s\\%s_%06i.jpg", redirPath, redirBase, curFrame);
|
||
if (!LoadJPEG(dstImg, pathFile)) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
int AVI_Grabber::INIT(WORLD *pScene)
|
||
{
|
||
dCurrentTime = 0.0f;
|
||
dTotalTime = 0.0f;
|
||
|
||
ulCurrentFrame = 0;
|
||
lTimeState = 0;
|
||
ulMediaParams = 0x1;
|
||
volume = 1.0f;
|
||
rate = 1.0f;
|
||
|
||
vw = new VideoWrapper();
|
||
vw->pDad = NULL;
|
||
|
||
if (!vw->loadVideoFile((char*)MediaName, !pScene->AVIMegaRedirect))
|
||
{
|
||
delete vw;
|
||
vw = NULL;
|
||
if (!pScene->AVIMegaRedirect)
|
||
return false;
|
||
int nbFrame = aviRedirect.GenRedirFiles((char *)MediaName, NULL, &Image, Tracks);
|
||
if (!nbFrame)
|
||
return false;
|
||
|
||
dTotalTime = (double)nbFrame / 30;
|
||
dAvgFramePerSecond = 30;
|
||
} else
|
||
{
|
||
LONGLONG time;
|
||
|
||
vw->mediaSeeking->GetDuration(&time);
|
||
dTotalTime = (double)time / 10000000;
|
||
dAvgFramePerSecond = vw->dAvgFramePerSecond;
|
||
|
||
Image.PITCH =
|
||
Image.SX = vw->videoWidth;
|
||
Image.SY = vw->videoHeight;
|
||
|
||
vw->pDad = this;
|
||
vw->grabFrameTexture();
|
||
vw->mediaControl->Pause();
|
||
|
||
if (pScene->AVIMegaRedirect)
|
||
aviRedirect.GenRedirFiles((char *)MediaName, vw, &Image, Tracks);
|
||
}
|
||
|
||
ulCurrentFrame = 0;
|
||
pScn = pScene;
|
||
Image.SetSize(Image.SX, Image.SY, 1);
|
||
|
||
if (Image.SX > 512)
|
||
{
|
||
Image.SX = 512;
|
||
Image.SY = ((Image.SX) * ((vw->videoHeight << 16) / vw->videoWidth)>>16);
|
||
}
|
||
if (!UseAlphaMode)
|
||
if (Image.SY > 512)
|
||
{
|
||
Image.SX = ((Image.SY) * ((vw->videoWidth << 16) / vw->videoHeight)>>16);
|
||
Image.SY = 512;
|
||
}
|
||
//CoUninitialize();
|
||
|
||
if (UseAlphaMode)
|
||
Image.SY >>= 1;
|
||
|
||
return 1;
|
||
}
|
||
int AVI_Grabber::FRAME()
|
||
{
|
||
double prevTime;
|
||
int imgChanged = 0;
|
||
|
||
if (pScn->bManualBoot & 2) return 0;
|
||
if (UseAlphaMode) Image.SY <<= 1;
|
||
|
||
if (vw || pScn->AVIMegaRedirect)
|
||
{
|
||
START_RASTER(Avi);
|
||
if (pScn->AVIMegaRedirect)
|
||
{
|
||
if (Tracks == NULL)
|
||
{
|
||
Tracks = (TrackPlayer*)CC_malloc(sizeof(TrackPlayer));
|
||
memset(Tracks,0,sizeof(TrackPlayer));
|
||
};
|
||
if (lTimeState < 0)
|
||
aviRedirect.GetImage(ulCurrentFrame-1, &Image);
|
||
else if (!lTimeState || lTimeState == 255)
|
||
aviRedirect.GetImage(ulCurrentFrame, &Image);
|
||
else
|
||
aviRedirect.GetImage(ulCurrentFrame+1, &Image);
|
||
ulCurrentFrame = aviRedirect.curFrame;
|
||
} else
|
||
{
|
||
BOOL needState = false;
|
||
if (abs((float)dCurrentTime - (float)lastTime) > 0.001f)
|
||
{
|
||
vw->mediaPosition->put_CurrentPosition(dCurrentTime);
|
||
needState = true;
|
||
}
|
||
|
||
switch (lTimeState)
|
||
{
|
||
case 0:
|
||
vw->mediaControl->Pause();
|
||
break;
|
||
case 255:
|
||
vw->mediaPosition->put_CurrentPosition(0);
|
||
vw->mediaControl->StopWhenReady();
|
||
needState = true;
|
||
break;
|
||
case 1:
|
||
vw->mediaControl->Run();
|
||
break;
|
||
}
|
||
|
||
if (needState)
|
||
{
|
||
OAFilterState state;
|
||
vw->mediaControl->GetState(500, &state);
|
||
}
|
||
|
||
// if (lTimeState || ulCurrentFrame != lastTime)
|
||
if (vw->CB.NewFrame)
|
||
{
|
||
vw->CB.NewFrame = 0;
|
||
imgChanged = 1;
|
||
}
|
||
if (lTimeState != 1)
|
||
lTimeState = 0;
|
||
|
||
prevTime = dCurrentTime;
|
||
vw->mediaPosition->get_CurrentPosition(&dCurrentTime);
|
||
|
||
BOOL bEnd = false;
|
||
long lEventCode, lParam1, lParam2;
|
||
while (E_ABORT != vw->mediaEvent->GetEvent(&lEventCode, &lParam1, &lParam2, 0))
|
||
{
|
||
if (lEventCode == EC_COMPLETE)
|
||
bEnd = true;
|
||
vw->mediaEvent->FreeEventParams(lEventCode, lParam1, lParam2);
|
||
}
|
||
|
||
if (bEnd)
|
||
{
|
||
if (ulMediaParams & 1)
|
||
{
|
||
dCurrentTime = 0.0f;
|
||
vw->mediaPosition->put_CurrentPosition(dCurrentTime);
|
||
vw->mediaControl->Stop();
|
||
if (lTimeState == 1)
|
||
vw->mediaControl->Run();
|
||
} else
|
||
{
|
||
lTimeState = 0;
|
||
}
|
||
}
|
||
ulCurrentFrame = TIME_TO_FRAME(dCurrentTime, dAvgFramePerSecond);
|
||
lastTime = dCurrentTime;
|
||
|
||
if (imgChanged)
|
||
{
|
||
while (vw->CB.copying)
|
||
Sleep(2);
|
||
vw->CB.copying = 1;
|
||
memcpy(Image.GetBase() , (s32*)vw->CB.imgBuffer, vw->videoWidth * vw->videoHeight * 4);
|
||
vw->CB.copying = 0;
|
||
if (vw->videoWidth > Image.SX)
|
||
{
|
||
int i,j,IncX,AddX,IncY,AddY;
|
||
unsigned long *SRC_512,*SRC_640,*SRC_LAST;
|
||
SRC_512 = SRC_640 = (unsigned long*)Image.GetBase();
|
||
IncY = 0;
|
||
AddY = (Image.SY<<16) / vw->videoHeight;
|
||
AddX = (Image.SX<<16) / vw->videoWidth;
|
||
for (i = 0,j = 0 ; i < vw->videoHeight; i++)
|
||
{
|
||
SRC_LAST = SRC_640 + vw->videoWidth;
|
||
IncX = 0;
|
||
while (SRC_640 < SRC_LAST)
|
||
{
|
||
*(SRC_512+(IncX>>16)) = *(SRC_640++);
|
||
IncX += AddX;
|
||
}
|
||
IncY += AddY;
|
||
SRC_512 = (unsigned long*)Image.GetBase() + ((IncY>>16) * Image.SX);
|
||
j++;
|
||
}
|
||
}
|
||
if (UseAlphaMode)
|
||
{
|
||
s32 *pAlpha,*pRGB,*pLast;
|
||
pAlpha = Image.GetBase();
|
||
pRGB = Image.GetBase() + (Image.SY>>1) * Image.PITCH;
|
||
pLast = Image.GetBase() + Image.SY * Image.PITCH;
|
||
while (pRGB < pLast)
|
||
{
|
||
*(u32*)pAlpha <<= 24;
|
||
*pAlpha |= *pRGB & 0xffffff;
|
||
pAlpha++;
|
||
pRGB++;
|
||
}//*/
|
||
}
|
||
}
|
||
}
|
||
|
||
if (vw && vw->audioConfig)
|
||
{
|
||
if (ulMediaParams & 2)
|
||
vw->audioConfig->put_Volume(-10000);
|
||
else
|
||
vw->audioConfig->put_Volume(-10000*(1-volume));
|
||
}
|
||
//if (pScn->WSPC->INTERP_MatchingPercent < 10.0f) I_Frame = 20;
|
||
#ifdef SHOWFRAMENUM
|
||
if (!lTimeState)
|
||
{
|
||
char TEXT[2048];
|
||
sprintf(TEXT,"%d TF:%d SPL:%d",vw->FrameNum,ulCurrentFrame,vw->StatePausedLocker);
|
||
DRawTEXT_Soft_B((u8*)TEXT,(u32*)Image.BASE,0, 0, Image.SX, Image.SY , 0xffff00);
|
||
}
|
||
#endif
|
||
STOP_RASTER(Avi);
|
||
|
||
|
||
}
|
||
|
||
if (UseAlphaMode) Image.SY >>= 1;
|
||
|
||
return imgChanged;
|
||
}
|
||
|
||
void AVI_Grabber::SetData(int dataIdx, void *data)
|
||
{
|
||
switch (dataIdx)
|
||
{
|
||
case 3:
|
||
volume = *(float *)data;
|
||
volume = log(volume+1.0f)/log(2.0f);
|
||
if (vw && vw->audioConfig)
|
||
vw->audioConfig->put_Volume(-10000*(1-volume));
|
||
break;
|
||
case 4:
|
||
rate = *(float *)data;
|
||
if (vw && vw->mediaSeeking)
|
||
vw->mediaSeeking->SetRate(rate);
|
||
break;
|
||
}
|
||
}
|
||
|
||
void *AVI_Grabber::GetData(int dataIdx)
|
||
{
|
||
switch (dataIdx)
|
||
{
|
||
case 3:
|
||
return &volume;
|
||
case 4:
|
||
return &rate;
|
||
case 5:
|
||
vw->mediaPosition->get_CurrentPosition(&dCurrentTime);
|
||
return &dCurrentTime;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
|
||
int AVI_Grabber::END()
|
||
{
|
||
if (vw)
|
||
{
|
||
vw->uninitVideo();
|
||
delete vw;
|
||
}
|
||
Image.Delete();
|
||
return 0;
|
||
}
|
||
|
||
|
||
#else
|
||
|
||
|
||
|
||
//**************************************************************
|
||
//**************************************************************
|
||
//**************************************************************
|
||
extern "C" {
|
||
#include "libavformat/avformat.h"
|
||
#include "libavutil/avutil.h"
|
||
#include "libavcodec/avcodec.h"
|
||
};
|
||
|
||
|
||
typedef struct AVI_Video_Data_
|
||
{
|
||
int streamIndex;
|
||
|
||
uint8_t *pFrameBuffer;
|
||
AVFrame *pFrame;
|
||
AVFrame *pFrameMAP;
|
||
|
||
AVCodecContext *pCodecCtx;
|
||
AVCodec *pCodec;
|
||
} AVI_Video_Data;
|
||
|
||
#define NB_WHDR 2
|
||
#define WAVE_BUFFER_SIZE 1024*16
|
||
#define WAVE_AVI_BUFFER_SIZE 16*AVCODEC_MAX_AUDIO_FRAME_SIZE
|
||
|
||
typedef struct AVI_Audio_Data_
|
||
{
|
||
int streamIndex;
|
||
HWAVEOUT waveOut;
|
||
WAVEHDR waveHDR[NB_WHDR];
|
||
uint8_t *pAVBuffer;
|
||
char *pWaveBuffer;
|
||
int waveAVIBegin;
|
||
int waveAVIEnd;
|
||
int waveAVISize;
|
||
char *pWaveAVIBuffer;
|
||
|
||
AVCodecContext *pCodecCtx;
|
||
AVCodec *pCodec;
|
||
} AVI_Audio_Data;
|
||
|
||
|
||
unsigned __stdcall PlayThread(void *params);
|
||
void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
|
||
|
||
class AVI_Grabber:public INPUT_IO
|
||
{
|
||
WORLD *pScn;
|
||
HRESULT hrinit;
|
||
|
||
|
||
DWORD sTimer;
|
||
double lastTime;
|
||
float volume;
|
||
|
||
//AVI_Redirect aviRedirect;
|
||
|
||
public:
|
||
AVFormatContext *pFormatCtx;
|
||
|
||
AVI_Video_Data vd;
|
||
AVI_Audio_Data sd;
|
||
|
||
int frameNew;
|
||
int processing;
|
||
HANDLE aviMutex;
|
||
|
||
public:
|
||
u32 UseAlphaMode;
|
||
int INIT (WORLD *pScene);
|
||
int FRAME ();
|
||
int END ();
|
||
IOTYPE GetType() {return IOtype_AVI;};
|
||
};
|
||
|
||
int AVI_Grabber::INIT(WORLD *pScene)
|
||
{
|
||
int allocSize;
|
||
int error;
|
||
av_register_all();
|
||
|
||
|
||
memset(&vd, 0, sizeof(vd));
|
||
memset(&sd, 0, sizeof(sd));
|
||
|
||
error = av_open_input_file(&pFormatCtx, (char *)MediaName, NULL, 0, NULL);
|
||
if (error < 0) return 0;
|
||
|
||
error = av_find_stream_info(pFormatCtx);
|
||
if (error < 0) return 0;
|
||
|
||
vd.streamIndex = -1;
|
||
for(int i=0; i<pFormatCtx->nb_streams && vd.streamIndex == -1; i++)
|
||
if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
|
||
vd.streamIndex=i;
|
||
if (vd.streamIndex < 0)
|
||
return 0;
|
||
|
||
sd.streamIndex = -1;
|
||
for(int i=0; i<pFormatCtx->nb_streams && sd.streamIndex == -1; i++)
|
||
if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
|
||
sd.streamIndex=i;
|
||
|
||
vd.pCodecCtx = pFormatCtx->streams[vd.streamIndex]->codec;
|
||
vd.pCodec = avcodec_find_decoder(vd.pCodecCtx->codec_id);
|
||
|
||
if (!vd.pCodec)
|
||
return 0;
|
||
|
||
if(vd.pCodec->capabilities & CODEC_CAP_TRUNCATED)
|
||
vd.pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
|
||
|
||
if (avcodec_open(vd.pCodecCtx, vd.pCodec) < 0)
|
||
return 0;
|
||
|
||
vd.pFrame = avcodec_alloc_frame();
|
||
allocSize = avpicture_get_size(vd.pCodecCtx->pix_fmt, vd.pCodecCtx->width, vd.pCodecCtx->height);
|
||
vd.pFrameBuffer = (uint8_t *)CC_malloc(allocSize);
|
||
avpicture_fill((AVPicture *)vd.pFrame,
|
||
vd.pFrameBuffer,
|
||
vd.pCodecCtx->pix_fmt,
|
||
vd.pCodecCtx->width, vd.pCodecCtx->height);
|
||
|
||
vd.pFrameMAP = avcodec_alloc_frame();
|
||
|
||
if (!vd.pFrame || !vd.pFrameMAP)
|
||
return 0;
|
||
|
||
Image.PITCH =
|
||
Image.SX = vd.pCodecCtx->width;
|
||
Image.SY = vd.pCodecCtx->height;
|
||
|
||
ulCurrentFrame = 0;
|
||
lTimeState = 0;
|
||
pScn = pScene;
|
||
allocSize = avpicture_get_size(PIX_FMT_RGB32, Image.SX , Image.SY);
|
||
Image.BASE = (s32 *)CC_malloc(allocSize);
|
||
|
||
avpicture_fill((AVPicture *)vd.pFrameMAP,
|
||
(uint8_t*)Image.BASE,
|
||
PIX_FMT_RGB32,
|
||
Image.SX, Image.SY);
|
||
|
||
|
||
if (Image.SX > 512)
|
||
{
|
||
Image.SX = 512;
|
||
Image.SY = ((Image.SX) * ((vd.pCodecCtx->height << 16) / vd.pCodecCtx->width)>>16);
|
||
}
|
||
if (!UseAlphaMode)
|
||
if (Image.SY > 512)
|
||
{
|
||
Image.SX = ((Image.SY) * ((vd.pCodecCtx->width << 16) / vd.pCodecCtx->height)>>16);
|
||
Image.SY = 512;
|
||
}
|
||
//CoUninitialize();
|
||
|
||
if (UseAlphaMode)
|
||
Image.SY >>= 1;
|
||
|
||
if (sd.streamIndex >= 0)
|
||
{
|
||
WAVEFORMATEX waveFormat;
|
||
memset(&waveFormat, 0, sizeof(waveFormat));
|
||
|
||
sd.pCodecCtx = pFormatCtx->streams[sd.streamIndex]->codec;
|
||
sd.pCodec = avcodec_find_decoder(sd.pCodecCtx->codec_id);
|
||
|
||
if (avcodec_open(sd.pCodecCtx, sd.pCodec) >= 0)
|
||
{
|
||
|
||
waveFormat.nSamplesPerSec = sd.pCodecCtx->sample_rate;
|
||
waveFormat.wBitsPerSample = 16; //sd.pCodecCtx->;
|
||
waveFormat.nChannels = sd.pCodecCtx->channels;
|
||
|
||
waveFormat.cbSize = 0; /* size of _extra_ info */
|
||
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||
waveFormat.nBlockAlign = (waveFormat.wBitsPerSample >> 3) * waveFormat.nChannels;
|
||
waveFormat.nAvgBytesPerSec = waveFormat.nBlockAlign * waveFormat.nSamplesPerSec;
|
||
|
||
memset(sd.waveHDR, 0, sizeof(sd.waveHDR));
|
||
sd.pAVBuffer = (uint8_t *)CC_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
||
sd.pWaveAVIBuffer = (char *)CC_malloc(WAVE_AVI_BUFFER_SIZE);
|
||
for (int uCurrentWHDR=0; uCurrentWHDR<NB_WHDR; uCurrentWHDR++)
|
||
{
|
||
sd.waveHDR[uCurrentWHDR].lpData = (char *)CC_malloc(WAVE_BUFFER_SIZE);
|
||
sd.waveHDR[uCurrentWHDR].dwBufferLength = WAVE_BUFFER_SIZE;
|
||
}
|
||
|
||
MMRESULT result = waveOutOpen(&sd.waveOut, WAVE_MAPPER, &waveFormat, (DWORD_PTR)waveOutProc, (DWORD_PTR)this, CALLBACK_FUNCTION);
|
||
for (int uCurrentWHDR=0; uCurrentWHDR<NB_WHDR; uCurrentWHDR++)
|
||
{
|
||
waveOutPrepareHeader( sd.waveOut, sd.waveHDR + uCurrentWHDR,sizeof(WAVEHDR) );
|
||
waveOutWrite( sd.waveOut, sd.waveHDR + uCurrentWHDR,sizeof(WAVEHDR) );
|
||
}
|
||
} else
|
||
{
|
||
sd.streamIndex = -1;
|
||
}
|
||
}
|
||
|
||
|
||
u32 threadID;
|
||
|
||
frameNew = 0;
|
||
processing = 1;
|
||
|
||
aviMutex = CreateMutex(NULL, FALSE, "AVIMutex");
|
||
_beginthreadex(NULL, 256, &PlayThread, (void *)this, 0, &threadID);
|
||
|
||
return 1;
|
||
}
|
||
|
||
|
||
|
||
int AVI_Grabber::END()
|
||
{
|
||
if (sd.waveOut)
|
||
{
|
||
waveOutPause( sd.waveOut );
|
||
waveOutClose( sd.waveOut );
|
||
}
|
||
|
||
processing = 0;
|
||
while (!processing)
|
||
Sleep(5);
|
||
|
||
if (vd.pFrameBuffer)
|
||
CC_free(vd.pFrameBuffer);
|
||
|
||
av_free(vd.pFrameMAP);
|
||
av_free(vd.pFrame);
|
||
|
||
// Close the codec
|
||
avcodec_close(vd.pCodecCtx);
|
||
// Close the video file
|
||
av_close_input_file(pFormatCtx);
|
||
|
||
return 1;
|
||
}
|
||
|
||
|
||
unsigned __stdcall PlayThread(void *params)
|
||
{
|
||
AVI_Grabber *pAviGrabber = (AVI_Grabber *)params;
|
||
AVPacket packet;
|
||
int bytesRemaining = 0;
|
||
int bytesDecoded = 0;
|
||
int got_picture = 0;
|
||
uint8_t *rawData = NULL;
|
||
|
||
u32 time = timeGetTime();
|
||
u32 currPacketTime = 0;
|
||
u32 frameTime = 40;
|
||
int sleepTime = 0;
|
||
int frameSize = 0;
|
||
|
||
packet.data = NULL;
|
||
|
||
while (pAviGrabber->processing)
|
||
{
|
||
switch (pAviGrabber->lTimeState)
|
||
{
|
||
case 0:
|
||
Sleep(10);
|
||
time = timeGetTime() - currPacketTime;
|
||
continue;
|
||
case 255:
|
||
av_seek_frame(pAviGrabber->pFormatCtx, -1, 0, AVSEEK_FLAG_ANY);
|
||
pAviGrabber->lTimeState = 0;
|
||
currPacketTime = 0;
|
||
time = timeGetTime();
|
||
continue;
|
||
}
|
||
|
||
|
||
if ((rawData || av_read_frame(pAviGrabber->pFormatCtx, &packet) >= 0) &&
|
||
(WAIT_OBJECT_0 == WaitForSingleObject(pAviGrabber->aviMutex, INFINITE)))
|
||
{
|
||
if (packet.stream_index == pAviGrabber->vd.streamIndex)
|
||
{
|
||
if (!rawData)
|
||
{
|
||
rawData = packet.data;
|
||
bytesRemaining = packet.size;
|
||
}
|
||
|
||
got_picture = 0;
|
||
bytesDecoded = avcodec_decode_video( pAviGrabber->vd.pCodecCtx, pAviGrabber->vd.pFrame,
|
||
&got_picture, rawData, bytesRemaining);
|
||
|
||
//if (bytesDecoded > bytesRemaining)
|
||
//{
|
||
// bytesDecoded = avcodec_decode_video( pAviGrabber->vd.pCodecCtx, pAviGrabber->vd.pFrame,
|
||
// &got_picture, rawData, bytesRemaining);
|
||
//}
|
||
|
||
bytesRemaining -= bytesDecoded;
|
||
if (bytesRemaining > 0)
|
||
rawData += bytesDecoded;
|
||
else
|
||
rawData = NULL;
|
||
|
||
if (got_picture)
|
||
{
|
||
currPacketTime = 1000 * /*packet.pts*/packet.dts * pAviGrabber->pFormatCtx->streams[pAviGrabber->vd.streamIndex]->time_base.num / pAviGrabber->pFormatCtx->streams[pAviGrabber->vd.streamIndex]->time_base.den;
|
||
sleepTime = currPacketTime - (timeGetTime() - time);
|
||
}
|
||
if (!rawData)
|
||
av_free_packet(&packet);
|
||
} else if (packet.stream_index == pAviGrabber->sd.streamIndex)
|
||
{
|
||
frameSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||
avcodec_decode_audio2( pAviGrabber->sd.pCodecCtx, (int16_t *)pAviGrabber->sd.pAVBuffer,
|
||
&frameSize, packet.data, packet.size);
|
||
|
||
currPacketTime = 1000 * /*packet.pts*/packet.dts * pAviGrabber->pFormatCtx->streams[pAviGrabber->sd.streamIndex]->time_base.num / pAviGrabber->pFormatCtx->streams[pAviGrabber->sd.streamIndex]->time_base.den;
|
||
sleepTime = currPacketTime - (timeGetTime() - time);
|
||
|
||
int copySize = min(frameSize, WAVE_BUFFER_SIZE);
|
||
if (pAviGrabber->sd.waveAVIEnd + frameSize > WAVE_AVI_BUFFER_SIZE)
|
||
{
|
||
int copySize1 = WAVE_AVI_BUFFER_SIZE - pAviGrabber->sd.waveAVIEnd;
|
||
memcpy( pAviGrabber->sd.pWaveAVIBuffer + pAviGrabber->sd.waveAVIEnd,
|
||
pAviGrabber->sd.pAVBuffer,
|
||
copySize1);
|
||
memcpy( pAviGrabber->sd.pWaveAVIBuffer,
|
||
pAviGrabber->sd.pAVBuffer + copySize1,
|
||
frameSize - copySize1);
|
||
pAviGrabber->sd.waveAVIEnd = frameSize - copySize1;
|
||
} else
|
||
{
|
||
memcpy( pAviGrabber->sd.pWaveAVIBuffer + pAviGrabber->sd.waveAVIEnd,
|
||
pAviGrabber->sd.pAVBuffer,
|
||
frameSize);
|
||
pAviGrabber->sd.waveAVIEnd += frameSize;
|
||
}
|
||
pAviGrabber->sd.waveAVISize += frameSize;
|
||
av_free_packet(&packet);
|
||
} else
|
||
av_free_packet(&packet);
|
||
|
||
ReleaseMutex(pAviGrabber->aviMutex);
|
||
}
|
||
|
||
if (sleepTime > 0)
|
||
{
|
||
Sleep(sleepTime);
|
||
sleepTime = 0;
|
||
}
|
||
if (got_picture)
|
||
{
|
||
pAviGrabber->frameNew = 1;
|
||
got_picture = 0;
|
||
}
|
||
|
||
}
|
||
pAviGrabber->processing = -1;
|
||
return 0;
|
||
}
|
||
|
||
|
||
void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
|
||
{
|
||
AVI_Grabber *pAviGrabber = (AVI_Grabber *)dwInstance;
|
||
|
||
if(uMsg != WOM_DONE)
|
||
return;
|
||
|
||
|
||
for ( int uCurrentWHDR = 0; uCurrentWHDR< NB_WHDR; uCurrentWHDR++)
|
||
{
|
||
if (pAviGrabber->sd.waveHDR[uCurrentWHDR].dwFlags & WHDR_DONE )
|
||
{
|
||
int copySize = min(pAviGrabber->sd.waveAVISize, WAVE_BUFFER_SIZE);
|
||
if (pAviGrabber->sd.waveAVIBegin + copySize > WAVE_AVI_BUFFER_SIZE)
|
||
{
|
||
int copySize1 = WAVE_AVI_BUFFER_SIZE - pAviGrabber->sd.waveAVIBegin;
|
||
memcpy( pAviGrabber->sd.waveHDR[uCurrentWHDR].lpData,
|
||
pAviGrabber->sd.pWaveAVIBuffer + pAviGrabber->sd.waveAVIBegin,
|
||
copySize1);
|
||
memcpy( pAviGrabber->sd.waveHDR[uCurrentWHDR].lpData + copySize1,
|
||
pAviGrabber->sd.pWaveAVIBuffer,
|
||
copySize - copySize1);
|
||
pAviGrabber->sd.waveAVIBegin = copySize - copySize1;
|
||
} else
|
||
{
|
||
memcpy( pAviGrabber->sd.waveHDR[uCurrentWHDR].lpData,
|
||
pAviGrabber->sd.pWaveAVIBuffer + pAviGrabber->sd.waveAVIBegin,
|
||
copySize );
|
||
pAviGrabber->sd.waveAVIBegin += copySize;
|
||
}
|
||
pAviGrabber->sd.waveAVISize -= copySize;
|
||
pAviGrabber->sd.waveHDR[uCurrentWHDR].dwBufferLength = copySize;
|
||
|
||
// Cas g<>n<EFBFBD>rique
|
||
waveOutUnprepareHeader ( hWaveOut, pAviGrabber->sd.waveHDR + uCurrentWHDR,sizeof(WAVEHDR) );
|
||
pAviGrabber->sd.waveHDR[uCurrentWHDR].dwFlags = 0;
|
||
waveOutPrepareHeader ( hWaveOut, pAviGrabber->sd.waveHDR + uCurrentWHDR,sizeof(WAVEHDR) );
|
||
waveOutWrite ( hWaveOut, pAviGrabber->sd.waveHDR + uCurrentWHDR,sizeof(WAVEHDR) );
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
int AVI_Grabber::FRAME()
|
||
{
|
||
if (!frameNew)
|
||
return 0;
|
||
|
||
if (WAIT_OBJECT_0 == WaitForSingleObject(aviMutex, INFINITE))
|
||
{
|
||
img_convert((AVPicture *)vd.pFrameMAP, PIX_FMT_RGB32,
|
||
(AVPicture *)vd.pFrame, vd.pCodecCtx->pix_fmt, vd.pCodecCtx->width, vd.pCodecCtx->height);
|
||
if (vd.pCodecCtx->width > Image.SX)
|
||
{
|
||
int i,j,IncX,AddX,IncY,AddY;
|
||
unsigned long *SRC_512,*SRC_640,*SRC_LAST;
|
||
SRC_512 = SRC_640 = (unsigned long*)Image.BASE;
|
||
IncY = 0;
|
||
AddY = (Image.SY<<16) / vd.pCodecCtx->height;
|
||
AddX = (Image.SX<<16) / vd.pCodecCtx->width;
|
||
for (i = 0,j = 0 ; i < vd.pCodecCtx->height; i++)
|
||
{
|
||
SRC_LAST = SRC_640 + vd.pCodecCtx->width;
|
||
IncX = 0;
|
||
while (SRC_640 < SRC_LAST)
|
||
{
|
||
*(SRC_512+(IncX>>16)) = *(SRC_640++);
|
||
IncX += AddX;
|
||
}
|
||
IncY += AddY;
|
||
SRC_512 = (unsigned long*)Image.BASE + ((IncY>>16) * Image.SX);
|
||
j++;
|
||
}
|
||
}
|
||
FLIP_V(&Image);
|
||
if (UseAlphaMode)
|
||
{
|
||
s32 *pAlpha,*pRGB,*pLast;
|
||
pAlpha = Image.BASE;
|
||
pRGB = Image.BASE + (Image.SY>>1) * Image.PITCH;
|
||
pLast = Image.BASE + Image.SY * Image.PITCH;
|
||
while (pRGB < pLast)
|
||
{
|
||
*(u32*)pAlpha <<= 24;
|
||
*pAlpha |= *pRGB & 0xffffff;
|
||
pAlpha++;
|
||
pRGB++;
|
||
}//*/
|
||
}
|
||
|
||
|
||
frameNew = 0;
|
||
|
||
ReleaseMutex(aviMutex);
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
//*/
|
||
|
||
|
||
#endif
|
||
|
||
//*********************************************
|
||
//*********************************************
|
||
|
||
INPUT_IO *AVI_CREATE(WORLD *pScene,char *Filename)
|
||
{
|
||
INPUT_IO *Ret;
|
||
u32 Alpha;
|
||
Alpha = 0;
|
||
if (GetFileNameExtend((char *)Filename) == 'AVIA' || GetFileNameExtend((char *)Filename) == 'WMVA')
|
||
{
|
||
Filename[strlen((char*)Filename)-1] = 0;
|
||
Alpha = 1;
|
||
}
|
||
if (!IsExist(Filename) && strnicmp(Filename, "http://", 7))
|
||
{
|
||
Ret = ERROR_CREATE("Avi not\nexist");
|
||
return Ret;
|
||
}
|
||
Ret = (INPUT_IO *)new(AVI_Grabber);
|
||
strcpy((char*)Ret->MediaName,Filename);
|
||
((AVI_Grabber*)Ret)->UseAlphaMode = Alpha;
|
||
|
||
if (!Ret->INIT(pScene))
|
||
{
|
||
delete Ret;
|
||
return NULL;
|
||
}
|
||
//Ret->FRAME();
|
||
return Ret;
|
||
} |