summaryrefslogtreecommitdiff
path: root/src/bink.c
diff options
context:
space:
mode:
authorTimotej Lazar <timotej.lazar@araneo.si>2020-05-22 01:34:17 +0200
committerTimotej Lazar <timotej.lazar@araneo.si>2020-05-30 02:32:31 +0200
commit3c3b436cc164c2ba1948c5bf57394e8c082442a5 (patch)
tree6340928320d7a184f380021b323e015afa24bec2 /src/bink.c
parent628a27b38b7fe89e51360ec81433bc04dbea0f2b (diff)
Replace deprecated ffmpeg functions and types
Refactor and update decoding functions. Use absolute frame times to maintain consistent video FPS.
Diffstat (limited to 'src/bink.c')
-rw-r--r--src/bink.c618
1 files changed, 314 insertions, 304 deletions
diff --git a/src/bink.c b/src/bink.c
index baa01ba..1e0ab77 100644
--- a/src/bink.c
+++ b/src/bink.c
@@ -7,10 +7,12 @@
#include <AL/al.h>
#include <AL/alc.h>
+#include <SDL.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
+#include "libavutil/imgutils.h"
#include "libavutil/channel_layout.h"
#include "libswscale/swscale.h"
@@ -34,20 +36,20 @@ extern float PlatVolumeToGain(int volume);
struct binkMovie
{
AVFormatContext* avContext;
+ AVPacket packet;
int videoStreamIndex;
- AVCodec* videoCodec;
AVCodecContext* videoCodecContext;
AVFrame* videoFrame;
struct SwsContext* videoScaleContext;
- AVPicture videoScalePicture;
+ uint8_t* videoScalePicture[4];
+ int videoScaleLineSize[4];
uint videoScaleWidth;
uint videoScaleHeight;
- uint videoScaleFormat;
- float videoFrameRate;
+ enum AVPixelFormat videoScaleFormat;
+ float videoFrameDuration;
int audioStreamIndex;
- AVCodec* audioCodec;
AVCodecContext* audioCodecContext;
AVFrame* audioFrame;
char* audioTempBuffer;
@@ -61,7 +63,7 @@ struct binkMovie
ALenum alFormat;
ALuint alSampleRate;
- uint timeLastUpdate;
+ uint timeStart;
BOOL looping;
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(
- aMovie->videoScalePicture.data[0],
+ aMovie->videoScalePicture[0],
aMovie->videoFrame->width,
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->videoStreamIndex = -1;
- aMovie->audioStreamIndex = -1;
+ *aMovie = (struct binkMovie){
+ .audioStreamIndex = -1,
+ .videoStreamIndex = -1,
+ .videoScaleFormat = AV_PIX_FMT_NONE,
+ };
}
-void BinkReleaseMovie(struct binkMovie* aMovie)
+static void BinkReleaseMovie(struct binkMovie* aMovie)
{
if(aMovie->alInited)
{
@@ -102,362 +106,368 @@ void BinkReleaseMovie(struct binkMovie* aMovie)
}
if(aMovie->videoScaleContext)
- avpicture_free(&aMovie->videoScalePicture);
+ av_freep(&aMovie->videoScalePicture[0]);
if(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);
}
-int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename, BOOL aLoopFlag, BOOL aFmvFlag, BOOL aMusicFlag)
+static int DecodeVideoFrame(struct binkMovie* aMovie)
{
- BinkInitMovieStruct(aMovie);
- aMovie->looping = aLoopFlag;
-
- if(aFmvFlag)
- {
- aMovie->videoScaleWidth = 128;
- aMovie->videoScaleHeight = 96;
- aMovie->videoScaleFormat = AV_PIX_FMT_RGB24;
- }
-
- if(avformat_open_input(&aMovie->avContext, aFilename, NULL, NULL) < 0)
- {
- return 0;
- }
-
- if(!avformat_find_stream_info(aMovie->avContext, NULL) < 0)
- {
- BinkReleaseMovie(aMovie);
+ int ret = avcodec_receive_frame(aMovie->videoCodecContext, aMovie->videoFrame);
+ if (ret < 0)
return 0;
- }
- int numStreams = 0;
- for(int i=0; i<aMovie->avContext->nb_streams; i++)
+ if(aMovie->videoScaleContext==NULL)
{
- AVCodecContext* codec_context = aMovie->avContext->streams[i]->codec;
- AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
- if(codec)
- {
- if((codec_context->codec_type==AVMEDIA_TYPE_VIDEO && aMovie->videoStreamIndex>=0) || (codec_context->codec_type==AVMEDIA_TYPE_AUDIO && aMovie->audioStreamIndex>=0))
- continue;
+ 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;
- if(avcodec_open2(codec_context, codec, 0) < 0)
- continue;
+ 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(codec_context->codec_type==AVMEDIA_TYPE_VIDEO && !aMusicFlag)
- {
- aMovie->videoCodec = codec;
- aMovie->videoCodecContext = codec_context;
- aMovie->videoStreamIndex = i;
- aMovie->videoFrame = av_frame_alloc();
- numStreams++;
-
- aMovie->videoFrameRate = (float)aMovie->avContext->streams[i]->avg_frame_rate.num / (float)aMovie->avContext->streams[i]->avg_frame_rate.den;
- }
- if(codec_context->codec_type==AVMEDIA_TYPE_AUDIO)
- {
- aMovie->audioCodec = codec;
- aMovie->audioCodecContext = codec_context;
- aMovie->audioStreamIndex = i;
- aMovie->audioFrame = av_frame_alloc();
- numStreams++;
- }
- }
- }
-
- if(aMovie->videoStreamIndex < 0 && aMovie->audioStreamIndex < 0)
- {
- BinkReleaseMovie(aMovie);
- return 0;
- }
-
- if(!aFmvFlag)
- {
- for(int i=0; i<(FRAMEQUEUESIZE-1) * numStreams; i++)
- BinkDecodeFrame(aMovie);
+ if (aMovie->videoScaleContext==NULL)
+ return 0;
+
+ av_image_alloc(aMovie->videoScalePicture, aMovie->videoScaleLineSize,
+ aMovie->videoScaleWidth, aMovie->videoScaleHeight,
+ aMovie->videoScaleFormat, 1);
}
- aMovie->timeLastUpdate = SDL_GetTicks();
+ sws_scale(aMovie->videoScaleContext,
+ (const uint8_t* const*)aMovie->videoFrame->data,
+ aMovie->videoFrame->linesize, 0, aMovie->videoFrame->height,
+ aMovie->videoScalePicture, aMovie->videoScaleLineSize);
return 1;
}
-
-int BinkDecodeFrameInternal(struct binkMovie* aMovie, AVPacket* aPacket)
+static int DecodeAudioFrame(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);
+ int decoded_frame_ready = 0;
+ av_frame_unref(aMovie->audioFrame);
+ //avcodec_get_frame_defaults(aMovie->audioFrame);
- if(aMovie->videoScaleContext==NULL)
- return 0;
-
- avpicture_alloc(&aMovie->videoScalePicture, aMovie->videoScaleFormat, aMovie->videoScaleWidth, aMovie->videoScaleHeight);
- }
+ int ret = avcodec_receive_frame(aMovie->audioCodecContext, aMovie->audioFrame);
+ if (ret < 0)
+ return 0;
- 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)
+ if(!SoundSys_IsOn())
+ return 0;
+
+ if(!aMovie->alInited)
{
-
- 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;
+ alGenSources(1, &aMovie->alSource);
+ AL_CHECK();
- 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();
+ alGenBuffers(FRAMEQUEUESIZE, aMovie->alBuffers);
+ 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;
+ 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);
+ 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)
+ 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)
{
- alSourceStop(aMovie->alSource);
- while(processedBuffers>0)
- {
- ALuint buffer = 0;
- alSourceUnqueueBuffers(aMovie->alSource, 1, &buffer);
- AL_CHECK();
+ ALuint buffer = 0;
+ alSourceUnqueueBuffers(aMovie->alSource, 1, &buffer);
+ AL_CHECK();
- if(buffer>0)
- {
- aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = buffer;
- aMovie->alNumFreeBuffers++;
- }
- processedBuffers--;
+ if(buffer>0)
+ {
+ aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = buffer;
+ aMovie->alNumFreeBuffers++;
}
- alSourcePlay(aMovie->alSource);
+ processedBuffers--;
}
+ alSourcePlay(aMovie->alSource);
+ }
- // queue this frame
- if(aMovie->alNumFreeBuffers>0)
- {
- ALuint alBuffer = aMovie->alFreeBuffers[aMovie->alNumFreeBuffers-1];
+ // queue this frame
+ if(aMovie->alNumFreeBuffers>0)
+ {
+ ALuint alBuffer = aMovie->alFreeBuffers[aMovie->alNumFreeBuffers-1];
- int sampleCount = aMovie->audioFrame->nb_samples * aMovie->alNumChannels;
+ int sampleCount = aMovie->audioFrame->nb_samples * aMovie->alNumChannels;
- // 16bit is deafult
- uint dataSize = sampleCount*2;
- void* data = (void*) aMovie->audioFrame->extended_data[0];
+ // 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;
+ 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;
+ 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;
+ 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;
+ }
+ } 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_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;
+ 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;
+ 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);
+ 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);
+ //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();
+ 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);
- alSourcePlay(aMovie->alSource);
+ alSourcePlay(aMovie->alSource);
- aMovie->alNumFreeBuffers--;
- aMovie->alFreeBuffers[aMovie->alNumFreeBuffers] = 0;
- }
+ 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 decoder’s buffer is full.
+ if (ret == AVERROR(EAGAIN)) {
+ return 1;
+ } else {
+ av_packet_unref(&aMovie->packet);
+ return ret < 0 ? 0 : 1;
+ }
+}
-int BinkDecodeFrame(struct binkMovie* aMovie)
+static int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename, BOOL aLoopFlag, BOOL aFmvFlag, BOOL aMusicFlag)
{
- AVPacket packet;
- av_init_packet(&packet);
+ BinkInitMovieStruct(aMovie);
+ aMovie->looping = aLoopFlag;
- if(av_read_frame(aMovie->avContext, &packet) < 0)
+ if(aFmvFlag)
{
- if(!aMovie->looping)
- return 0;
+ aMovie->videoScaleWidth = 128;
+ aMovie->videoScaleHeight = 96;
+ aMovie->videoScaleFormat = AV_PIX_FMT_RGB24;
+ }
- av_seek_frame(aMovie->avContext, -1, 0, 0);
- if(av_read_frame(aMovie->avContext, &packet) < 0)
- return 0;
+ if(avformat_open_input(&aMovie->avContext, aFilename, NULL, NULL) < 0)
+ {
+ return 0;
}
- int result = BinkDecodeFrameInternal(aMovie, &packet);
-
-// if(packet.data)
-// av_free_packet(&packet);
-
- return result;
-}
+ 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;
+ }
+ 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);
+ }
+ }
+ if(aMovie->videoStreamIndex < 0 && aMovie->audioStreamIndex < 0)
+ {
+ BinkReleaseMovie(aMovie);
+ return 0;
+ }
-int BinkUpdateMovie(struct binkMovie* aMovie)
+ if(!aFmvFlag)
+ {
+ for(int i=0; i<(FRAMEQUEUESIZE-1) * numStreams; i++)
+ ReadFrame(aMovie);
+ }
+
+ return 1;
+}
+
+
+static int BinkUpdateMovie(struct binkMovie* aMovie)
{
if(!aMovie->avContext)
return 0;
- uint timeNow = SDL_GetTicks();
- float delta = ((float)(timeNow - aMovie->timeLastUpdate)) / 1000.0f;
-
-
- if(aMovie->videoStreamIndex >= 0)
- {
- if(delta < (1.0f / aMovie->videoFrameRate))
- {
- if(aMovie->audioStreamIndex<0 || !SoundSys_IsOn() || aMovie->alNumFreeBuffers==0)
- return 1;
- }
+ 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);
}
- else if(aMovie->audioStreamIndex >= 0 && aMovie->alInited)
- {
+
+ if (aMovie->audioStreamIndex >= 0) {
int processedBuffers = 0;
alGetSourcei(aMovie->alSource, AL_BUFFERS_PROCESSED, &processedBuffers);
- if(aMovie->alNumFreeBuffers<=0 && processedBuffers == 0)
- return 1;
+ while (!aMovie->alInited || aMovie->alNumFreeBuffers>0 || processedBuffers>0) {
+ if (DecodeAudioFrame(aMovie))
+ playing += 1;
+ else
+ break;
+ }
}
-
- 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;
+ return !eof || playing;
}
@@ -468,14 +478,14 @@ int BinkUpdateMovie(struct binkMovie* aMovie)
void PlayBinkedFMV(char *filenamePtr, int volume)
{
struct binkMovie movie;
-
- if(BinkStartMovie(&movie, filenamePtr, FALSE, FALSE, FALSE))
- {
+
+ if (BinkStartMovie(&movie, filenamePtr, FALSE, FALSE, FALSE)) {
alSourcef(movie.alSource, AL_GAIN, PlatVolumeToGain(volume));
- while(BinkUpdateMovie(&movie))
- {
+
+ while (BinkUpdateMovie(&movie)) {
BinkRenderMovie(&movie);
FlipBuffers();
+ SDL_Delay(4); // don’t just burn it
}
BinkReleaseMovie(&movie);
}
@@ -541,7 +551,7 @@ int PlayMusicBink(int volume)
alGetSourcei(musicMovie.alSource, AL_BUFFERS_PROCESSED, &processedBuffers);
if(processedBuffers + musicMovie.alNumFreeBuffers > 0)
{
- if(!BinkDecodeFrame(&musicMovie))
+ if(!ReadFrame(&musicMovie))
{
return 0;
}
@@ -612,7 +622,7 @@ char* GetBinkFMVImage(FMVHandle aFmvHandle)
if(!movie->videoScaleContext)
return 0;
- return movie->videoScalePicture.data[0];
+ return movie->videoScalePicture[0];
}