2018-02-18 18:48:51 -03:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include "fixer.h"
|
|
|
|
|
|
|
|
|
|
#include "bink.h"
|
|
|
|
|
|
|
|
|
|
#include <AL/al.h>
|
|
|
|
|
#include <AL/alc.h>
|
2020-05-22 01:34:17 +02:00
|
|
|
|
#include <SDL.h>
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
|
|
|
|
#include "libavcodec/avcodec.h"
|
|
|
|
|
#include "libavformat/avformat.h"
|
|
|
|
|
#include "libavutil/avutil.h"
|
2020-05-22 01:34:17 +02:00
|
|
|
|
#include "libavutil/imgutils.h"
|
2018-02-18 18:48:51 -03:00
|
|
|
|
#include "libavutil/channel_layout.h"
|
|
|
|
|
#include "libswscale/swscale.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#define DISABLE_MOVIES
|
|
|
|
|
//#define DISABLE_MUSIC
|
|
|
|
|
//#define DISABLE_FMVS
|
|
|
|
|
|
|
|
|
|
extern void SDL_Delay();
|
|
|
|
|
extern uint SDL_GetTicks();
|
|
|
|
|
extern int SoundSys_IsOn();
|
|
|
|
|
extern void DrawAvpMenuBink(char* buf, int width, int height, int pitch);
|
|
|
|
|
extern float PlatVolumeToGain(int volume);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#define AL_CHECK() { int err = alGetError(); if(err!=AL_NO_ERROR) printf("%s:%d ALError %04x\n", __FILE__, __LINE__, err); }
|
|
|
|
|
#define AL_CHECK() {}
|
|
|
|
|
|
|
|
|
|
#define FRAMEQUEUESIZE 4
|
|
|
|
|
|
|
|
|
|
struct binkMovie
|
|
|
|
|
{
|
|
|
|
|
AVFormatContext* avContext;
|
2020-05-22 01:34:17 +02:00
|
|
|
|
AVPacket packet;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
|
|
|
|
int videoStreamIndex;
|
|
|
|
|
AVCodecContext* videoCodecContext;
|
|
|
|
|
AVFrame* videoFrame;
|
|
|
|
|
struct SwsContext* videoScaleContext;
|
2020-05-22 01:34:17 +02:00
|
|
|
|
uint8_t* videoScalePicture[4];
|
|
|
|
|
int videoScaleLineSize[4];
|
2018-02-18 18:48:51 -03:00
|
|
|
|
uint videoScaleWidth;
|
|
|
|
|
uint videoScaleHeight;
|
2020-05-22 01:34:17 +02:00
|
|
|
|
enum AVPixelFormat videoScaleFormat;
|
|
|
|
|
float videoFrameDuration;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
|
|
|
|
int audioStreamIndex;
|
|
|
|
|
AVCodecContext* audioCodecContext;
|
|
|
|
|
AVFrame* audioFrame;
|
|
|
|
|
char* audioTempBuffer;
|
|
|
|
|
|
|
|
|
|
BOOL alInited;
|
|
|
|
|
ALuint alSource;
|
|
|
|
|
ALuint alBuffers[FRAMEQUEUESIZE];
|
|
|
|
|
ALuint alFreeBuffers[FRAMEQUEUESIZE];
|
|
|
|
|
ALuint alNumFreeBuffers;
|
|
|
|
|
ALuint alNumChannels;
|
|
|
|
|
ALenum alFormat;
|
|
|
|
|
ALuint alSampleRate;
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
uint timeStart;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
|
|
|
|
BOOL looping;
|
|
|
|
|
BOOL isfmv;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
static void BinkRenderMovie(struct binkMovie* aMovie)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(aMovie && aMovie->videoFrame && aMovie->videoScalePicture[0])
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
|
|
|
|
DrawAvpMenuBink(
|
2020-05-22 01:34:17 +02:00
|
|
|
|
aMovie->videoScalePicture[0],
|
2018-02-18 18:48:51 -03:00
|
|
|
|
aMovie->videoFrame->width,
|
|
|
|
|
aMovie->videoFrame->height,
|
2020-05-22 01:34:17 +02:00
|
|
|
|
aMovie->videoScaleLineSize[0]);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
static void BinkInitMovieStruct(struct binkMovie* aMovie)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
*aMovie = (struct binkMovie){
|
|
|
|
|
.audioStreamIndex = -1,
|
|
|
|
|
.videoStreamIndex = -1,
|
|
|
|
|
.videoScaleFormat = AV_PIX_FMT_NONE,
|
|
|
|
|
};
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
static void BinkReleaseMovie(struct binkMovie* aMovie)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
|
|
|
|
if(aMovie->alInited)
|
|
|
|
|
{
|
|
|
|
|
alSourceStop(aMovie->alSource);
|
|
|
|
|
alDeleteSources(1, &aMovie->alSource);
|
|
|
|
|
alDeleteBuffers(FRAMEQUEUESIZE, aMovie->alBuffers);
|
|
|
|
|
if(aMovie->audioTempBuffer)
|
|
|
|
|
free(aMovie->audioTempBuffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(aMovie->videoScaleContext)
|
2020-05-22 01:34:17 +02:00
|
|
|
|
av_freep(&aMovie->videoScalePicture[0]);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
|
|
|
|
if(aMovie->avContext)
|
|
|
|
|
avformat_close_input(&aMovie->avContext);
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(aMovie->audioCodecContext)
|
|
|
|
|
avcodec_free_context(&aMovie->audioCodecContext);
|
|
|
|
|
if(aMovie->audioFrame)
|
|
|
|
|
av_frame_free(&aMovie->audioFrame);
|
|
|
|
|
if(aMovie->videoCodecContext)
|
|
|
|
|
avcodec_free_context(&aMovie->videoCodecContext);
|
|
|
|
|
if(aMovie->videoFrame)
|
|
|
|
|
av_frame_free(&aMovie->videoFrame);
|
|
|
|
|
|
2018-02-18 18:48:51 -03:00
|
|
|
|
BinkInitMovieStruct(aMovie);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
static int DecodeVideoFrame(struct binkMovie* aMovie)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
int ret = avcodec_receive_frame(aMovie->videoCodecContext, aMovie->videoFrame);
|
|
|
|
|
if (ret < 0)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
return 0;
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(aMovie->videoScaleContext==NULL)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(aMovie->videoScaleWidth==0) aMovie->videoScaleWidth = aMovie->videoFrame->width;
|
|
|
|
|
if(aMovie->videoScaleHeight==0) aMovie->videoScaleHeight = aMovie->videoFrame->height;
|
|
|
|
|
if(aMovie->videoScaleFormat==AV_PIX_FMT_NONE) aMovie->videoScaleFormat = AV_PIX_FMT_RGB565;
|
|
|
|
|
|
|
|
|
|
aMovie->videoScaleContext = sws_getContext(
|
|
|
|
|
aMovie->videoFrame->width, aMovie->videoFrame->height,
|
|
|
|
|
aMovie->videoFrame->format,
|
|
|
|
|
aMovie->videoScaleWidth, aMovie->videoScaleHeight,
|
|
|
|
|
aMovie->videoScaleFormat,
|
|
|
|
|
SWS_FAST_BILINEAR, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
if (aMovie->videoScaleContext==NULL)
|
|
|
|
|
return 0;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
av_image_alloc(aMovie->videoScalePicture, aMovie->videoScaleLineSize,
|
|
|
|
|
aMovie->videoScaleWidth, aMovie->videoScaleHeight,
|
|
|
|
|
aMovie->videoScaleFormat, 1);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
sws_scale(aMovie->videoScaleContext,
|
|
|
|
|
(const uint8_t* const*)aMovie->videoFrame->data,
|
|
|
|
|
aMovie->videoFrame->linesize, 0, aMovie->videoFrame->height,
|
|
|
|
|
aMovie->videoScalePicture, aMovie->videoScaleLineSize);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
static int DecodeAudioFrame(struct binkMovie* aMovie)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
int decoded_frame_ready = 0;
|
|
|
|
|
av_frame_unref(aMovie->audioFrame);
|
|
|
|
|
//avcodec_get_frame_defaults(aMovie->audioFrame);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
int ret = avcodec_receive_frame(aMovie->audioCodecContext, aMovie->audioFrame);
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
return 0;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(!SoundSys_IsOn())
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if(!aMovie->alInited)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
alGenSources(1, &aMovie->alSource);
|
|
|
|
|
AL_CHECK();
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
alGenBuffers(FRAMEQUEUESIZE, aMovie->alBuffers);
|
|
|
|
|
AL_CHECK();
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
alSource3f(aMovie->alSource, AL_POSITION, 0.0, 0.0, 0.0);
|
|
|
|
|
alSource3f(aMovie->alSource, AL_VELOCITY, 0.0, 0.0, 0.0);
|
|
|
|
|
alSource3f(aMovie->alSource, AL_DIRECTION, 0.0, 0.0, 0.0);
|
|
|
|
|
alSourcef(aMovie->alSource, AL_ROLLOFF_FACTOR, 0.0);
|
|
|
|
|
alSourcei(aMovie->alSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
|
|
|
|
alSourcef(aMovie->alSource, AL_PITCH, 1);
|
|
|
|
|
alSourcef(aMovie->alSource, AL_GAIN, 1.0);
|
|
|
|
|
|
|
|
|
|
AL_CHECK();
|
|
|
|
|
|
|
|
|
|
aMovie->alNumFreeBuffers=FRAMEQUEUESIZE;
|
|
|
|
|
for(int i=0; i<aMovie->alNumFreeBuffers; i++)
|
|
|
|
|
aMovie->alFreeBuffers[i] = aMovie->alBuffers[i];
|
|
|
|
|
|
|
|
|
|
switch(aMovie->audioFrame->channel_layout)
|
|
|
|
|
{
|
|
|
|
|
case AV_CH_LAYOUT_MONO:
|
|
|
|
|
aMovie->alFormat = (aMovie->audioFrame->format == AV_SAMPLE_FMT_U8) ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16;
|
|
|
|
|
aMovie->alNumChannels = 1;
|
|
|
|
|
break;
|
|
|
|
|
case AV_CH_LAYOUT_STEREO:
|
|
|
|
|
aMovie->alFormat = (aMovie->audioFrame->format == AV_SAMPLE_FMT_U8) ? AL_FORMAT_STEREO8 : AL_FORMAT_STEREO16;
|
|
|
|
|
aMovie->alNumChannels = 2;
|
|
|
|
|
break;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
aMovie->alSampleRate = aMovie->audioFrame->sample_rate;
|
|
|
|
|
aMovie->audioTempBuffer = malloc(aMovie->alNumChannels * aMovie->audioFrame->nb_samples * 2 * 2);
|
|
|
|
|
aMovie->alInited=TRUE;
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
memset(aMovie->audioTempBuffer, 0, aMovie->alNumChannels * aMovie->audioFrame->nb_samples * 2 * 2);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(aMovie->alNumChannels==0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
// reclaim completed frames
|
|
|
|
|
int processedBuffers = 0;
|
|
|
|
|
alGetSourcei(aMovie->alSource, AL_BUFFERS_PROCESSED, &processedBuffers);
|
|
|
|
|
if(processedBuffers>0)
|
|
|
|
|
{
|
|
|
|
|
alSourceStop(aMovie->alSource);
|
|
|
|
|
while(processedBuffers>0)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
ALuint buffer = 0;
|
|
|
|
|
alSourceUnqueueBuffers(aMovie->alSource, 1, &buffer);
|
|
|
|
|
AL_CHECK();
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(buffer>0)
|
|
|
|
|
{
|
|
|
|
|
aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = buffer;
|
|
|
|
|
aMovie->alNumFreeBuffers++;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
2020-05-22 01:34:17 +02:00
|
|
|
|
processedBuffers--;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
2020-05-22 01:34:17 +02:00
|
|
|
|
alSourcePlay(aMovie->alSource);
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
// queue this frame
|
|
|
|
|
if(aMovie->alNumFreeBuffers>0)
|
|
|
|
|
{
|
|
|
|
|
ALuint alBuffer = aMovie->alFreeBuffers[aMovie->alNumFreeBuffers-1];
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
int sampleCount = aMovie->audioFrame->nb_samples * aMovie->alNumChannels;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
// 16bit is deafult
|
|
|
|
|
uint dataSize = sampleCount*2;
|
|
|
|
|
void* data = (void*) aMovie->audioFrame->extended_data[0];
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
switch(aMovie->audioFrame->format)
|
|
|
|
|
{
|
|
|
|
|
case AV_SAMPLE_FMT_U8:
|
|
|
|
|
{
|
|
|
|
|
dataSize = sampleCount;
|
|
|
|
|
} break;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
default:
|
|
|
|
|
case AV_SAMPLE_FMT_S16:
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
unsigned short* p = (unsigned short*) data;
|
|
|
|
|
for(int i=0; i<sampleCount; i++)
|
|
|
|
|
p[i] -= p[i]>>2;
|
|
|
|
|
*/
|
|
|
|
|
} break;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
case AV_SAMPLE_FMT_FLT:
|
|
|
|
|
{
|
|
|
|
|
data = (void*) aMovie->audioTempBuffer;
|
|
|
|
|
short* tempBuf = (short*) aMovie->audioTempBuffer;
|
|
|
|
|
float* srcBuf = (float*) aMovie->audioFrame->extended_data[0];
|
|
|
|
|
for(int i=0; i<sampleCount; i++)
|
|
|
|
|
{
|
|
|
|
|
float val = srcBuf[i] * 32768;
|
|
|
|
|
if(val > 32767) val = 32767;
|
|
|
|
|
if(val < -32768) val = 32768;
|
|
|
|
|
tempBuf[i] = (short) val;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
}
|
|
|
|
|
} break;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
case AV_SAMPLE_FMT_S32:
|
|
|
|
|
{
|
|
|
|
|
data = (void*) aMovie->audioTempBuffer;
|
|
|
|
|
short* tempBuf = (short*) aMovie->audioTempBuffer;
|
|
|
|
|
unsigned int* srcBuf = (unsigned int*) aMovie->audioFrame->extended_data[0];
|
|
|
|
|
for(int i=0; i<sampleCount; i++)
|
|
|
|
|
tempBuf[i] = (short) (((*srcBuf - *srcBuf>>2) >> 16) & 0x0000FFFF);
|
|
|
|
|
} break;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
case AV_SAMPLE_FMT_FLTP:
|
|
|
|
|
{
|
|
|
|
|
data = (void*) aMovie->audioTempBuffer;
|
|
|
|
|
short* tempBuf = (short*) aMovie->audioTempBuffer;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
for(int i=0; i<aMovie->audioFrame->nb_samples; i++)
|
|
|
|
|
{
|
|
|
|
|
for(int j=0; j<aMovie->alNumChannels; j++)
|
|
|
|
|
{
|
|
|
|
|
float* srcBuf = (float*) aMovie->audioFrame->extended_data[j];
|
|
|
|
|
float val = srcBuf[i] * 32768;
|
|
|
|
|
if(val > 32767) val = 32767;
|
|
|
|
|
if(val < -32768) val = 32768;
|
|
|
|
|
tempBuf[(i*aMovie->alNumChannels)+j] = (short) val;
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
2020-05-22 01:34:17 +02:00
|
|
|
|
} break;
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
alSourceStop(aMovie->alSource);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
//printf("fmt=%d, buffer size=%d, rdy=%d, len=%d, s1=%d, samples=%d\n", aMovie->audioFrame->format, dataSize, decoded_frame_ready, len, aPacket->size, sampleCount);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
alBufferData(alBuffer, aMovie->alFormat, data, dataSize-16, aMovie->alSampleRate);
|
|
|
|
|
AL_CHECK();
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
alSourceQueueBuffers(aMovie->alSource, 1, &alBuffer);
|
|
|
|
|
AL_CHECK();
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
float vx, vy, vz;
|
|
|
|
|
alGetListener3f(AL_VELOCITY, &vx, &vy, &vz);
|
|
|
|
|
alSource3f(aMovie->alSource, AL_VELOCITY, vx, vy, vz);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
alSourcePlay(aMovie->alSource);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
aMovie->alNumFreeBuffers--;
|
|
|
|
|
aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = 0;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
static int ReadFrame(struct binkMovie* aMovie)
|
|
|
|
|
{
|
|
|
|
|
// Read from file if no packet is buffered.
|
|
|
|
|
if (!aMovie->packet.buf && av_read_frame(aMovie->avContext, &aMovie->packet) < 0) {
|
|
|
|
|
if (aMovie->looping) {
|
|
|
|
|
av_seek_frame(aMovie->avContext, -1, 0, 0);
|
|
|
|
|
return ReadFrame(aMovie);
|
|
|
|
|
} else {
|
|
|
|
|
// Drain buffered frames.
|
|
|
|
|
if (aMovie->videoStreamIndex >= 0)
|
|
|
|
|
avcodec_send_packet(aMovie->videoCodecContext, NULL);
|
|
|
|
|
if (aMovie->audioStreamIndex >= 0)
|
|
|
|
|
avcodec_send_packet(aMovie->audioCodecContext, NULL);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Send the (possibly buffered) packet to decoder.
|
|
|
|
|
int ret = 0;
|
|
|
|
|
if (aMovie->packet.stream_index == aMovie->videoStreamIndex)
|
|
|
|
|
ret = avcodec_send_packet(aMovie->videoCodecContext, &aMovie->packet);
|
|
|
|
|
else if (aMovie->packet.stream_index == aMovie->audioStreamIndex)
|
|
|
|
|
ret = avcodec_send_packet(aMovie->audioCodecContext, &aMovie->packet);
|
|
|
|
|
|
|
|
|
|
// Keep the packet around for next time if decoder’s buffer is full.
|
|
|
|
|
if (ret == AVERROR(EAGAIN)) {
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
av_packet_unref(&aMovie->packet);
|
|
|
|
|
return ret < 0 ? 0 : 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
static int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename, BOOL aLoopFlag, BOOL aFmvFlag, BOOL aMusicFlag)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
BinkInitMovieStruct(aMovie);
|
|
|
|
|
aMovie->looping = aLoopFlag;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(aFmvFlag)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
aMovie->videoScaleWidth = 128;
|
|
|
|
|
aMovie->videoScaleHeight = 96;
|
|
|
|
|
aMovie->videoScaleFormat = AV_PIX_FMT_RGB24;
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(avformat_open_input(&aMovie->avContext, aFilename, NULL, NULL) < 0)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(!avformat_find_stream_info(aMovie->avContext, NULL) < 0)
|
|
|
|
|
{
|
|
|
|
|
BinkReleaseMovie(aMovie);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int numStreams = 0;
|
|
|
|
|
for(int i=0; i<aMovie->avContext->nb_streams; i++)
|
|
|
|
|
{
|
|
|
|
|
const AVStream* stream = aMovie->avContext->streams[i];
|
|
|
|
|
const AVCodec* codec = avcodec_find_decoder(stream->codecpar->codec_id);
|
|
|
|
|
if (!codec)
|
|
|
|
|
continue;
|
|
|
|
|
AVCodecContext *context = avcodec_alloc_context3(codec);
|
|
|
|
|
if (!context)
|
|
|
|
|
continue;
|
|
|
|
|
if (avcodec_parameters_to_context(context, stream->codecpar) < 0 ||
|
|
|
|
|
avcodec_open2(context, codec, NULL) < 0) {
|
|
|
|
|
avcodec_free_context(&context);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if (aMovie->videoStreamIndex < 0 && context->codec_type == AVMEDIA_TYPE_VIDEO)
|
|
|
|
|
{
|
|
|
|
|
aMovie->videoCodecContext = context;
|
|
|
|
|
aMovie->videoStreamIndex = i;
|
|
|
|
|
aMovie->videoFrame = av_frame_alloc();
|
|
|
|
|
aMovie->videoFrameDuration =
|
|
|
|
|
1000.0f * (float)stream->time_base.num / (float)stream->time_base.den;
|
|
|
|
|
numStreams++;
|
|
|
|
|
}
|
|
|
|
|
else if (aMovie->audioStreamIndex < 0 && context->codec_type == AVMEDIA_TYPE_AUDIO)
|
|
|
|
|
{
|
|
|
|
|
aMovie->audioCodecContext = context;
|
|
|
|
|
aMovie->audioStreamIndex = i;
|
|
|
|
|
aMovie->audioFrame = av_frame_alloc();
|
|
|
|
|
numStreams++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
avcodec_free_context(&context);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(aMovie->videoStreamIndex < 0 && aMovie->audioStreamIndex < 0)
|
|
|
|
|
{
|
|
|
|
|
BinkReleaseMovie(aMovie);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(!aFmvFlag)
|
|
|
|
|
{
|
|
|
|
|
for(int i=0; i<(FRAMEQUEUESIZE-1) * numStreams; i++)
|
|
|
|
|
ReadFrame(aMovie);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int BinkUpdateMovie(struct binkMovie* aMovie)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
|
|
|
|
if(!aMovie->avContext)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
const int t = SDL_GetTicks();
|
|
|
|
|
const int eof = !ReadFrame(aMovie);
|
|
|
|
|
|
|
|
|
|
int playing = 0;
|
|
|
|
|
if (aMovie->videoStreamIndex >= 0) {
|
|
|
|
|
if (aMovie->videoFrame->pts == 0)
|
|
|
|
|
aMovie->timeStart = t - aMovie->videoFrameDuration;
|
|
|
|
|
if (t - aMovie->timeStart >= aMovie->videoFrame->pts * aMovie->videoFrameDuration)
|
|
|
|
|
playing += DecodeVideoFrame(aMovie);
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
2020-05-22 01:34:17 +02:00
|
|
|
|
|
|
|
|
|
if (aMovie->audioStreamIndex >= 0) {
|
2018-02-18 18:48:51 -03:00
|
|
|
|
int processedBuffers = 0;
|
|
|
|
|
alGetSourcei(aMovie->alSource, AL_BUFFERS_PROCESSED, &processedBuffers);
|
2020-05-22 01:34:17 +02:00
|
|
|
|
while (!aMovie->alInited || aMovie->alNumFreeBuffers>0 || processedBuffers>0) {
|
|
|
|
|
if (DecodeAudioFrame(aMovie))
|
|
|
|
|
playing += 1;
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
2020-05-22 01:34:17 +02:00
|
|
|
|
return !eof || playing;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PlayBinkedFMV(char *filenamePtr, int volume)
|
|
|
|
|
{
|
|
|
|
|
struct binkMovie movie;
|
2020-05-22 01:34:17 +02:00
|
|
|
|
|
|
|
|
|
if (BinkStartMovie(&movie, filenamePtr, FALSE, FALSE, FALSE)) {
|
2018-02-18 18:48:51 -03:00
|
|
|
|
alSourcef(movie.alSource, AL_GAIN, PlatVolumeToGain(volume));
|
2020-05-22 01:34:17 +02:00
|
|
|
|
|
|
|
|
|
while (BinkUpdateMovie(&movie)) {
|
2018-02-18 18:48:51 -03:00
|
|
|
|
BinkRenderMovie(&movie);
|
|
|
|
|
FlipBuffers();
|
2020-05-22 01:34:17 +02:00
|
|
|
|
SDL_Delay(4); // don’t just burn it
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
|
|
|
|
BinkReleaseMovie(&movie);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
struct binkMovie menuBackgroundMovie;
|
|
|
|
|
|
|
|
|
|
void StartMenuBackgroundBink()
|
|
|
|
|
{
|
|
|
|
|
BinkStartMovie(&menuBackgroundMovie, "FMVs/Menubackground.bik", TRUE, FALSE, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int PlayMenuBackgroundBink()
|
|
|
|
|
{
|
|
|
|
|
ClearScreenToBlack();
|
|
|
|
|
if(BinkUpdateMovie(&menuBackgroundMovie))
|
|
|
|
|
{
|
|
|
|
|
BinkRenderMovie(&menuBackgroundMovie);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EndMenuBackgroundBink()
|
|
|
|
|
{
|
|
|
|
|
BinkReleaseMovie(&menuBackgroundMovie);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
struct binkMovie musicMovie;
|
|
|
|
|
|
|
|
|
|
int StartMusicBink(char* filenamePtr, BOOL looping)
|
|
|
|
|
{
|
2020-05-21 23:45:05 +02:00
|
|
|
|
if(!SoundSys_IsOn())
|
2018-02-18 18:48:51 -03:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
int ret = BinkStartMovie(&musicMovie, filenamePtr, looping, FALSE, TRUE);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int PlayMusicBink(int volume)
|
|
|
|
|
{
|
2020-05-21 23:45:05 +02:00
|
|
|
|
if(!SoundSys_IsOn())
|
2018-02-18 18:48:51 -03:00
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
if(!musicMovie.avContext)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
if(!(musicMovie.audioStreamIndex>=0 && musicMovie.alInited))
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
alSourcef(musicMovie.alSource, AL_GAIN, PlatVolumeToGain(volume));
|
|
|
|
|
for(int i=0; i<musicMovie.avContext->nb_streams * FRAMEQUEUESIZE; i++)
|
|
|
|
|
{
|
|
|
|
|
int processedBuffers = 0;
|
|
|
|
|
alGetSourcei(musicMovie.alSource, AL_BUFFERS_PROCESSED, &processedBuffers);
|
|
|
|
|
if(processedBuffers + musicMovie.alNumFreeBuffers > 0)
|
|
|
|
|
{
|
2020-05-22 01:34:17 +02:00
|
|
|
|
if(!ReadFrame(&musicMovie))
|
2018-02-18 18:48:51 -03:00
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EndMusicBink()
|
|
|
|
|
{
|
2020-05-21 23:45:05 +02:00
|
|
|
|
if(!SoundSys_IsOn())
|
2018-02-18 18:48:51 -03:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
BinkReleaseMovie(&musicMovie);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FMVHandle CreateBinkFMV(char* filenamePtr)
|
|
|
|
|
{
|
|
|
|
|
struct binkMovie* movie = malloc(sizeof(struct binkMovie));
|
|
|
|
|
BinkInitMovieStruct(movie);
|
|
|
|
|
|
|
|
|
|
if(!BinkStartMovie(movie, filenamePtr, FALSE, TRUE, FALSE))
|
|
|
|
|
{
|
|
|
|
|
free(movie);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return (FMVHandle)movie;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int UpdateBinkFMV(FMVHandle aFmvHandle, int volume)
|
|
|
|
|
{
|
2020-05-21 23:45:05 +02:00
|
|
|
|
if(aFmvHandle==0)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
struct binkMovie* movie = (struct binkMovie*)aFmvHandle;
|
|
|
|
|
alSourcef(movie->alSource, AL_GAIN, PlatVolumeToGain(volume));
|
|
|
|
|
BinkUpdateMovie(movie);
|
|
|
|
|
BinkUpdateMovie(movie);
|
|
|
|
|
BinkUpdateMovie(movie);
|
|
|
|
|
BinkUpdateMovie(movie);
|
|
|
|
|
return BinkUpdateMovie(movie);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CloseBinkFMV(FMVHandle aFmvHandle)
|
|
|
|
|
{
|
2020-05-21 23:45:05 +02:00
|
|
|
|
if(aFmvHandle==0)
|
2020-04-18 23:31:03 +02:00
|
|
|
|
return;
|
2018-02-18 18:48:51 -03:00
|
|
|
|
|
|
|
|
|
struct binkMovie* movie = (struct binkMovie*)aFmvHandle;
|
|
|
|
|
BinkReleaseMovie(movie);
|
|
|
|
|
free(movie);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char* GetBinkFMVImage(FMVHandle aFmvHandle)
|
|
|
|
|
{
|
2020-05-21 23:45:05 +02:00
|
|
|
|
if(aFmvHandle==0)
|
2018-02-18 18:48:51 -03:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
struct binkMovie* movie = (struct binkMovie*)aFmvHandle;
|
|
|
|
|
|
|
|
|
|
if(!movie->videoScaleContext)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2020-05-22 01:34:17 +02:00
|
|
|
|
return movie->videoScalePicture[0];
|
2018-02-18 18:48:51 -03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|