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 #include +#include #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,32 +106,281 @@ 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) +{ + 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; ialNumFreeBuffers; 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>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 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>2) >> 16) & 0x0000FFFF); + } break; + + case AV_SAMPLE_FMT_FLTP: + { + data = (void*) aMovie->audioTempBuffer; + short* tempBuf = (short*) aMovie->audioTempBuffer; + + for(int i=0; iaudioFrame->nb_samples; i++) + { + for(int j=0; jalNumChannels; 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 decoder’s 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); 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); @@ -137,327 +390,84 @@ int BinkStartMovie(struct binkMovie* aMovie, const char* aFilename, BOOL aLoopFl int numStreams = 0; for(int i=0; iavContext->nb_streams; i++) { - AVCodecContext* codec_context = aMovie->avContext->streams[i]->codec; - AVCodec* codec = avcodec_find_decoder(codec_context->codec_id); - if(codec) + 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) { - if((codec_context->codec_type==AVMEDIA_TYPE_VIDEO && aMovie->videoStreamIndex>=0) || (codec_context->codec_type==AVMEDIA_TYPE_AUDIO && aMovie->audioStreamIndex>=0)) - continue; - - if(avcodec_open2(codec_context, codec, 0) < 0) - continue; - - 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++; - } + 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; } - + if(!aFmvFlag) { for(int i=0; i<(FRAMEQUEUESIZE-1) * numStreams; i++) - BinkDecodeFrame(aMovie); + ReadFrame(aMovie); } - aMovie->timeLastUpdate = SDL_GetTicks(); return 1; } -int BinkDecodeFrameInternal(struct binkMovie* aMovie, AVPacket* aPacket) -{ - // 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; ialNumFreeBuffers; 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>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 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>2) >> 16) & 0x0000FFFF); - } break; - - case AV_SAMPLE_FMT_FLTP: - { - data = (void*) aMovie->audioTempBuffer; - short* tempBuf = (short*) aMovie->audioTempBuffer; - - for(int i=0; iaudioFrame->nb_samples; i++) - { - for(int j=0; jalNumChannels; 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) +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]; }