Skip to content

Commit

Permalink
SRT Subtitle Support
Browse files Browse the repository at this point in the history
  • Loading branch information
SonicMastr committed Apr 9, 2021
1 parent 3db57d5 commit 84a3f56
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 33 deletions.
26 changes: 2 additions & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,50 +62,28 @@ add_executable(${PROJECT_NAME}
src/commonValues.c
src/menus/menuMain.c
src/menus/menuInfo.c
src/avplayer/avsubs.c
src/avplayer/avplayer.c
src/avplayer/avsound.c
src/avplayer/avplayerUtils.c
src/avplayer/overlay.c
)

target_link_libraries(${PROJECT_NAME}
vita2d_sys
vita2d_sys_stub
SceKernel_stub
SceAppMgr_stub
SceAvcodec_stub
SceVideodec_stub
SceAppUtil_stub
SceAvPlayer_stub
SceAudio_stub
SceCtrl_stub
ScePng
SceDeflt
SceSysmem_stub
SceDisplay_stub
SceDisplayUser_stub
SceSysmodule_stub
SceIofilemgr_stub
SceAppMgrUser_stub
SceShellSvc_stub
SceGxm_stub
SceGxmInternal_stub
SceGxmInternalForVsh_stub
SceGxmInternalForTest_stub
SceGpuEs4User_stub
SceGpuEs4UserForVsh_stub
SceCommonDialog_stub
SceDbg_stub
SceFios2_stub
SceJpegUser_stub
SceJpegArm_stub
ScePgf_stub
ScePvf_stub
SceRtabi_stub
SceSharedFb_stub
SceThreadmgr_stub
SceModulemgr_stub
SceProcessmgr_stub
SceDmacmgr_stub
)

VDSuiteCreateSfo(vmp-param.sfo param.yml)
Expand Down
Binary file added modules/libvita2d_sys.suprx
Binary file not shown.
38 changes: 31 additions & 7 deletions src/avplayer/avplayer.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "avplayer.h"
#include "avsound.h"
#include "avsubs.h"
#include "common.h"
#include "texture.h"
#include "overlay.h"
Expand Down Expand Up @@ -30,6 +31,8 @@ SceUID timerUid;
SceKernelSysClock timerBaseClock;
SceKernelSysClock *timerCurrentClock = NULL;
SceUID callback;
static SceBool subReset = 0;
uint64_t playerTime = 0;

SceBool ran;

Expand Down Expand Up @@ -69,10 +72,12 @@ static void handleAVPlayerControls()
else
jumpTime -= jumpToTimeOffset;
sceAvPlayerJumpToTime(player, jumpTime);
subReset = 1;
}
if (pressed & SCE_CTRL_RIGHT) {
int64_t jumpTime = sceAvPlayerCurrentTime(player);
sceAvPlayerJumpToTime(player, jumpTime+jumpToTimeOffset);
subReset = 1;
}
}

Expand Down Expand Up @@ -128,13 +133,15 @@ void eventCallback(void* jumpback, int32_t argEventId, int32_t argSourceId, void
break;
case SCE_AVPLAYER_TIMED_TEXT_DELIVERY:
{
memset(subs, '\0', 2048);
SceAvPlayerFrameInfo* pTextEventData = (SceAvPlayerFrameInfo*)argEventData;
uint16_t size = pTextEventData->details.subs.textSize;
if ((char*)pTextEventData->pData) {
strncpy(subs, (char*)pTextEventData->pData, size);
if (subType == SUBTITLES_TIMED_TEXT) {
memset(subs, '\0', 2048);
SceAvPlayerFrameInfo* pTextEventData = (SceAvPlayerFrameInfo*)argEventData;
uint16_t size = pTextEventData->details.subs.textSize;
if ((char*)pTextEventData->pData) {
strncpy(subs, (char*)pTextEventData->pData, size);
}
printf("##Text to display: %s\n", subs);
}
printf("##Text to display: %s\n", subs);
}
break;
case SCE_AVPLAYER_STATE_PLAY:
Expand Down Expand Up @@ -199,10 +206,10 @@ static SceInt32 loadAVPlayerThread()
playerInit.debugLevel = 3;

player = sceAvPlayerInit(&playerInit);
printf("File Name: %s", file);
if (R_FAILED(sceAvPlayerAddSource(player, file))) {
playerStatus = PLAYER_ERROR;
}
subStatus = SUBTITLES_NONE;
return sceKernelExitThread(0);
}

Expand Down Expand Up @@ -239,6 +246,14 @@ static SceInt32 timerThread()

static int drawSubtitles()
{
if (subType == SUBTITLES_SRT) {
char *curSubs;
memset(subs, '\0', 2048);
curSubs = avGetSrt(&subReset);
if (curSubs)
strncpy(subs, curSubs, strlen(curSubs));
printf("##Text to display: %s\n", subs);
}
if (subs[0] != '\0') {
int fontSize = 1;
float linespace = FRAMEBUF_HEIGHT/200.0f;
Expand Down Expand Up @@ -282,8 +297,15 @@ static int drawLoading()

int startPlayback(char *filename)
{
subStatus = SUBTITLES_NONE;
SceUID main_thread_uid = sceKernelGetThreadId();
sceKernelChangeThreadPriority(main_thread_uid, 70);
if(!avOpenSrt(filename)) {
subStatus = SUBTITLES_ENABLED;
subType = SUBTITLES_SRT;
}
else
subType = SUBTITLES_TIMED_TEXT;
file = filename;
rad = 0.0f;
playerStatus = PLAYER_LOADING;
Expand Down Expand Up @@ -313,6 +335,7 @@ int startPlayback(char *filename)
SceAvPlayerFrameInfo videoFrame;
memset(&videoFrame, 0, sizeof(SceAvPlayerFrameInfo));
while (sceAvPlayerIsActive(player)) {
playerTime = sceAvPlayerCurrentTime(player);
sceDisplayWaitVblankStart();
vita2d_start_drawing();
vita2d_clear_screen();
Expand All @@ -332,6 +355,7 @@ int startPlayback(char *filename)
}
sceAvPlayerClose(player);
printf("Freeing?\n\n");
avFreeSrt();
if (frameTexture != NULL)
free(frameTexture);
sceKernelDeleteEventFlag(eventUid);
Expand Down
147 changes: 147 additions & 0 deletions src/avplayer/avsubs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/** Welcome to hell **/
#include "avplayer.h"
#include "common.h"
#include "avsubs.h"
#include "fs.h"

FILE *srtFile = NULL;

uint64_t endTime, startTime = 0;

SrtStructure_t *srtSubtitlesHead, *srtSubtitlesCurrent = NULL;

char *srtDelim = " --> "; // Most if not all SRT should have this for time
char *srtTimeFormat = "%d:%d:%d,%d"; // SRT Time format

char srtText[2048] = {'\0'}; // Actual Text Data

static uint64_t avGetMilliseconds(char *time)
{
int hours, mins, seconds, milliseconds;

sscanf(time, srtTimeFormat, &hours, &mins, &seconds, &milliseconds);

printf("Hours %d\nMins %d\nSecs %d\nMilliseconds %d\n", hours, mins, seconds, milliseconds);

return hours * 3600000 + mins * 60000 + seconds * 1000 + milliseconds;
}

static char *avCleanSrtDialog(char *dialog)
{
char *tempChar = strstr(dialog, "</");
char *out;
if (tempChar) { // Found XML data
strncpy(tempChar, dialog, strlen(dialog) - strlen(tempChar));
if (strstr(tempChar, "an8}")) {
out = (strrchr(tempChar, '}') + 1); // Find the last tag
} else {
out = (strrchr(tempChar, '>') + 1); // Find the last tag
}
}
else
strncpy(out, dialog, strlen(dialog));
if (strchr(out, '\r')) {
int len = strlen(out) + 1;
for(int i = 0; i<len ; i++)
{
if(out[i] == '\r')
strncpy(&out[i] ,&out[i + 1], len - i);
}
}
return out;
}

static SceVoid avParseSrt()
{
if (srtFile) {
srtSubtitlesHead = (SrtStructure_t *)malloc(sizeof(SrtStructure_t));
srtSubtitlesCurrent = srtSubtitlesHead;
int curIndex = 0;
char buf[1024]; // line buffer
while(fgets(buf, 1024, srtFile)) { // New line
srtSubtitlesCurrent->next = NULL;
char *timeLine = strstr(buf, srtDelim); // Check to see if current line contains timestamp data
if (timeLine) {
char *start = strtok(buf, srtDelim);
printf("Start Text: %s\n", start);
char *end = strtok(NULL, srtDelim);
printf("End Text: %s\n", end);

srtSubtitlesCurrent->startTime = avGetMilliseconds(start);
srtSubtitlesCurrent->endTime = avGetMilliseconds(end);

printf("Start Time %llu\nEnd Time %llu\nStart Text: %s\nEnd Text: %s\n", srtSubtitlesCurrent->startTime, srtSubtitlesCurrent->endTime, start, end);

memset(srtText, '\0', sizeof(srtText));
while (fgets(buf, 1024, srtFile)) {
if (strlen(buf) == 1)
break;
strcat(srtText, buf);
}
char *tempText = avCleanSrtDialog(srtText);
strncpy(srtSubtitlesCurrent->dialog, tempText, strlen(tempText));
srtSubtitlesCurrent->index = curIndex;
srtSubtitlesCurrent->next = (SrtStructure_t *)malloc(sizeof(SrtStructure_t));
srtSubtitlesCurrent = srtSubtitlesCurrent->next;
curIndex++;
}
}
srtSubtitlesCurrent = srtSubtitlesHead;
}
}

SceInt avOpenSrt(const char *filename)
{
int len = strlen(filename);
const char *extension = &filename[len-4];
if (!strncasecmp(extension, ".mp4", 4)) {
char srtPath[1024];
memset(srtPath, '\0', 1024);
strncpy(srtPath, filename, len-4);
strncat(srtPath, ".srt", 4);
printf("Finding File %s\n\n", srtPath);
srtFile = fopen(srtPath, "rb");
if (srtFile) {
avParseSrt();
printf("FOUND\n\n", srtPath);
fclose(srtFile);
return SCE_OK;
}
}
return -1;
}

char *avGetSrt(SceBool *reset)
{
if (srtSubtitlesHead) {
if (*reset) { // Fast Forward and Rewind needs to keep track of this
srtSubtitlesCurrent = srtSubtitlesHead;
*reset = 0;
}
if (playerTime > srtSubtitlesCurrent->endTime) {
while (srtSubtitlesCurrent->next) {
srtSubtitlesCurrent = srtSubtitlesCurrent->next;
if (srtSubtitlesCurrent->endTime && playerTime < srtSubtitlesCurrent->endTime) {
if (playerTime < srtSubtitlesCurrent->startTime) // If we don't put this here, everything will flip
return '\0';
return srtSubtitlesCurrent->dialog;
}
}
srtSubtitlesCurrent = srtSubtitlesHead;
}
if (playerTime < srtSubtitlesCurrent->startTime) // If we don't put this here, everything will flip
return '\0';
return srtSubtitlesCurrent->dialog;
}
return '\0';
}

void *avFreeSrt()
{
while (srtSubtitlesHead != NULL)
{
srtSubtitlesCurrent = srtSubtitlesHead;
srtSubtitlesHead = srtSubtitlesHead->next;
free(srtSubtitlesCurrent);
}
}
4 changes: 2 additions & 2 deletions src/commonValues.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ vita2d_pvf *subtitleFont;
SceUInt32 SCE_CTRL_ENTER;
SceUInt32 SCE_CTRL_CANCEL;
SceUInt32 pressed = 0;
void *mspaceGlobal;
vita2d_pgf *pgf;
int position = 0;
int file_count = 0;
Expand All @@ -14,4 +13,5 @@ PlayerInitStatus playerStatus;
PlayerState playerState;
ThumbnailStatus thumbnailStatus;
uint64_t streamDuration = 0;
SubtitlesStatus subStatus;
SubtitlesStatus subStatus;
SubtitlesType subType;
2 changes: 2 additions & 0 deletions src/include/avplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ int avPlayerInit(void);
int avPlayerTerm(void);
int startPlayback(char *filename);

extern uint64_t playerTime;

#endif
16 changes: 16 additions & 0 deletions src/include/avsubs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef AVSUBS_H
#define AVSUBS_H

typedef struct SrtStructure {
int index;
uint64_t startTime;
uint64_t endTime;
char dialog[1024];
struct SrtStructure *next;
} SrtStructure_t;

SceInt avOpenSrt(const char *filename);
char *avGetSrt(SceBool *reset);
void *avFreeSrt(void);

#endif
6 changes: 6 additions & 0 deletions src/include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ typedef enum SubtitlesStatus {
SUBTITLES_NONE
} SubtitlesStatus;

typedef enum SubtitlesType {
SUBTITLES_TIMED_TEXT,
SUBTITLES_SRT
} SubtitlesType;

extern vita2d_pvf *subtitleFont;
extern SceUInt32 SCE_CTRL_ENTER;
extern SceUInt32 SCE_CTRL_CANCEL;
Expand All @@ -69,5 +74,6 @@ extern PlayerState playerState;
extern ThumbnailStatus thumbnailStatus;
extern uint64_t streamDuration;
extern SubtitlesStatus subStatus;
extern SubtitlesType subType;

#endif
1 change: 1 addition & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ int initVita2d()
int main()
{
sceIoMkdir("ux0:data/SubPlayer", 0777);
sceKernelLoadStartModule("app0:modules/libvita2d_sys.suprx", 0, SCE_NULL, 0, SCE_NULL, SCE_NULL);
vita2d_display_set_max_resolution(FRAMEBUF_WIDTH, FRAMEBUF_HEIGHT);
vita2d_display_set_resolution(FRAMEBUF_WIDTH, FRAMEBUF_HEIGHT);
initVita2d();
Expand Down

0 comments on commit 84a3f56

Please sign in to comment.