Multiple audio tracks now supported.
This commit is contained in:
parent
191001e3a6
commit
b0a66bf4a4
4 changed files with 353 additions and 77 deletions
|
@ -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
|
||||
|
|
195
src/singe.c
195
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;
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue