Language codes are now available for audio tracks to determine which is which.

This commit is contained in:
Scott Duensing 2023-12-04 19:57:04 -06:00
parent e1a11f49d4
commit 8d5de6db89
3 changed files with 133 additions and 52 deletions

View file

@ -322,6 +322,7 @@ int32_t apiDiscGetAudioTrack(lua_State *L);
int32_t apiDiscGetAudioTracks(lua_State *L); int32_t apiDiscGetAudioTracks(lua_State *L);
int32_t apiDiscGetFrame(lua_State *L); int32_t apiDiscGetFrame(lua_State *L);
int32_t apiDiscGetHeight(lua_State *L); int32_t apiDiscGetHeight(lua_State *L);
int32_t apiDiscGetLanguage(lua_State *L);
int32_t apiDiscGetState(lua_State *L); int32_t apiDiscGetState(lua_State *L);
int32_t apiDiscGetWidth(lua_State *L); int32_t apiDiscGetWidth(lua_State *L);
int32_t apiDiscPause(lua_State *L); int32_t apiDiscPause(lua_State *L);
@ -417,6 +418,7 @@ int32_t apiVideoGetAudioTracks(lua_State *L);
int32_t apiVideoGetFrame(lua_State *L); int32_t apiVideoGetFrame(lua_State *L);
int32_t apiVideoGetFrameCount(lua_State *L); int32_t apiVideoGetFrameCount(lua_State *L);
int32_t apiVideoGetHeight(lua_State *L); int32_t apiVideoGetHeight(lua_State *L);
int32_t apiVideoGetLanguage(lua_State *L);
int32_t apiVideoGetVolume(lua_State *L); int32_t apiVideoGetVolume(lua_State *L);
int32_t apiVideoGetWidth(lua_State *L); int32_t apiVideoGetWidth(lua_State *L);
int32_t apiVideoIsPlaying(lua_State *L); int32_t apiVideoIsPlaying(lua_State *L);
@ -713,6 +715,33 @@ int32_t apiDiscGetFrame(lua_State *L) {
} }
int32_t apiDiscGetLanguage(lua_State *L) {
int32_t n = lua_gettop(L);
bool result = false;
char *r = NULL;
int32_t track = -1;
double d;
VideoT *video = NULL;
if (n == 1) {
if (lua_isnumber(L, 1)) {
d = lua_tonumber(L, 1); track = (int32_t)d;
r = videoGetLanguage(_global.videoHandle, track);
result = true;
}
}
if (result) {
luaTrace(L, "discGetLanguage", "%d %s", track, r);
} else {
luaDie(L, "discGetLanguage", "Failed!");
}
lua_pushstring(L, r);
return 1;
}
int32_t apiDiscPause(lua_State *L) { int32_t apiDiscPause(lua_State *L) {
(void)L; (void)L;
if (!_global.discStopped) { if (!_global.discStopped) {
@ -2733,6 +2762,40 @@ int32_t apiVideoGetFrameCount(lua_State *L) {
} }
int32_t apiVideoGetLanguage(lua_State *L) {
int32_t n = lua_gettop(L);
bool result = false;
char *r = NULL;
int32_t id = -1;
int32_t track = -1;
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, "videoGetLanguage", "No video at index %d in apiVideoGetLanguage.", id);
r = videoGetLanguage(video->handle, track);
result = true;
}
}
}
if (result) {
luaTrace(L, "videoGetLanguage", "%d %d %s", id, track, r);
} else {
luaDie(L, "videoGetLanguage", "Failed!");
}
lua_pushstring(L, r);
return 1;
}
int32_t apiVideoGetHeight(lua_State *L) { int32_t apiVideoGetHeight(lua_State *L) {
int32_t n = lua_gettop(L); int32_t n = lua_gettop(L);
bool result = false; bool result = false;
@ -4559,6 +4622,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) {
lua_register(_global.luaContext, "discGetAudioTracks", apiDiscGetAudioTracks); lua_register(_global.luaContext, "discGetAudioTracks", apiDiscGetAudioTracks);
lua_register(_global.luaContext, "discGetFrame", apiDiscGetFrame); lua_register(_global.luaContext, "discGetFrame", apiDiscGetFrame);
lua_register(_global.luaContext, "discGetHeight", apiDiscGetHeight); lua_register(_global.luaContext, "discGetHeight", apiDiscGetHeight);
lua_register(_global.luaContext, "discGetLanguage", apiDiscGetLanguage);
lua_register(_global.luaContext, "discGetState", apiDiscGetState); lua_register(_global.luaContext, "discGetState", apiDiscGetState);
lua_register(_global.luaContext, "discGetWidth", apiDiscGetWidth); lua_register(_global.luaContext, "discGetWidth", apiDiscGetWidth);
lua_register(_global.luaContext, "discPause", apiDiscPause); lua_register(_global.luaContext, "discPause", apiDiscPause);
@ -4654,6 +4718,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) {
lua_register(_global.luaContext, "videoGetFrame", apiVideoGetFrame); lua_register(_global.luaContext, "videoGetFrame", apiVideoGetFrame);
lua_register(_global.luaContext, "videoGetFrameCount", apiVideoGetFrameCount); lua_register(_global.luaContext, "videoGetFrameCount", apiVideoGetFrameCount);
lua_register(_global.luaContext, "videoGetHeight", apiVideoGetHeight); lua_register(_global.luaContext, "videoGetHeight", apiVideoGetHeight);
lua_register(_global.luaContext, "videoGetLanguage", apiVideoGetLanguage);
lua_register(_global.luaContext, "videoGetVolume", apiVideoGetVolume); lua_register(_global.luaContext, "videoGetVolume", apiVideoGetVolume);
lua_register(_global.luaContext, "videoGetWidth", apiVideoGetWidth); lua_register(_global.luaContext, "videoGetWidth", apiVideoGetWidth);
lua_register(_global.luaContext, "videoIsPlaying", apiVideoIsPlaying); lua_register(_global.luaContext, "videoIsPlaying", apiVideoIsPlaying);

View file

@ -36,6 +36,7 @@
typedef struct AudioStreamS { typedef struct AudioStreamS {
FFMS_AudioSource *audioSource; FFMS_AudioSource *audioSource;
const FFMS_AudioProperties *audioProps; const FFMS_AudioProperties *audioProps;
char *language;
} AudioStreamT; } AudioStreamT;
#pragma GCC diagnostic push #pragma GCC diagnostic push
@ -194,17 +195,21 @@ FFMS_Index *_createIndex(char *filename, char *indexPath, bool hasVideo, bool ha
return index; return index;
} }
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer) { int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer) {
int32_t pixelFormats[2]; int32_t pixelFormats[2];
int32_t result = -1; int32_t result = -1;
FFMS_Index *vIndex = NULL; FFMS_Index *vIndex = NULL;
FFMS_Index *aIndex = NULL; FFMS_Index *aIndex = NULL;
VideoPlayerT *v = NULL; VideoPlayerT *v = NULL;
int32_t x = 0; int32_t x = 0;
int32_t count = 0; int32_t count = 0;
FFMS_Track *track = NULL; FFMS_Track *track = NULL;
int32_t ttype = FFMS_TYPE_UNKNOWN; int32_t ttype = FFMS_TYPE_UNKNOWN;
AVFormatContext *fmt_ctx = NULL;
AVDictionaryEntry *tag = NULL;
// Create new videoPlayer // Create new videoPlayer
v = calloc(1, sizeof(VideoPlayerT)); v = calloc(1, sizeof(VideoPlayerT));
@ -248,34 +253,11 @@ int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bo
if (FFMS_SetOutputFormatV2(v->videoSource, pixelFormats, v->propFrame->EncodedWidth, v->propFrame->EncodedHeight, FFMS_RESIZER_BICUBIC, &v->errInfo)) utilDie("%s", v->errInfo.Buffer); 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(s) // Find audio track(s)
//utilSay("Tracks in file: %d", FFMS_GetNumTracks(aIndex));
for (x=0; x<FFMS_GetNumTracks(aIndex); x++) { for (x=0; x<FFMS_GetNumTracks(aIndex); x++) {
track = FFMS_GetTrackFromIndex(aIndex, x); track = FFMS_GetTrackFromIndex(aIndex, x);
ttype = FFMS_GetTrackType(track); ttype = FFMS_GetTrackType(track);
// Just count the tracks for now. // Just count the tracks for now.
if (ttype == FFMS_TYPE_AUDIO) count++; 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) { if (count > 0) {
// Allocate space for the tracks. // Allocate space for the tracks.
@ -289,6 +271,20 @@ int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bo
v->audioSourceCount++; v->audioSourceCount++;
} }
} }
// Use ffmpeg directly to figure out language IDs for audio tracks
if (avformat_open_input(&fmt_ctx, aFilename, NULL, NULL) >= 0) {
count = 0;
for (x=0; x<fmt_ctx->nb_streams; x++) {
if (fmt_ctx->streams[x]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
while ((tag = (AVDictionaryEntry *)av_dict_iterate(fmt_ctx->streams[x]->metadata, tag))) {
if (utilStricmp("language", tag->key) == 0) {
v->audio[count++].language = strdup(tag->value);
}
}
}
}
avformat_close_input(&fmt_ctx);
}
// Current audio track. // Current audio track.
v->currentAudioTrack = 0; v->currentAudioTrack = 0;
} }
@ -463,6 +459,24 @@ int64_t videoGetFrameCount(int32_t playerHandle) {
} }
char *videoGetLanguage(int32_t playerHandle, int32_t audioTrack) {
VideoPlayerT *v = NULL;
char *r = NULL;
// Get our player structure
HASH_FIND_INT(_videoPlayerHash, &playerHandle, v);
if (!v) utilDie("No video player at index %d in videoGetHeight.", playerHandle);
if ((audioTrack >= 0) && (audioTrack < v->audioSourceCount)) {
r = v->audio[audioTrack].language;
} else {
utilDie("Invalid audio track in videoSetAudioTrack.");
}
return r;
}
int32_t videoGetHeight(int32_t playerHandle) { int32_t videoGetHeight(int32_t playerHandle) {
VideoPlayerT *v = NULL; VideoPlayerT *v = NULL;
@ -627,6 +641,7 @@ int32_t videoUnload(int32_t playerHandle) {
SDL_FreeAudioStream(v->audioStream); SDL_FreeAudioStream(v->audioStream);
free(v->audioBuffer); free(v->audioBuffer);
for (x=0; x<v->audioSourceCount; x++) { for (x=0; x<v->audioSourceCount; x++) {
if (v->audio[x].language) free(v->audio[x].language);
FFMS_DestroyAudioSource(v->audio[x].audioSource); FFMS_DestroyAudioSource(v->audio[x].audioSource);
} }
free(v->audio); free(v->audio);

View file

@ -32,26 +32,27 @@
typedef void (*videoIndexingCallback)(int32_t); typedef void (*videoIndexingCallback)(int32_t);
int32_t videoInit(void); int32_t videoInit(void);
int32_t videoIsPlaying(int32_t playerHandle); int32_t videoIsPlaying(int32_t playerHandle);
int32_t videoGetAudioTrack(int32_t playerHandle); int32_t videoGetAudioTrack(int32_t playerHandle);
int32_t videoGetAudioTracks(int32_t playerHandle); int32_t videoGetAudioTracks(int32_t playerHandle);
int64_t videoGetFrame(int32_t playerHandle); int64_t videoGetFrame(int32_t playerHandle);
int64_t videoGetFrameCount(int32_t playerHandle); int64_t videoGetFrameCount(int32_t playerHandle);
int32_t videoGetHeight(int32_t playerHandle); int32_t videoGetHeight(int32_t playerHandle);
int32_t videoGetWidth(int32_t playerHandle); char *videoGetLanguage(int32_t playerHandle, int32_t audioTrack);
int32_t videoGetVolume(int32_t playerHandle, int32_t *leftPercent, int32_t *rightPercent); int32_t videoGetWidth(int32_t playerHandle);
int32_t videoLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer); int32_t videoGetVolume(int32_t playerHandle, int32_t *leftPercent, int32_t *rightPercent);
int32_t videoLoadWithAudio(char *vFilename, char *aFilename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer); int32_t videoLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer);
int32_t videoPause(int32_t playerHandle); int32_t videoLoadWithAudio(char *vFilename, char *aFilename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer);
int32_t videoPlay(int32_t playerHandle); int32_t videoPause(int32_t playerHandle);
int32_t videoQuit(void); int32_t videoPlay(int32_t playerHandle);
int32_t videoSeek(int32_t playerHandle, int64_t seekFrame); int32_t videoQuit(void);
int32_t videoSetAudioTrack(int32_t playerHandle, int32_t track); int32_t videoSeek(int32_t playerHandle, int64_t seekFrame);
int32_t videoSetIndexCallback(videoIndexingCallback callback); int32_t videoSetAudioTrack(int32_t playerHandle, int32_t track);
int32_t videoSetVolume(int32_t playerHandle, int32_t leftPercent, int32_t rightPercent); int32_t videoSetIndexCallback(videoIndexingCallback callback);
int32_t videoUnload(int32_t playerHandle); int32_t videoSetVolume(int32_t playerHandle, int32_t leftPercent, int32_t rightPercent);
int32_t videoUpdate(int32_t playerHandle, SDL_Texture **texture); int32_t videoUnload(int32_t playerHandle);
int32_t videoUpdate(int32_t playerHandle, SDL_Texture **texture);
#endif // VIDEOPLAYER_H #endif // VIDEOPLAYER_H