summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bink.c268
1 files changed, 143 insertions, 125 deletions
diff --git a/src/bink.c b/src/bink.c
index 5bc99c5..b414658 100644
--- a/src/bink.c
+++ b/src/bink.c
@@ -19,7 +19,8 @@ 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
+#define AUDIO_FRAMES 32
+#define VIDEO_FRAMES 4
struct binkMovie {
AVFormatContext* avContext;
@@ -29,12 +30,15 @@ struct binkMovie {
AVCodecContext* videoCodecContext;
AVFrame* videoFrame;
struct SwsContext* videoScaleContext;
- uint8_t* videoScalePicture[4];
int videoScaleLineSize[4];
uint videoScaleWidth;
uint videoScaleHeight;
enum AVPixelFormat videoScaleFormat;
- float videoFrameDuration;
+
+ uint8_t* videoFrames[VIDEO_FRAMES][4];
+ int currentFrame;
+ int renderedFrames;
+ float frameDuration;
int audioStreamIndex;
AVCodecContext* audioCodecContext;
@@ -43,8 +47,8 @@ struct binkMovie {
BOOL alInited;
ALuint alSource;
- ALuint alBuffers[FRAMEQUEUESIZE];
- ALuint alFreeBuffers[FRAMEQUEUESIZE];
+ ALuint alBuffers[AUDIO_FRAMES];
+ ALuint alFreeBuffers[AUDIO_FRAMES];
ALuint alNumFreeBuffers;
ALuint alNumChannels;
ALenum alFormat;
@@ -54,15 +58,23 @@ struct binkMovie {
BOOL looping;
};
-static void BinkRenderMovie(struct binkMovie* aMovie)
+static int BinkRenderMovie(struct binkMovie* movie)
{
- if (aMovie && aMovie->videoFrame && aMovie->videoScalePicture[0]) {
- DrawAvpMenuBink(
- aMovie->videoScalePicture[0],
- aMovie->videoFrame->width,
- aMovie->videoFrame->height,
- aMovie->videoScaleLineSize[0]);
+ const int t = SDL_GetTicks() - movie->timeStart;
+ int dt = 0;
+ while (movie->renderedFrames > 1 &&
+ (dt = t - (movie->currentFrame + 1) * movie->frameDuration) >= 0) {
+ movie->currentFrame++;
+ movie->renderedFrames--;
+ }
+
+ if (movie->renderedFrames) {
+ DrawAvpMenuBink(movie->videoFrames[movie->currentFrame%VIDEO_FRAMES][0],
+ movie->videoFrame->width,
+ movie->videoFrame->height,
+ movie->videoScaleLineSize[0]);
}
+ return dt;
}
static void BinkInitMovieStruct(struct binkMovie* aMovie)
@@ -79,7 +91,7 @@ static void BinkReleaseMovie(struct binkMovie* aMovie)
if (aMovie->alInited) {
alSourceStop(aMovie->alSource);
alDeleteSources(1, &aMovie->alSource);
- alDeleteBuffers(FRAMEQUEUESIZE, aMovie->alBuffers);
+ alDeleteBuffers(AUDIO_FRAMES, aMovie->alBuffers);
if (aMovie->audioTempBuffer)
free(aMovie->audioTempBuffer);
}
@@ -97,7 +109,8 @@ static void BinkReleaseMovie(struct binkMovie* aMovie)
if (aMovie->videoScaleContext) {
sws_freeContext(aMovie->videoScaleContext);
- av_freep(&aMovie->videoScalePicture[0]);
+ for (int i = 0; i < VIDEO_FRAMES; i++)
+ av_freep(&aMovie->videoFrames[i][0]);
}
BinkInitMovieStruct(aMovie);
@@ -105,9 +118,6 @@ static void BinkReleaseMovie(struct binkMovie* aMovie)
static int DecodeVideoFrame(struct binkMovie* aMovie)
{
- if (avcodec_receive_frame(aMovie->videoCodecContext, aMovie->videoFrame) != 0)
- return 0;
-
// Initialize scale context.
if (aMovie->videoScaleContext == NULL) {
if (aMovie->videoScaleWidth == 0)
@@ -127,23 +137,42 @@ static int DecodeVideoFrame(struct binkMovie* aMovie)
if (aMovie->videoScaleContext == NULL)
return 0;
- av_image_alloc(aMovie->videoScalePicture, aMovie->videoScaleLineSize,
- aMovie->videoScaleWidth, aMovie->videoScaleHeight,
- aMovie->videoScaleFormat, 1);
+ for (int i = 0; i < VIDEO_FRAMES; i++) {
+ av_image_alloc(
+ aMovie->videoFrames[i], aMovie->videoScaleLineSize,
+ aMovie->videoScaleWidth, aMovie->videoScaleHeight,
+ aMovie->videoScaleFormat, 1);
+ }
}
sws_scale(aMovie->videoScaleContext,
(const uint8_t* const*)aMovie->videoFrame->data,
aMovie->videoFrame->linesize, 0, aMovie->videoFrame->height,
- aMovie->videoScalePicture, aMovie->videoScaleLineSize);
+ aMovie->videoFrames[(aMovie->currentFrame+aMovie->renderedFrames) % VIDEO_FRAMES],
+ aMovie->videoScaleLineSize);
+ aMovie->renderedFrames++;
return 1;
}
-static int DecodeAudioFrame(struct binkMovie* aMovie)
+// Reclaim completed audio buffers.
+static int ProcessAudio(struct binkMovie* aMovie)
{
- if (avcodec_receive_frame(aMovie->audioCodecContext, aMovie->audioFrame) != 0)
+ if (!aMovie->alInited)
return 0;
+ int processed = 0;
+ alGetSourcei(aMovie->alSource, AL_BUFFERS_PROCESSED, &processed);
+ if (processed > 0) {
+ ALuint buffers[AUDIO_FRAMES];
+ alSourceUnqueueBuffers(aMovie->alSource, processed, buffers);
+ for (int i = 0; i < processed; i++)
+ aMovie->alFreeBuffers[aMovie->alNumFreeBuffers++] = buffers[i];
+ }
+ return 1;
+}
+
+static int DecodeAudioFrame(struct binkMovie* aMovie)
+{
if (!SoundSys_IsOn())
return 0;
@@ -170,95 +199,87 @@ static int DecodeAudioFrame(struct binkMovie* aMovie)
if (aMovie->alNumChannels == 0)
return 0;
- // reclaim completed frames
- int processed = 0;
- alGetSourcei(aMovie->alSource, AL_BUFFERS_PROCESSED, &processed);
- if (processed > 0) {
- ALuint buffers[FRAMEQUEUESIZE];
- alSourceUnqueueBuffers(aMovie->alSource, processed, buffers);
- AL_CHECK();
- for (int i = 0; i < processed; i++)
- aMovie->alFreeBuffers[aMovie->alNumFreeBuffers++] = buffers[i];
- }
+ if (aMovie->alNumFreeBuffers == 0)
+ return 0;
// queue this frame
- if (aMovie->alNumFreeBuffers > 0) {
- ALuint alBuffer = aMovie->alFreeBuffers[aMovie->alNumFreeBuffers-1];
+ ALuint alBuffer = aMovie->alFreeBuffers[aMovie->alNumFreeBuffers-1];
- int sampleCount = aMovie->audioFrame->nb_samples * aMovie->alNumChannels;
- uint dataSize = sampleCount * 2; // 16bit is deafult
- void* data = (void*)aMovie->audioFrame->extended_data[0];
+ int sampleCount = aMovie->audioFrame->nb_samples * aMovie->alNumChannels;
+ uint dataSize = sampleCount * 2; // 16bit is deafult
+ void* data = (void*)aMovie->audioFrame->extended_data[0];
- switch (aMovie->audioFrame->format) {
- case AV_SAMPLE_FMT_U8: {
- dataSize = sampleCount;
- } break;
+ switch (aMovie->audioFrame->format) {
+ case AV_SAMPLE_FMT_U8: {
+ dataSize = sampleCount;
+ } break;
- 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;
-
- 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++) {
+ 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;
+
+ 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;
+ }
+ } break;
+
+ 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;
+
+ case AV_SAMPLE_FMT_FLTP: {
+ data = (void*)aMovie->audioTempBuffer;
+ short* tempBuf = (short*)aMovie->audioTempBuffer;
+ 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] = (short)val;
+ tempBuf[(i*aMovie->alNumChannels)+j] = (short)val;
}
- } break;
-
- 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;
-
- case AV_SAMPLE_FMT_FLTP: {
- data = (void*)aMovie->audioTempBuffer;
- short* tempBuf = (short*)aMovie->audioTempBuffer;
- 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;
- }
- }
- } break;
}
+ } break;
+ }
- alSourceStop(aMovie->alSource);
-
- alBufferData(alBuffer, aMovie->alFormat, data, dataSize - 16, aMovie->alSampleRate);
- AL_CHECK();
+ alBufferData(alBuffer, aMovie->alFormat, data, dataSize - 16, aMovie->alSampleRate);
+ AL_CHECK();
- alSourceQueueBuffers(aMovie->alSource, 1, &alBuffer);
- AL_CHECK();
+ alSourceQueueBuffers(aMovie->alSource, 1, &alBuffer);
+ AL_CHECK();
- float vx, vy, vz;
- alGetListener3f(AL_VELOCITY, &vx, &vy, &vz);
- alSource3f(aMovie->alSource, AL_VELOCITY, vx, vy, vz);
+ float vx, vy, vz;
+ alGetListener3f(AL_VELOCITY, &vx, &vy, &vz);
+ alSource3f(aMovie->alSource, AL_VELOCITY, vx, vy, vz);
+ int state = 0;
+ alGetSourcei(aMovie->alSource, AL_SOURCE_STATE, &state);
+ if (state != AL_PLAYING)
alSourcePlay(aMovie->alSource);
- aMovie->alNumFreeBuffers--;
- aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = 0;
- }
+ aMovie->alNumFreeBuffers--;
+ aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = 0;
+
return 1;
}
@@ -281,7 +302,7 @@ static int ReadPacket(struct binkMovie* aMovie)
}
// Send the (possibly buffered) packet to decoder.
- int ret = 0;
+ int ret = AVERROR(EAGAIN);
if (aMovie->packet.stream_index == aMovie->videoStreamIndex)
ret = avcodec_send_packet(aMovie->videoCodecContext, &aMovie->packet);
else if (aMovie->packet.stream_index == aMovie->audioStreamIndex)
@@ -335,8 +356,9 @@ static int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename,
aMovie->videoCodecContext = context;
aMovie->videoStreamIndex = i;
aMovie->videoFrame = av_frame_alloc();
- aMovie->videoFrameDuration =
+ aMovie->frameDuration =
1000.0f * (float)stream->time_base.num / (float)stream->time_base.den;
+ aMovie->timeStart = SDL_GetTicks();
numStreams++;
} else if (aMovie->audioStreamIndex < 0 && context->codec_type == AVMEDIA_TYPE_AUDIO) {
aMovie->audioCodecContext = context;
@@ -352,8 +374,8 @@ static int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename,
alSourcef(aMovie->alSource, AL_PITCH, 1.0);
alSourcef(aMovie->alSource, AL_GAIN, 1.0);
- alGenBuffers(FRAMEQUEUESIZE, aMovie->alBuffers);
- aMovie->alNumFreeBuffers = FRAMEQUEUESIZE;
+ alGenBuffers(AUDIO_FRAMES, aMovie->alBuffers);
+ aMovie->alNumFreeBuffers = AUDIO_FRAMES;
for (int i = 0; i < aMovie->alNumFreeBuffers; i++)
aMovie->alFreeBuffers[i] = aMovie->alBuffers[i];
@@ -369,7 +391,7 @@ static int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename,
}
if (!aFmvFlag) {
- for (int i = 0; i < (FRAMEQUEUESIZE-1) * numStreams; i++)
+ for (int i = 0; i < (AUDIO_FRAMES + VIDEO_FRAMES) / 2; i++)
ReadPacket(aMovie);
}
@@ -381,29 +403,18 @@ static int BinkUpdateMovie(struct binkMovie* aMovie)
if(!aMovie->avContext)
return 0;
- const int t = SDL_GetTicks();
const int eof = !ReadPacket(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)
+ if (aMovie->videoStreamIndex >= 0 && aMovie->renderedFrames < VIDEO_FRAMES)
+ if (avcodec_receive_frame(aMovie->videoCodecContext, aMovie->videoFrame) == 0)
playing += DecodeVideoFrame(aMovie);
- }
- if (aMovie->audioStreamIndex >= 0) {
- int processedBuffers = 0;
- alGetSourcei(aMovie->alSource, AL_BUFFERS_PROCESSED, &processedBuffers);
- while (!aMovie->alInited || aMovie->alNumFreeBuffers>0 || processedBuffers>0) {
- if (DecodeAudioFrame(aMovie))
- playing += 1;
- else
- break;
- }
- }
+ if (aMovie->audioStreamIndex >= 0 && aMovie->alNumFreeBuffers > 0)
+ if (avcodec_receive_frame(aMovie->audioCodecContext, aMovie->audioFrame) == 0)
+ playing += DecodeAudioFrame(aMovie);
- return !eof || playing;
+ return eof && !playing ? -1 : playing;
}
void PlayBinkedFMV(char* filenamePtr, int volume)
@@ -411,10 +422,15 @@ void PlayBinkedFMV(char* filenamePtr, int volume)
struct binkMovie movie;
if (BinkStartMovie(&movie, filenamePtr, FALSE, FALSE, FALSE)) {
alSourcef(movie.alSource, AL_GAIN, PlatVolumeToGain(volume));
- while (BinkUpdateMovie(&movie)) {
- BinkRenderMovie(&movie);
+ int updated = 0;
+ while ((updated = BinkUpdateMovie(&movie)) >= 0) {
+ ProcessAudio(&movie);
+ int dt = BinkRenderMovie(&movie);
FlipBuffers();
- SDL_Delay(4); // don’t just burn it
+
+ // don’t just burn it
+ if (!updated && dt > 0)
+ SDL_Delay(dt);
}
BinkReleaseMovie(&movie);
}
@@ -433,7 +449,8 @@ void StartMenuBackgroundBink()
int PlayMenuBackgroundBink()
{
ClearScreenToBlack();
- if (BinkUpdateMovie(&menuBackgroundMovie)) {
+ if (BinkUpdateMovie(&menuBackgroundMovie) >= 0) {
+ ProcessAudio(&menuBackgroundMovie);
BinkRenderMovie(&menuBackgroundMovie);
return 1;
}
@@ -468,7 +485,7 @@ int PlayMusicBink(int volume)
return 1;
alSourcef(musicMovie.alSource, AL_GAIN, PlatVolumeToGain(volume));
- for (int i = 0; i < musicMovie.avContext->nb_streams * FRAMEQUEUESIZE; i++) {
+ for (int i = 0; i < musicMovie.avContext->nb_streams * AUDIO_FRAMES; i++) {
int processedBuffers = 0;
alGetSourcei(musicMovie.alSource, AL_BUFFERS_PROCESSED, &processedBuffers);
if (processedBuffers + musicMovie.alNumFreeBuffers > 0)
@@ -526,10 +543,11 @@ void CloseBinkFMV(FMVHandle aFmvHandle)
char* GetBinkFMVImage(FMVHandle aFmvHandle)
{
if (aFmvHandle == 0)
- return 0;
+ return NULL;
struct binkMovie* movie = (struct binkMovie*)aFmvHandle;
- if(!movie->videoScaleContext)
- return 0;
- return movie->videoScalePicture[0];
+ if (!movie->videoScaleContext)
+ return NULL;
+ return movie->renderedFrames ?
+ movie->videoFrames[movie->currentFrame%VIDEO_FRAMES][0] : NULL;
}