diff --git a/src/singe.c b/src/singe.c index 2b5eeb0be..e736e4cc8 100644 --- a/src/singe.c +++ b/src/singe.c @@ -322,6 +322,7 @@ 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 apiDiscGetLanguage(lua_State *L); int32_t apiDiscGetState(lua_State *L); int32_t apiDiscGetWidth(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 apiVideoGetFrameCount(lua_State *L); int32_t apiVideoGetHeight(lua_State *L); +int32_t apiVideoGetLanguage(lua_State *L); int32_t apiVideoGetVolume(lua_State *L); int32_t apiVideoGetWidth(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) { (void)L; 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 n = lua_gettop(L); 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, "discGetFrame", apiDiscGetFrame); lua_register(_global.luaContext, "discGetHeight", apiDiscGetHeight); + lua_register(_global.luaContext, "discGetLanguage", apiDiscGetLanguage); lua_register(_global.luaContext, "discGetState", apiDiscGetState); lua_register(_global.luaContext, "discGetWidth", apiDiscGetWidth); 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, "videoGetFrameCount", apiVideoGetFrameCount); lua_register(_global.luaContext, "videoGetHeight", apiVideoGetHeight); + lua_register(_global.luaContext, "videoGetLanguage", apiVideoGetLanguage); lua_register(_global.luaContext, "videoGetVolume", apiVideoGetVolume); lua_register(_global.luaContext, "videoGetWidth", apiVideoGetWidth); lua_register(_global.luaContext, "videoIsPlaying", apiVideoIsPlaying); diff --git a/src/videoPlayer.c b/src/videoPlayer.c index 666080f4d..f1dbed8e7 100644 --- a/src/videoPlayer.c +++ b/src/videoPlayer.c @@ -36,6 +36,7 @@ typedef struct AudioStreamS { FFMS_AudioSource *audioSource; const FFMS_AudioProperties *audioProps; + char *language; } AudioStreamT; #pragma GCC diagnostic push @@ -194,17 +195,21 @@ FFMS_Index *_createIndex(char *filename, char *indexPath, bool hasVideo, bool ha return index; } +#include +#include int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer) { - int32_t pixelFormats[2]; - int32_t result = -1; - 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; + int32_t pixelFormats[2]; + int32_t result = -1; + 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; + AVFormatContext *fmt_ctx = NULL; + AVDictionaryEntry *tag = NULL; // Create new videoPlayer 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); // Find audio track(s) - //utilSay("Tracks in file: %d", FFMS_GetNumTracks(aIndex)); for (x=0; x 0) { // Allocate space for the tracks. @@ -289,6 +271,20 @@ int32_t _loadVideoAndAudio(char *vFilename, char *aFilename, char *indexPath, bo 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; xnb_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. 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) { VideoPlayerT *v = NULL; @@ -627,6 +641,7 @@ int32_t videoUnload(int32_t playerHandle) { SDL_FreeAudioStream(v->audioStream); free(v->audioBuffer); for (x=0; xaudioSourceCount; x++) { + if (v->audio[x].language) free(v->audio[x].language); FFMS_DestroyAudioSource(v->audio[x].audioSource); } free(v->audio); diff --git a/src/videoPlayer.h b/src/videoPlayer.h index d6f17d6ce..6ccbecabc 100644 --- a/src/videoPlayer.h +++ b/src/videoPlayer.h @@ -32,26 +32,27 @@ 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); -int32_t videoGetWidth(int32_t playerHandle); -int32_t videoGetVolume(int32_t playerHandle, int32_t *leftPercent, int32_t *rightPercent); -int32_t videoLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer); -int32_t videoLoadWithAudio(char *vFilename, char *aFilename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer); -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); -int32_t videoUpdate(int32_t playerHandle, SDL_Texture **texture); +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); +char *videoGetLanguage(int32_t playerHandle, int32_t audioTrack); +int32_t videoGetWidth(int32_t playerHandle); +int32_t videoGetVolume(int32_t playerHandle, int32_t *leftPercent, int32_t *rightPercent); +int32_t videoLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer); +int32_t videoLoadWithAudio(char *vFilename, char *aFilename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer); +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); +int32_t videoUpdate(int32_t playerHandle, SDL_Texture **texture); #endif // VIDEOPLAYER_H