diff --git a/build-all.sh b/build-all.sh index f95451f64..977dd68ee 100755 --- a/build-all.sh +++ b/build-all.sh @@ -48,7 +48,7 @@ function buildAll() { mkdir -p ${G_GENERATED} -if [[ 1 == 1 ]]; then +if [[ 0 == 1 ]]; then pushd thirdparty/bzip2 clearAndEnterBuild cmake ${COMMON} \ @@ -94,7 +94,6 @@ if [[ 1 == 1 ]]; then .. make install popd -fi pushd thirdparty/SDL2_image clearAndEnterBuild @@ -132,7 +131,6 @@ fi cp -f external/libwebp/libwebpdemux.a "${G_TARGET}/lib/." popd -if [[ 1 == 1 ]]; then pushd thirdparty/SDL2_mixer clearAndEnterBuild cmake ${COMMON} \ @@ -503,7 +501,7 @@ sudo apt-get install -y \ buildAll linux x86_64 2>&1 | tee ${G_BUILDDIR}/linux-x86_64.log -buildAll windows x86_64 2>&1 | tee ${G_BUILDDIR}/windows-x86_64.log +#buildAll windows x86_64 2>&1 | tee ${G_BUILDDIR}/windows-x86_64.log #buildAll linux x86 #buildAll macos aarch64 diff --git a/src/singe.c b/src/singe.c index 273f7b6ec..fb13543a7 100644 --- a/src/singe.c +++ b/src/singe.c @@ -63,6 +63,9 @@ LSEC_API int luaopen_ssl_config(lua_State *L); //#define DEBUG_TOOLS +#define INDEX_DISPLAY_START -1 +#define INDEX_DISPLAY_STOP -2 + #define AUDIO_MAX_VOLUME 63 #define MAX_TITLE_LENGTH 1024 #define MAX_MICE 4 @@ -197,7 +200,7 @@ enum { INPUT_QUIT, INPUT_PAUSE, INPUT_CONSOLE, - // Added in Singe 2.x + // Added in Singe 2.00 INPUT_ACTION_4, INPUT_TILT, INPUT_GRAB, @@ -304,6 +307,8 @@ int32_t apiDebugPrint(lua_State *L); int32_t apiDiscAudio(lua_State *L); int32_t apiDiscChangeSpeed(lua_State *L); +int32_t apiDiscGetAudioTrack(lua_State *L); +int32_t apiDiscGetAudioTracks(lua_State *L); int32_t apiDiscGetFrame(lua_State *L); int32_t apiDiscGetHeight(lua_State *L); int32_t apiDiscGetState(lua_State *L); @@ -313,6 +318,7 @@ int32_t apiDiscPauseAtFrame(lua_State *L); int32_t apiDiscPlay(lua_State *L); int32_t apiDiscSearch(lua_State *L); int32_t apiDiscSearchBlanking(lua_State *L); +int32_t apiDiscSetAudioTrack(lua_State *L); int32_t apiDiscSetFps(lua_State *L); int32_t apiDiscSkipBackward(lua_State *L); int32_t apiDiscSkipBlanking(lua_State *L); @@ -389,6 +395,8 @@ int32_t apiSpriteScale(lua_State *L); int32_t apiSpriteUnload(lua_State *L); int32_t apiVideoDraw(lua_State *L); +int32_t apiVideoGetAudioTrack(lua_State *L); +int32_t apiVideoGetAudioTracks(lua_State *L); int32_t apiVideoGetFrame(lua_State *L); int32_t apiVideoGetFrameCount(lua_State *L); int32_t apiVideoGetHeight(lua_State *L); @@ -399,6 +407,7 @@ int32_t apiVideoLoad(lua_State *L); int32_t apiVideoPause(lua_State *L); int32_t apiVideoPlay(lua_State *L); int32_t apiVideoSeek(lua_State *L); +int32_t apiVideoSetAudioTrack(lua_State *L); int32_t apiVideoSetVolume(lua_State *L); int32_t apiVideoUnload(lua_State *L); @@ -621,6 +630,50 @@ int32_t apiDiscChangeSpeed(lua_State *L) { } +int32_t apiDiscGetAudioTrack(lua_State *L) { + bool result = false; + int64_t r = 0; + + (void)L; + + if (_global.videoHandle >= 0) { + r = videoGetAudioTrack(_global.videoHandle); + result = true; + } + + if (result) { + luaTrace(L, "discGetAudioTrack", "%ld", r); + } else { + luaDie(L, "discGetAudioTrack", "Failed!"); + } + + lua_pushnumber(L, r); + return 1; +} + + +int32_t apiDiscGetAudioTracks(lua_State *L) { + bool result = false; + int64_t r = 0; + + (void)L; + + if (_global.videoHandle >= 0) { + r = videoGetAudioTracks(_global.videoHandle); + result = true; + } + + if (result) { + luaTrace(L, "discGetAudioTracks", "%ld", r); + } else { + luaDie(L, "discGetAudioTracks", "Failed!"); + } + + lua_pushnumber(L, r); + return 1; +} + + int32_t apiDiscGetFrame(lua_State *L) { int64_t frame = 0; @@ -707,6 +760,36 @@ int32_t apiDiscSearchBlanking(lua_State *L) { } +int32_t apiDiscSetAudioTrack(lua_State *L) { + int32_t n = lua_gettop(L); + bool result = false; + int64_t track = 0; + double d; + + if (n == 1) { + if (lua_isnumber(L, 1)) { + d = lua_tonumber(L, 1); track = (int32_t)d; + if (_global.videoHandle >= 0) { + if ((track >= 0) && (track < videoGetAudioTracks(_global.videoHandle))) { + videoSetAudioTrack(_global.videoHandle, track); + } else { + luaDie(L, "discSetAudioTrack", "Invalid audio track in apiDiscSetAudioTrack."); + } + result = true; + } + } + } + + if (result) { + luaTrace(L, "discSetAudioTrack", "%d", track); + } else { + luaDie(L, "discSetAudioTrack", "Failed!"); + } + + return 0; +} + + int32_t apiDiscSetFps(lua_State *L) { (void)L; //***REMOVED*** @@ -2251,6 +2334,66 @@ int32_t apiVideoDraw(lua_State *L) { } +int32_t apiVideoGetAudioTrack(lua_State *L) { + int32_t n = lua_gettop(L); + bool result = false; + int64_t r = 0; + int32_t id = -1; + double d; + VideoT *video = NULL; + + if (n == 1) { + if (lua_isnumber(L, 1)) { + d = lua_tonumber(L, 1); id = (int32_t)d; + // Get our video structure + HASH_FIND_INT(_global.videoList, &id, video); + if (!video) luaDie(L, "videoGetAudioTrack", "No video at index %d in apiVideoGetAudioTrack.", id); + r = videoGetAudioTrack(video->handle); + result = true; + } + } + + if (result) { + luaTrace(L, "videoGetAudioTrack", "%d %ld", id, r); + } else { + luaDie(L, "videoGetAudioTrack", "Failed!"); + } + + lua_pushnumber(L, r); + return 1; +} + + +int32_t apiVideoGetAudioTracks(lua_State *L) { + int32_t n = lua_gettop(L); + bool result = false; + int64_t r = 0; + int32_t id = -1; + double d; + VideoT *video = NULL; + + if (n == 1) { + if (lua_isnumber(L, 1)) { + d = lua_tonumber(L, 1); id = (int32_t)d; + // Get our video structure + HASH_FIND_INT(_global.videoList, &id, video); + if (!video) luaDie(L, "videoGetAudioTracks", "No video at index %d in apiVideoGetAudioTracks.", id); + r = videoGetAudioTracks(video->handle); + result = true; + } + } + + if (result) { + luaTrace(L, "videoGetAudioTracks", "%d %ld", id, r); + } else { + luaDie(L, "videoGetAudioTracks", "Failed!"); + } + + lua_pushnumber(L, r); + return 1; +} + + int32_t apiVideoGetFrame(lua_State *L) { int32_t n = lua_gettop(L); bool result = false; @@ -2536,7 +2679,7 @@ int32_t apiVideoPlay(lua_State *L) { } -int32_t apiVideoSeek(lua_State *L) { +int32_t apiVideoSeek(lua_State *L) { int32_t n = lua_gettop(L); bool result = false; int32_t id = -1; @@ -2568,7 +2711,43 @@ int32_t apiVideoSeek(lua_State *L) { } -int32_t apiVideoSetVolume(lua_State *L) { +int32_t apiVideoSetAudioTrack(lua_State *L) { + int32_t n = lua_gettop(L); + bool result = false; + int32_t id = -1; + int64_t track = 0; + double d; + VideoT *video = NULL; + + if (n == 2) { + if (lua_isnumber(L, 1)) { + if (lua_isnumber(L, 2)) { + d = lua_tonumber(L, 1); id = (int32_t)d; + d = lua_tonumber(L, 2); track = (int32_t)d; + // Get our video structure + HASH_FIND_INT(_global.videoList, &id, video); + if (!video) luaDie(L, "videoSetAudioTrack", "No video at index %d in apiVideoSetAudioTrack.", id); + if ((track >= 0) && (track < videoGetAudioTracks(video->handle))) { + videoSetAudioTrack(video->handle, track); + } else { + luaDie(L, "videoSetAudioTrack", "Invalid audio track in video at index %d in apiVideoSetAudioTrack.", id); + } + result = true; + } + } + } + + if (result) { + luaTrace(L, "videoSetAudioTrack", "%d %d", id, track); + } else { + luaDie(L, "videoSetAudioTrack", "Failed!"); + } + + return 0; +} + + +int32_t apiVideoSetVolume(lua_State *L) { int32_t n = lua_gettop(L); bool result = false; int32_t id = -1; @@ -3303,7 +3482,7 @@ void doIndexDisplay(int32_t percent) { // 'percent' 0 to 100 is the actual display. // 'percent' -2 shuts the display down. - if (percent == -1) { + if (percent == INDEX_DISPLAY_START) { // Setup SDL_RenderGetLogicalSize(_global.renderer, &oldW, &oldH); SDL_RenderSetLogicalSize(_global.renderer, screenW, screenH); @@ -3328,7 +3507,7 @@ void doIndexDisplay(int32_t percent) { return; } - if (percent == -2) { + if (percent == INDEX_DISPLAY_STOP) { // Shutdown SDL_DestroyTexture(texDisc); SDL_DestroyTexture(texGlass); @@ -3949,6 +4128,8 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { lua_register(_global.luaContext, "discAudio", apiDiscAudio); lua_register(_global.luaContext, "discChangeSpeed", apiDiscChangeSpeed); + lua_register(_global.luaContext, "discGetAudioTrack", apiDiscGetAudioTrack); + lua_register(_global.luaContext, "discGetAudioTracks", apiDiscGetAudioTracks); lua_register(_global.luaContext, "discGetFrame", apiDiscGetFrame); lua_register(_global.luaContext, "discGetHeight", apiDiscGetHeight); lua_register(_global.luaContext, "discGetState", apiDiscGetState); @@ -3958,6 +4139,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { lua_register(_global.luaContext, "discPlay", apiDiscPlay); lua_register(_global.luaContext, "discSearch", apiDiscSearch); lua_register(_global.luaContext, "discSearchBlanking", apiDiscSearchBlanking); + lua_register(_global.luaContext, "discSetAudioTrack", apiDiscSetAudioTrack); lua_register(_global.luaContext, "discSetFPS", apiDiscSetFps); lua_register(_global.luaContext, "discSkipBackward", apiDiscSkipBackward); lua_register(_global.luaContext, "discSkipBlanking", apiDiscSkipBlanking); @@ -4034,6 +4216,8 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { lua_register(_global.luaContext, "spriteUnload", apiSpriteUnload); lua_register(_global.luaContext, "videoDraw", apiVideoDraw); + lua_register(_global.luaContext, "videoGetAudioTrack", apiVideoGetAudioTrack); + lua_register(_global.luaContext, "videoGetAudioTracks", apiVideoGetAudioTracks); lua_register(_global.luaContext, "videoGetFrame", apiVideoGetFrame); lua_register(_global.luaContext, "videoGetFrameCount", apiVideoGetFrameCount); lua_register(_global.luaContext, "videoGetHeight", apiVideoGetHeight); @@ -4044,6 +4228,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { lua_register(_global.luaContext, "videoPause", apiVideoPause); lua_register(_global.luaContext, "videoPlay", apiVideoPlay); lua_register(_global.luaContext, "videoSeek", apiVideoSeek); + lua_register(_global.luaContext, "videoSetAudioTrack", apiVideoSetAudioTrack); lua_register(_global.luaContext, "videoSetVolume", apiVideoSetVolume); lua_register(_global.luaContext, "videoUnload", apiVideoUnload); @@ -4054,7 +4239,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { // Open main video file progTrace("Opening main video file"); - doIndexDisplay(-1); + doIndexDisplay(INDEX_DISPLAY_START); videoSetIndexCallback(doIndexDisplay); if (_global.conf->isFrameFile) { _global.frameFileHandle = frameFileLoad(_global.conf->videoFile, _global.conf->dataDir, (bool)_global.conf->stretchVideo, _global.renderer, _global.conf->showCalculated); @@ -4066,7 +4251,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { if (_global.videoHandle < 0) utilDie("Unable to load video file: %s", _global.conf->videoFile); videoSetVolume(_global.videoHandle, _global.conf->volumeVldp, _global.conf->volumeVldp); videoSetIndexCallback(NULL); - doIndexDisplay(-2); + doIndexDisplay(INDEX_DISPLAY_STOP); // Should we resize the window? if (conf->resolutionWasCalculated && !conf->fullScreen && !conf->fullScreenWindow) { diff --git a/src/videoPlayer.c b/src/videoPlayer.c index 38093c17a..666080f4d 100644 --- a/src/videoPlayer.c +++ b/src/videoPlayer.c @@ -33,48 +33,53 @@ #define AUDIO_SILENCE_SECONDS 2 +typedef struct AudioStreamS { + FFMS_AudioSource *audioSource; + const FFMS_AudioProperties *audioProps; +} AudioStreamT; + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpadded" typedef struct VideoPlayerS { - int32_t id; - bool playing; - bool resetTime; - byte *audioBuffer; - byte audioSampleBytes; - byte *audioSilenceRaw; - char errMsg[1024]; - int32_t volumeLeft; - int32_t volumeRight; - int32_t audioTrack; - int32_t videoTrack; - int32_t audioSampleSize; - int32_t mixSampleSize; - int32_t audioSilenceChannel; - int64_t frame; - int64_t audioBufferSize; - int64_t frameDeltaTime; - int64_t lastFrameTime; - int64_t timestamp; - int64_t audioDelta; - int64_t audioPosition; - int64_t framesPlayed; - Uint16 audioFormat; - Uint32 lastTickTime; - Uint32 audioSilenceSize; - //double audioAdjustment; - Mix_Chunk *silenceChunk; - SDL_AudioStream *audioStream; - SDL_Texture *videoTexture; - FFMS_ErrorInfo errInfo; - FFMS_AudioSource *audioSource; - FFMS_VideoSource *videoSource; - const FFMS_AudioProperties *audioProps; - const FFMS_VideoProperties *videoProps; - const FFMS_Frame *propFrame; - const FFMS_TrackTimeBase *videoTimeBase; - const FFMS_Frame *frameData; - const FFMS_FrameInfo *frameInfo; - UT_hash_handle hh; + int32_t id; + bool playing; + bool resetTime; + byte *audioBuffer; + byte audioSampleBytes; + byte *audioSilenceRaw; + char errMsg[1024]; + int32_t volumeLeft; + int32_t volumeRight; + int32_t videoTrack; + int32_t audioSampleSize; + int32_t mixSampleSize; + int32_t audioSilenceChannel; + int64_t frame; + int64_t audioBufferSize; + int64_t frameDeltaTime; + int64_t lastFrameTime; + int64_t timestamp; + int64_t audioDelta; + int64_t audioPosition; + int64_t framesPlayed; + Uint16 audioFormat; + Uint32 lastTickTime; + Uint32 audioSilenceSize; + //double audioAdjustment; + Mix_Chunk *silenceChunk; + SDL_AudioStream *audioStream; + SDL_Texture *videoTexture; + FFMS_ErrorInfo errInfo; + int32_t currentAudioTrack; + int32_t audioSourceCount; + AudioStreamT *audio; + FFMS_VideoSource *videoSource; + const FFMS_VideoProperties *videoProps; + const FFMS_Frame *propFrame; + const FFMS_TrackTimeBase *videoTimeBase; + const FFMS_Frame *frameData; + const FFMS_FrameInfo *frameInfo; + UT_hash_handle hh; } VideoPlayerT; #pragma GCC diagnostic pop @@ -196,13 +201,18 @@ int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bo FFMS_Index *vIndex = NULL; FFMS_Index *aIndex = NULL; VideoPlayerT *v = NULL; + int32_t x = 0; + int32_t count = 0; + FFMS_Track *track = NULL; + int32_t ttype = FFMS_TYPE_UNKNOWN; // Create new videoPlayer v = calloc(1, sizeof(VideoPlayerT)); if (!v) utilDie("Unable to allocate new video player."); // Set some starting values - v->audioTrack = -1; + v->audioSourceCount = 0; + v->currentAudioTrack = -1; v->videoTrack = -1; v->audioSilenceChannel = -1; v->playing = false; // Start paused @@ -215,8 +225,8 @@ int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bo vIndex = _createIndex(vFilename, indexPath, true, false, v); aIndex = _createIndex(aFilename, indexPath, false, true, v); } else { - vIndex = _createIndex(vFilename, indexPath, true, true, v); - aIndex = vIndex; + vIndex = _createIndex(vFilename, indexPath, true, true, v); + aIndex = vIndex; aFilename = vFilename; } @@ -237,13 +247,50 @@ int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bo pixelFormats[1] = -1; if (FFMS_SetOutputFormatV2(v->videoSource, pixelFormats, v->propFrame->EncodedWidth, v->propFrame->EncodedHeight, FFMS_RESIZER_BICUBIC, &v->errInfo)) utilDie("%s", v->errInfo.Buffer); - // Find audio track - v->audioTrack = FFMS_GetFirstTrackOfType(aIndex, FFMS_TYPE_AUDIO, &v->errInfo); - if (v->audioTrack >= 0) { - v->audioSource = FFMS_CreateAudioSource(aFilename, v->audioTrack, aIndex, FFMS_DELAY_FIRST_VIDEO_TRACK, &v->errInfo); - if (v->audioSource == NULL) utilDie("%s", v->errInfo.Buffer); - // Get audio properties - v->audioProps = FFMS_GetAudioProperties(v->audioSource); + // Find audio track(s) + //utilSay("Tracks in file: %d", FFMS_GetNumTracks(aIndex)); + for (x=0; x 0) { + // Allocate space for the tracks. + v->audio = (AudioStreamT *)calloc(count, sizeof(AudioStreamT)); + // Now create them. + for (x=0; xaudio[v->audioSourceCount].audioSource = FFMS_CreateAudioSource(aFilename, x, aIndex, FFMS_DELAY_FIRST_VIDEO_TRACK, &v->errInfo); + if (v->audio[v->audioSourceCount].audioSource == NULL) utilDie("%s", v->errInfo.Buffer); + v->audio[v->audioSourceCount].audioProps = FFMS_GetAudioProperties(v->audio[v->audioSourceCount].audioSource); + v->audioSourceCount++; + } + } + // Current audio track. + v->currentAudioTrack = 0; } // Indicies are now part of audioSource & videoSource, so release these @@ -263,10 +310,10 @@ int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bo SDL_RenderSetLogicalSize(renderer, v->propFrame->EncodedWidth, v->propFrame->EncodedHeight); } - // Do we have audio? - if (v->audioSource) { + // Do we have audio? All audio streams must have the same format! + if (v->audioSourceCount > 0) { // Determine audio format - switch (v->audioProps->SampleFormat) { + switch (v->audio[0].audioProps->SampleFormat) { case FFMS_FMT_U8: v->audioFormat = AUDIO_U8; v->audioSampleBytes = 1; @@ -287,15 +334,15 @@ int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bo utilDie("Unknown audio sample format."); break; } - if (v->audioProps->Channels > 2) utilDie("Only mono and stereo audio are supported."); + if (v->audio[0].audioProps->Channels > 2) utilDie("Only mono and stereo audio are supported."); // Create audio stream to convert audio to our desired format - v->audioStream = SDL_NewAudioStream(v->audioFormat, (Uint8)v->audioProps->Channels, v->audioProps->SampleRate, _mixFormat, _mixChannels, _mixRate); + v->audioStream = SDL_NewAudioStream(v->audioFormat, (Uint8)v->audio[0].audioProps->Channels, v->audio[0].audioProps->SampleRate, _mixFormat, _mixChannels, _mixRate); if (!v->audioStream) utilDie("%s", SDL_GetError()); // Create a buffer to read audio into before conversion v->mixSampleSize = SDL_AUDIO_BITSIZE(_mixFormat) / 8 * _mixChannels; - v->audioSampleSize = v->audioSampleBytes * v->audioProps->Channels; + v->audioSampleSize = v->audioSampleBytes * v->audio[0].audioProps->Channels; v->audioBufferSize = v->audioSampleSize * AUDIO_SAMPLE_PREREAD; v->audioBuffer = (byte *)malloc((size_t)v->audioBufferSize * sizeof(byte)); if (!v->audioBuffer) utilDie("Unable to allocate %ld byte audio buffer.", (size_t)v->audioBufferSize * sizeof(byte)); @@ -371,6 +418,28 @@ int32_t videoIsPlaying(int32_t playerHandle) { } +int32_t videoGetAudioTrack(int32_t playerHandle) { + VideoPlayerT *v = NULL; + + // Get our player structure + HASH_FIND_INT(_videoPlayerHash, &playerHandle, v); + if (!v) utilDie("No video player at index %d in videoGetAudioTrack.", playerHandle); + + return v->currentAudioTrack; +} + + +int32_t videoGetAudioTracks(int32_t playerHandle) { + VideoPlayerT *v = NULL; + + // Get our player structure + HASH_FIND_INT(_videoPlayerHash, &playerHandle, v); + if (!v) utilDie("No video player at index %d in videoGetAudioTracks.", playerHandle); + + return v->audioSourceCount; +} + + int64_t videoGetFrame(int32_t playerHandle) { VideoPlayerT *v = NULL; @@ -505,6 +574,23 @@ int32_t videoSeek(int32_t playerHandle, int64_t seekFrame) { } +int32_t videoSetAudioTrack(int32_t playerHandle, int32_t track) { + VideoPlayerT *v = NULL; + + // Get our player structure + HASH_FIND_INT(_videoPlayerHash, &playerHandle, v); + if (!v) utilDie("No video player at index %d in videoSetAudioTrack.", playerHandle); + + if ((track >= 0) && (track < v->audioSourceCount)) { + v->currentAudioTrack = track; + } else { + utilDie("Invalid audio track in videoSetAudioTrack."); + } + + return 0; +} + + int32_t videoSetIndexCallback(videoIndexingCallback callback) { _indexingFunction = callback; return 0; @@ -527,19 +613,23 @@ int32_t videoSetVolume(int32_t playerHandle, int32_t leftPercent, int32_t rightP int32_t videoUnload(int32_t playerHandle) { VideoPlayerT *v = NULL; + int32_t x = 0; // Get our player structure HASH_FIND_INT(_videoPlayerHash, &playerHandle, v); if (!v) utilDie("No video player at index %d in videoStop.", playerHandle); - if (v->audioSource) { + if (v->audioSourceCount > 0) { Mix_HaltChannel(v->audioSilenceChannel); Mix_UnregisterEffect(v->audioSilenceChannel, _dequeueVideoAudio); Mix_FreeChunk(v->silenceChunk); free(v->audioSilenceRaw); SDL_FreeAudioStream(v->audioStream); free(v->audioBuffer); - FFMS_DestroyAudioSource(v->audioSource); + for (x=0; xaudioSourceCount; x++) { + FFMS_DestroyAudioSource(v->audio[x].audioSource); + } + free(v->audio); } FFMS_DestroyVideoSource(v->videoSource); @@ -566,7 +656,7 @@ int32_t videoUpdate(int32_t playerHandle, SDL_Texture **texture) { if (!v) utilDie("No video player at index %d in videoUpdate.", playerHandle); // Audio drift limit - threshold = v->audioSource ? (v->audioProps->SampleRate / 2) : 99999; + threshold = v->audio[v->currentAudioTrack].audioSource ? (v->audio[v->currentAudioTrack].audioProps->SampleRate / 2) : 99999; // Handle video frames (and time) //if ((SDL_GetTicks() - v->lastTickTime >= v->frameDeltaTime) || (v->audioDelta > threshold) || v->resetTime) { @@ -598,9 +688,9 @@ int32_t videoUpdate(int32_t playerHandle, SDL_Texture **texture) { v->lastTickTime = SDL_GetTicks(); if (v->resetTime) { - if (v->audioSource) { + if (v->audioSourceCount > 0) { SDL_AudioStreamClear(v->audioStream); - v->audioPosition = (int64_t)((double)v->timestamp * 0.001 * (double)v->audioProps->SampleRate); + v->audioPosition = (int64_t)((double)v->timestamp * 0.001 * (double)v->audio[v->currentAudioTrack].audioProps->SampleRate); v->audioDelta = 0; } v->lastTickTime = 0; @@ -611,19 +701,19 @@ int32_t videoUpdate(int32_t playerHandle, SDL_Texture **texture) { } // Handle audio samples - if (v->audioSource) { + if (v->audioSourceCount > 0) { // Add more samples to queue? - if ((v->playing) && (SDL_AudioStreamAvailable(v->audioStream) < AUDIO_STREAM_LOW_WATERMARK) && (v->audioPosition < v->audioProps->NumSamples)) { + if ((v->playing) && (SDL_AudioStreamAvailable(v->audioStream) < AUDIO_STREAM_LOW_WATERMARK) && (v->audioPosition < v->audio[v->currentAudioTrack].audioProps->NumSamples)) { // Maximum samples we can read at a time count = AUDIO_SAMPLE_PREREAD; // Don't read past end of audio data - if (v->audioPosition + count >= v->audioProps->NumSamples) { - count = v->audioProps->NumSamples - v->audioPosition - 1; + if (v->audioPosition + count >= v->audio[v->currentAudioTrack].audioProps->NumSamples) { + count = v->audio[v->currentAudioTrack].audioProps->NumSamples - v->audioPosition - 1; } // Are we reading anything? if (count > 0) { // Get audio from video stream - if (FFMS_GetAudio(v->audioSource, v->audioBuffer, v->audioPosition, count, &v->errInfo)) utilDie("%s", v->errInfo.Buffer); + if (FFMS_GetAudio(v->audio[v->currentAudioTrack].audioSource, v->audioBuffer, v->audioPosition, count, &v->errInfo)) utilDie("%s", v->errInfo.Buffer); // Feed it to the mixer stream if (SDL_AudioStreamPut(v->audioStream, v->audioBuffer, (int32_t)(count * v->audioSampleSize)) < 0) utilDie("%s", SDL_GetError()); v->audioPosition += count; @@ -631,7 +721,7 @@ int32_t videoUpdate(int32_t playerHandle, SDL_Texture **texture) { } // Used to determine if we should play two frames rapidly to catch up to audio - v->audioDelta = labs((long)(v->audioPosition - (int64_t)((double)v->timestamp * 0.001 * (double)v->audioProps->SampleRate))); + v->audioDelta = labs((long)(v->audioPosition - (int64_t)((double)v->timestamp * 0.001 * (double)v->audio[v->currentAudioTrack].audioProps->SampleRate))); // Did we trip the audio sync compensation? if (v->audioDelta > threshold) { diff --git a/src/videoPlayer.h b/src/videoPlayer.h index 7f61f3877..d6f17d6ce 100644 --- a/src/videoPlayer.h +++ b/src/videoPlayer.h @@ -34,6 +34,8 @@ typedef void (*videoIndexingCallback)(int32_t); int32_t videoInit(void); int32_t videoIsPlaying(int32_t playerHandle); +int32_t videoGetAudioTrack(int32_t playerHandle); +int32_t videoGetAudioTracks(int32_t playerHandle); int64_t videoGetFrame(int32_t playerHandle); int64_t videoGetFrameCount(int32_t playerHandle); int32_t videoGetHeight(int32_t playerHandle); @@ -45,6 +47,7 @@ int32_t videoPause(int32_t playerHandle); int32_t videoPlay(int32_t playerHandle); int32_t videoQuit(void); int32_t videoSeek(int32_t playerHandle, int64_t seekFrame); +int32_t videoSetAudioTrack(int32_t playerHandle, int32_t track); int32_t videoSetIndexCallback(videoIndexingCallback callback); int32_t videoSetVolume(int32_t playerHandle, int32_t leftPercent, int32_t rightPercent); int32_t videoUnload(int32_t playerHandle);