Multiple audio tracks now supported.

This commit is contained in:
Scott Duensing 2023-11-30 20:48:13 -06:00
parent 191001e3a6
commit b0a66bf4a4
4 changed files with 353 additions and 77 deletions

View file

@ -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

View file

@ -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;
@ -2568,6 +2711,42 @@ int32_t apiVideoSeek(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;
@ -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) {

View file

@ -33,6 +33,11 @@
#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 {
@ -45,7 +50,6 @@ typedef struct VideoPlayerS {
char errMsg[1024];
int32_t volumeLeft;
int32_t volumeRight;
int32_t audioTrack;
int32_t videoTrack;
int32_t audioSampleSize;
int32_t mixSampleSize;
@ -66,9 +70,10 @@ typedef struct VideoPlayerS {
SDL_AudioStream *audioStream;
SDL_Texture *videoTexture;
FFMS_ErrorInfo errInfo;
FFMS_AudioSource *audioSource;
int32_t currentAudioTrack;
int32_t audioSourceCount;
AudioStreamT *audio;
FFMS_VideoSource *videoSource;
const FFMS_AudioProperties *audioProps;
const FFMS_VideoProperties *videoProps;
const FFMS_Frame *propFrame;
const FFMS_TrackTimeBase *videoTimeBase;
@ -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
@ -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<FFMS_GetNumTracks(aIndex); x++) {
track = FFMS_GetTrackFromIndex(aIndex, x);
ttype = FFMS_GetTrackType(track);
// Just count the tracks for now.
if (ttype == FFMS_TYPE_AUDIO) count++;
/*
switch (ttype) {
case FFMS_TYPE_UNKNOWN:
utilSay("Track %d is FFMS_TYPE_UNKNOWN", x);
break;
case FFMS_TYPE_VIDEO:
utilSay("Track %d is FFMS_TYPE_VIDEO", x);
break;
case FFMS_TYPE_AUDIO:
utilSay("Track %d is FFMS_TYPE_AUDIO", x);
break;
case FFMS_TYPE_DATA:
utilSay("Track %d is FFMS_TYPE_DATA", x);
break;
case FFMS_TYPE_SUBTITLE:
utilSay("Track %d is FFMS_TYPE_SUBTITLE", x);
break;
case FFMS_TYPE_ATTACHMENT:
utilSay("Track %d is FFMS_TYPE_ATTACHMENT", x);
break;
}
*/
}
if (count > 0) {
// Allocate space for the tracks.
v->audio = (AudioStreamT *)calloc(count, sizeof(AudioStreamT));
// Now create them.
for (x=0; x<FFMS_GetNumTracks(aIndex); x++) {
if (FFMS_GetTrackType(FFMS_GetTrackFromIndex(aIndex, x)) == FFMS_TYPE_AUDIO) {
v->audio[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; x<v->audioSourceCount; 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) {

View file

@ -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);