Replace deprecated ffmpeg functions and types

Refactor and update decoding functions. Use absolute frame times to
maintain consistent video FPS.
This commit is contained in:
Timotej Lazar 2020-05-22 01:34:17 +02:00
parent 628a27b38b
commit 3c3b436cc1

View file

@ -7,10 +7,12 @@
#include <AL/al.h> #include <AL/al.h>
#include <AL/alc.h> #include <AL/alc.h>
#include <SDL.h>
#include "libavcodec/avcodec.h" #include "libavcodec/avcodec.h"
#include "libavformat/avformat.h" #include "libavformat/avformat.h"
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#include "libavutil/imgutils.h"
#include "libavutil/channel_layout.h" #include "libavutil/channel_layout.h"
#include "libswscale/swscale.h" #include "libswscale/swscale.h"
@ -34,20 +36,20 @@ extern float PlatVolumeToGain(int volume);
struct binkMovie struct binkMovie
{ {
AVFormatContext* avContext; AVFormatContext* avContext;
AVPacket packet;
int videoStreamIndex; int videoStreamIndex;
AVCodec* videoCodec;
AVCodecContext* videoCodecContext; AVCodecContext* videoCodecContext;
AVFrame* videoFrame; AVFrame* videoFrame;
struct SwsContext* videoScaleContext; struct SwsContext* videoScaleContext;
AVPicture videoScalePicture; uint8_t* videoScalePicture[4];
int videoScaleLineSize[4];
uint videoScaleWidth; uint videoScaleWidth;
uint videoScaleHeight; uint videoScaleHeight;
uint videoScaleFormat; enum AVPixelFormat videoScaleFormat;
float videoFrameRate; float videoFrameDuration;
int audioStreamIndex; int audioStreamIndex;
AVCodec* audioCodec;
AVCodecContext* audioCodecContext; AVCodecContext* audioCodecContext;
AVFrame* audioFrame; AVFrame* audioFrame;
char* audioTempBuffer; char* audioTempBuffer;
@ -61,7 +63,7 @@ struct binkMovie
ALenum alFormat; ALenum alFormat;
ALuint alSampleRate; ALuint alSampleRate;
uint timeLastUpdate; uint timeStart;
BOOL looping; BOOL looping;
BOOL isfmv; BOOL isfmv;
@ -70,27 +72,29 @@ struct binkMovie
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
void BinkRenderMovie(struct binkMovie* aMovie) static void BinkRenderMovie(struct binkMovie* aMovie)
{ {
if(aMovie && aMovie->videoFrame && aMovie->videoScalePicture.data[0]) if(aMovie && aMovie->videoFrame && aMovie->videoScalePicture[0])
{ {
DrawAvpMenuBink( DrawAvpMenuBink(
aMovie->videoScalePicture.data[0], aMovie->videoScalePicture[0],
aMovie->videoFrame->width, aMovie->videoFrame->width,
aMovie->videoFrame->height, aMovie->videoFrame->height,
aMovie->videoScalePicture.linesize[0]); aMovie->videoScaleLineSize[0]);
} }
} }
void BinkInitMovieStruct(struct binkMovie* aMovie) static void BinkInitMovieStruct(struct binkMovie* aMovie)
{ {
memset((void*)aMovie, 0, sizeof(struct binkMovie)); *aMovie = (struct binkMovie){
aMovie->videoStreamIndex = -1; .audioStreamIndex = -1,
aMovie->audioStreamIndex = -1; .videoStreamIndex = -1,
.videoScaleFormat = AV_PIX_FMT_NONE,
};
} }
void BinkReleaseMovie(struct binkMovie* aMovie) static void BinkReleaseMovie(struct binkMovie* aMovie)
{ {
if(aMovie->alInited) if(aMovie->alInited)
{ {
@ -102,32 +106,281 @@ void BinkReleaseMovie(struct binkMovie* aMovie)
} }
if(aMovie->videoScaleContext) if(aMovie->videoScaleContext)
avpicture_free(&aMovie->videoScalePicture); av_freep(&aMovie->videoScalePicture[0]);
if(aMovie->avContext) if(aMovie->avContext)
avformat_close_input(&aMovie->avContext); avformat_close_input(&aMovie->avContext);
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);
BinkInitMovieStruct(aMovie); BinkInitMovieStruct(aMovie);
} }
int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename, BOOL aLoopFlag, BOOL aFmvFlag, BOOL aMusicFlag) static int DecodeVideoFrame(struct binkMovie* aMovie)
{
int ret = avcodec_receive_frame(aMovie->videoCodecContext, aMovie->videoFrame);
if (ret < 0)
return 0;
if(aMovie->videoScaleContext==NULL)
{
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;
av_image_alloc(aMovie->videoScalePicture, 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);
return 1;
}
static int DecodeAudioFrame(struct binkMovie* aMovie)
{
int decoded_frame_ready = 0;
av_frame_unref(aMovie->audioFrame);
//avcodec_get_frame_defaults(aMovie->audioFrame);
int ret = avcodec_receive_frame(aMovie->audioCodecContext, aMovie->audioFrame);
if (ret < 0)
return 0;
if(!SoundSys_IsOn())
return 0;
if(!aMovie->alInited)
{
alGenSources(1, &aMovie->alSource);
AL_CHECK();
alGenBuffers(FRAMEQUEUESIZE, aMovie->alBuffers);
AL_CHECK();
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;
}
aMovie->alSampleRate = aMovie->audioFrame->sample_rate;
aMovie->audioTempBuffer = malloc(aMovie->alNumChannels * aMovie->audioFrame->nb_samples * 2 * 2);
aMovie->alInited=TRUE;
}
memset(aMovie->audioTempBuffer, 0, aMovie->alNumChannels * aMovie->audioFrame->nb_samples * 2 * 2);
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)
{
ALuint buffer = 0;
alSourceUnqueueBuffers(aMovie->alSource, 1, &buffer);
AL_CHECK();
if(buffer>0)
{
aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = buffer;
aMovie->alNumFreeBuffers++;
}
processedBuffers--;
}
alSourcePlay(aMovie->alSource);
}
// queue this frame
if(aMovie->alNumFreeBuffers>0)
{
ALuint alBuffer = aMovie->alFreeBuffers[aMovie->alNumFreeBuffers-1];
int sampleCount = aMovie->audioFrame->nb_samples * aMovie->alNumChannels;
// 16bit is deafult
uint dataSize = sampleCount*2;
void* data = (void*) aMovie->audioFrame->extended_data[0];
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++)
{
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*aMovie->alNumChannels)+j] = (short) val;
}
}
} break;
}
alSourceStop(aMovie->alSource);
//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);
alBufferData(alBuffer, aMovie->alFormat, data, dataSize-16, aMovie->alSampleRate);
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);
alSourcePlay(aMovie->alSource);
aMovie->alNumFreeBuffers--;
aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = 0;
}
return 1;
}
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 decoders buffer is full.
if (ret == AVERROR(EAGAIN)) {
return 1;
} else {
av_packet_unref(&aMovie->packet);
return ret < 0 ? 0 : 1;
}
}
static int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename, BOOL aLoopFlag, BOOL aFmvFlag, BOOL aMusicFlag)
{ {
BinkInitMovieStruct(aMovie); BinkInitMovieStruct(aMovie);
aMovie->looping = aLoopFlag; aMovie->looping = aLoopFlag;
if(aFmvFlag) if(aFmvFlag)
{ {
aMovie->videoScaleWidth = 128; aMovie->videoScaleWidth = 128;
aMovie->videoScaleHeight = 96; aMovie->videoScaleHeight = 96;
aMovie->videoScaleFormat = AV_PIX_FMT_RGB24; aMovie->videoScaleFormat = AV_PIX_FMT_RGB24;
} }
if(avformat_open_input(&aMovie->avContext, aFilename, NULL, NULL) < 0) if(avformat_open_input(&aMovie->avContext, aFilename, NULL, NULL) < 0)
{ {
return 0; return 0;
} }
if(!avformat_find_stream_info(aMovie->avContext, NULL) < 0) if(!avformat_find_stream_info(aMovie->avContext, NULL) < 0)
{ {
BinkReleaseMovie(aMovie); BinkReleaseMovie(aMovie);
@ -137,327 +390,84 @@ int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename, BOOL aLoopFl
int numStreams = 0; int numStreams = 0;
for(int i=0; i<aMovie->avContext->nb_streams; i++) for(int i=0; i<aMovie->avContext->nb_streams; i++)
{ {
AVCodecContext* codec_context = aMovie->avContext->streams[i]->codec; const AVStream* stream = aMovie->avContext->streams[i];
AVCodec* codec = avcodec_find_decoder(codec_context->codec_id); const AVCodec* codec = avcodec_find_decoder(stream->codecpar->codec_id);
if(codec) 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;
}
if (aMovie->videoStreamIndex < 0 && context->codec_type == AVMEDIA_TYPE_VIDEO)
{ {
if((codec_context->codec_type==AVMEDIA_TYPE_VIDEO && aMovie->videoStreamIndex>=0) || (codec_context->codec_type==AVMEDIA_TYPE_AUDIO && aMovie->audioStreamIndex>=0)) aMovie->videoCodecContext = context;
continue; aMovie->videoStreamIndex = i;
aMovie->videoFrame = av_frame_alloc();
if(avcodec_open2(codec_context, codec, 0) < 0) aMovie->videoFrameDuration =
continue; 1000.0f * (float)stream->time_base.num / (float)stream->time_base.den;
numStreams++;
if(codec_context->codec_type==AVMEDIA_TYPE_VIDEO && !aMusicFlag) }
{ else if (aMovie->audioStreamIndex < 0 && context->codec_type == AVMEDIA_TYPE_AUDIO)
aMovie->videoCodec = codec; {
aMovie->videoCodecContext = codec_context; aMovie->audioCodecContext = context;
aMovie->videoStreamIndex = i; aMovie->audioStreamIndex = i;
aMovie->videoFrame = av_frame_alloc(); aMovie->audioFrame = av_frame_alloc();
numStreams++; numStreams++;
}
aMovie->videoFrameRate = (float)aMovie->avContext->streams[i]->avg_frame_rate.num / (float)aMovie->avContext->streams[i]->avg_frame_rate.den; else
} {
if(codec_context->codec_type==AVMEDIA_TYPE_AUDIO) avcodec_free_context(&context);
{
aMovie->audioCodec = codec;
aMovie->audioCodecContext = codec_context;
aMovie->audioStreamIndex = i;
aMovie->audioFrame = av_frame_alloc();
numStreams++;
}
} }
} }
if(aMovie->videoStreamIndex < 0 && aMovie->audioStreamIndex < 0) if(aMovie->videoStreamIndex < 0 && aMovie->audioStreamIndex < 0)
{ {
BinkReleaseMovie(aMovie); BinkReleaseMovie(aMovie);
return 0; return 0;
} }
if(!aFmvFlag) if(!aFmvFlag)
{ {
for(int i=0; i<(FRAMEQUEUESIZE-1) * numStreams; i++) for(int i=0; i<(FRAMEQUEUESIZE-1) * numStreams; i++)
BinkDecodeFrame(aMovie); ReadFrame(aMovie);
} }
aMovie->timeLastUpdate = SDL_GetTicks();
return 1; return 1;
} }
int BinkDecodeFrameInternal(struct binkMovie* aMovie, AVPacket* aPacket) static int BinkUpdateMovie(struct binkMovie* aMovie)
{
// decode video frame
if(aPacket->stream_index == aMovie->videoStreamIndex)
{
int decoded_frame_ready = 0;
int len = avcodec_decode_video2(aMovie->videoCodecContext, aMovie->videoFrame, &decoded_frame_ready, aPacket);
if(len<0)
return aMovie->looping;
if(decoded_frame_ready<1)
return 1;
if(aMovie->videoScaleContext==NULL)
{
if(aMovie->videoScaleWidth==0) aMovie->videoScaleWidth = aMovie->videoFrame->width;
if(aMovie->videoScaleHeight==0) aMovie->videoScaleHeight = aMovie->videoFrame->height;
if(aMovie->videoScaleFormat==0) 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;
avpicture_alloc(&aMovie->videoScalePicture, aMovie->videoScaleFormat, aMovie->videoScaleWidth, aMovie->videoScaleHeight);
}
sws_scale(aMovie->videoScaleContext, aMovie->videoFrame->data, aMovie->videoFrame->linesize, 0, aMovie->videoFrame->height, aMovie->videoScalePicture.data, aMovie->videoScalePicture.linesize);
}
// decode audio frame
else if(aPacket->stream_index == aMovie->audioStreamIndex)
{
int packageSize= aPacket->size;
int decoded_frame_ready = 0;
av_frame_unref(aMovie->audioFrame);
//avcodec_get_frame_defaults(aMovie->audioFrame);
int len = avcodec_decode_audio4(aMovie->audioCodecContext, aMovie->audioFrame, &decoded_frame_ready, aPacket);
if(len<0)
return aMovie->looping;
if(!SoundSys_IsOn())
return 0;
if(!aMovie->alInited)
{
alGenSources(1, &aMovie->alSource);
AL_CHECK();
alGenBuffers(FRAMEQUEUESIZE, aMovie->alBuffers);
AL_CHECK();
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;
}
aMovie->alSampleRate = aMovie->audioFrame->sample_rate;
aMovie->audioTempBuffer = malloc(aMovie->alNumChannels * aMovie->audioFrame->nb_samples * 2 * 2);
aMovie->alInited=TRUE;
}
memset(aMovie->audioTempBuffer, 0, aMovie->alNumChannels * aMovie->audioFrame->nb_samples * 2 * 2);
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)
{
ALuint buffer = 0;
alSourceUnqueueBuffers(aMovie->alSource, 1, &buffer);
AL_CHECK();
if(buffer>0)
{
aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = buffer;
aMovie->alNumFreeBuffers++;
}
processedBuffers--;
}
alSourcePlay(aMovie->alSource);
}
// queue this frame
if(aMovie->alNumFreeBuffers>0)
{
ALuint alBuffer = aMovie->alFreeBuffers[aMovie->alNumFreeBuffers-1];
int sampleCount = aMovie->audioFrame->nb_samples * aMovie->alNumChannels;
// 16bit is deafult
uint dataSize = sampleCount*2;
void* data = (void*) aMovie->audioFrame->extended_data[0];
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++)
{
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*aMovie->alNumChannels)+j] = (short) val;
}
}
} break;
}
alSourceStop(aMovie->alSource);
//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);
alBufferData(alBuffer, aMovie->alFormat, data, dataSize-16, aMovie->alSampleRate);
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);
alSourcePlay(aMovie->alSource);
aMovie->alNumFreeBuffers--;
aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = 0;
}
}
return 1;
}
int BinkDecodeFrame(struct binkMovie* aMovie)
{
AVPacket packet;
av_init_packet(&packet);
if(av_read_frame(aMovie->avContext, &packet) < 0)
{
if(!aMovie->looping)
return 0;
av_seek_frame(aMovie->avContext, -1, 0, 0);
if(av_read_frame(aMovie->avContext, &packet) < 0)
return 0;
}
int result = BinkDecodeFrameInternal(aMovie, &packet);
// if(packet.data)
// av_free_packet(&packet);
return result;
}
int BinkUpdateMovie(struct binkMovie* aMovie)
{ {
if(!aMovie->avContext) if(!aMovie->avContext)
return 0; return 0;
uint timeNow = SDL_GetTicks(); const int t = SDL_GetTicks();
float delta = ((float)(timeNow - aMovie->timeLastUpdate)) / 1000.0f; const int eof = !ReadFrame(aMovie);
int playing = 0;
if(aMovie->videoStreamIndex >= 0) if (aMovie->videoStreamIndex >= 0) {
{ if (aMovie->videoFrame->pts == 0)
if(delta < (1.0f / aMovie->videoFrameRate)) aMovie->timeStart = t - aMovie->videoFrameDuration;
{ if (t - aMovie->timeStart >= aMovie->videoFrame->pts * aMovie->videoFrameDuration)
if(aMovie->audioStreamIndex<0 || !SoundSys_IsOn() || aMovie->alNumFreeBuffers==0) playing += DecodeVideoFrame(aMovie);
return 1;
}
} }
else if(aMovie->audioStreamIndex >= 0 && aMovie->alInited)
{ if (aMovie->audioStreamIndex >= 0) {
int processedBuffers = 0; int processedBuffers = 0;
alGetSourcei(aMovie->alSource, AL_BUFFERS_PROCESSED, &processedBuffers); alGetSourcei(aMovie->alSource, AL_BUFFERS_PROCESSED, &processedBuffers);
if(aMovie->alNumFreeBuffers<=0 && processedBuffers == 0) while (!aMovie->alInited || aMovie->alNumFreeBuffers>0 || processedBuffers>0) {
return 1; if (DecodeAudioFrame(aMovie))
playing += 1;
else
break;
}
} }
return !eof || playing;
int streamsPlaying = 0;
if(aMovie->videoStreamIndex >= 0)
streamsPlaying += BinkDecodeFrame(aMovie);
if(aMovie->audioStreamIndex >= 0)
streamsPlaying += BinkDecodeFrame(aMovie);
aMovie->timeLastUpdate = timeNow;
return (streamsPlaying > 0) ? 1 : 0;
} }
@ -468,14 +478,14 @@ int BinkUpdateMovie(struct binkMovie* aMovie)
void PlayBinkedFMV(char *filenamePtr, int volume) void PlayBinkedFMV(char *filenamePtr, int volume)
{ {
struct binkMovie movie; struct binkMovie movie;
if(BinkStartMovie(&movie, filenamePtr, FALSE, FALSE, FALSE)) if (BinkStartMovie(&movie, filenamePtr, FALSE, FALSE, FALSE)) {
{
alSourcef(movie.alSource, AL_GAIN, PlatVolumeToGain(volume)); alSourcef(movie.alSource, AL_GAIN, PlatVolumeToGain(volume));
while(BinkUpdateMovie(&movie))
{ while (BinkUpdateMovie(&movie)) {
BinkRenderMovie(&movie); BinkRenderMovie(&movie);
FlipBuffers(); FlipBuffers();
SDL_Delay(4); // dont just burn it
} }
BinkReleaseMovie(&movie); BinkReleaseMovie(&movie);
} }
@ -541,7 +551,7 @@ int PlayMusicBink(int volume)
alGetSourcei(musicMovie.alSource, AL_BUFFERS_PROCESSED, &processedBuffers); alGetSourcei(musicMovie.alSource, AL_BUFFERS_PROCESSED, &processedBuffers);
if(processedBuffers + musicMovie.alNumFreeBuffers > 0) if(processedBuffers + musicMovie.alNumFreeBuffers > 0)
{ {
if(!BinkDecodeFrame(&musicMovie)) if(!ReadFrame(&musicMovie))
{ {
return 0; return 0;
} }
@ -612,7 +622,7 @@ char* GetBinkFMVImage(FMVHandle aFmvHandle)
if(!movie->videoScaleContext) if(!movie->videoScaleContext)
return 0; return 0;
return movie->videoScalePicture.data[0]; return movie->videoScalePicture[0];
} }