diff --git a/libeplayer3/container/container_ass.c b/libeplayer3/container/container_ass.c deleted file mode 100644 index 33fcbc0..0000000 --- a/libeplayer3/container/container_ass.c +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Container handling for subtitles handled by libass - * konfetti 2010; based on code from crow - * - * The subtitle handling as container is not a very proper solution, in - * a proper architecture this should be handled as subcontainer or something - * like that. But we dont want to make more effort as necessary here ;) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* ***************************** */ -/* Includes */ -/* ***************************** */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "common.h" -#include "misc.h" -#include "subtitle.h" -#include "writer.h" - -/* ***************************** */ -/* Makros/Constants */ -/* ***************************** */ - -#define ASS_DEBUG - -#ifdef ASS_DEBUG - -static short debug_level = 0; - -#define ass_printf(level, fmt, x...) do { \ -if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) -#else -#define ass_printf(level, fmt, x...) -#endif - -#ifndef ASS_SILENT -#define ass_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) -#else -#define ass_err(fmt, x...) -#endif - -/* Error Constants */ -#define cERR_CONTAINER_ASS_NO_ERROR 0 -#define cERR_CONTAINER_ASS_ERROR -1 - -#define ASS_RING_SIZE 5 - -#define ASS_FONT "/share/fonts/neutrino.ttf" - -/* ***************************** */ -/* Types */ -/* ***************************** */ - -typedef struct ass_s { - unsigned char *data; - int len; - unsigned char *extradata; - int extralen; - - long long int pts; - float duration; -} ass_t; - -typedef struct region_s { - unsigned int x; - unsigned int y; - unsigned int w; - unsigned int h; - time_t undisplay; - - struct region_s *next; -} region_t; - -/* ***************************** */ -/* Varaibles */ -/* ***************************** */ - -static pthread_mutex_t mutex; - -static pthread_t PlayThread; -static int hasPlayThreadStarted = 0; - -static unsigned char isContainerRunning = 0; - -static ASS_Library *ass_library; -static ASS_Renderer *ass_renderer; - -//static float ass_font_scale = 0.4; // was: 0.7 -//static float ass_line_spacing = 0.4; // was: 0.7 - -static unsigned int screen_width = 0; -static unsigned int screen_height = 0; -static uint32_t *destination = NULL; -static int destStride = 0; -static void (*framebufferBlit) (void) = NULL; - -static int needsBlit = 0; - -static ASS_Track *ass_track = NULL; - -static region_t *firstRegion = NULL; - -/* ***************************** */ -/* Prototypes */ -/* ***************************** */ - -/* ***************************** */ -/* MISC Functions */ -/* ***************************** */ - -void ass_msg_callback(int level - __attribute__ ((unused)), const char *format, - va_list va, void *ctx __attribute__ ((unused))) -{ - int n; - char *str; - va_list dst; - - va_copy(dst, va); - n = vsnprintf(NULL, 0, format, va); - if (n > 0 && (str = malloc(n + 1))) { - vsnprintf(str, n + 1, format, dst); - ass_printf(100, "%s\n", str); - free(str); - } -} - -static void getMutex(int line) -{ - ass_printf(150, "%d requesting mutex\n", line); - - pthread_mutex_lock(&mutex); - - ass_printf(150, "%d received mutex\n", line); -} - -static void releaseMutex(int line) -{ - pthread_mutex_unlock(&mutex); - - ass_printf(150, "%d released mutex\n", line); -} - -/* ********************************* */ -/* Region Undisplay handling */ -/* ********************************* */ - -/* release and undisplay all saved regions - */ -void releaseRegions() -{ - region_t *next, *old; - Writer_t *writer; - - if (firstRegion == NULL) - return; - - writer = getDefaultFramebufferWriter(); - - if (writer == NULL) { - ass_err("no framebuffer writer found!\n"); - } - - next = firstRegion; - while (next) { - if (writer) { - WriterFBCallData_t out; - - ass_printf(100, "release: w %d h %d x %d y %d\n", - next->w, next->h, next->x, next->y); - - out.data = NULL; - out.Width = next->w; - out.Height = next->h; - out.x = next->x; - out.y = next->y; - - out.Screen_Width = screen_width; - out.Screen_Height = screen_height; - out.destination = destination; - out.destStride = destStride; - - writer->writeData(&out); - needsBlit = 1; - } - old = next; - next = next->next; - free(old); - } - - firstRegion = NULL; -} - -/* check for regions which should be undisplayed. - * we are very tolerant on time here, because - * regions are also released when new regions are - * detected (see ETSI EN 300 743 Chapter Page Composition) - */ -void checkRegions() -{ -#define cDeltaTime 2 - region_t *next, *old, *prev; - Writer_t *writer; - time_t now = time(NULL); - - if (firstRegion == NULL) - return; - - writer = getDefaultFramebufferWriter(); - - if (!writer) { - ass_err("no framebuffer writer found!\n"); - } - - prev = next = firstRegion; - while (next) { - if (now > next->undisplay + cDeltaTime) { - ass_printf(100, "undisplay: %ld > %ld\n", now, - next->undisplay + cDeltaTime); - - if (writer) { - WriterFBCallData_t out; - - ass_printf(100, "release: w %d h %d x %d y %d\n", - next->w, next->h, next->x, next->y); - - out.data = NULL; - out.Width = next->w; - out.Height = next->h; - out.x = next->x; - out.y = next->y; - - out.Screen_Width = screen_width; - out.Screen_Height = screen_height; - out.destination = destination; - out.destStride = destStride; - - writer->writeData(&out); - needsBlit = 1; - } - - old = next; - next = prev->next = next->next; - - if (old == firstRegion) - firstRegion = next; - free(old); - } else { - prev = next; - next = next->next; - } - } -} - -/* store a display region for later release */ -void storeRegion(unsigned int x, unsigned int y, unsigned int w, - unsigned int h, time_t undisplay) -{ - region_t **new = &firstRegion; - - ass_printf(100, "%d %d %d %d %ld\n", x, y, w, h, undisplay); - - while (*new) - new = &(*new)->next; - - *new = malloc(sizeof(region_t)); - - (*new)->next = NULL; - (*new)->x = x; - (*new)->y = y; - (*new)->w = w; - (*new)->h = h; - (*new)->undisplay = undisplay; -} - -/* **************************** */ -/* Worker Thread */ -/* **************************** */ - -static void ASSThread(Context_t * context) -{ - char threadname[17]; - strncpy(threadname, __func__, sizeof(threadname)); - threadname[16] = 0; - prctl(PR_SET_NAME, (unsigned long) &threadname); - Writer_t *writer; - - ass_printf(10, "\n"); - - while (context->playback->isCreationPhase) { - ass_err("Thread waiting for end of init phase...\n"); - usleep(1000); - } - - ass_printf(10, "Running!\n"); - - writer = getDefaultFramebufferWriter(); - - if (writer == NULL) { - ass_err("no framebuffer writer found!\n"); - } - - while (context && context->playback && context->playback->isPlaying) { - - //IF MOVIE IS PAUSED, WAIT - if (context->playback->isPaused) { - ass_printf(20, "paused\n"); - - usleep(100000); - continue; - } - - if (context->playback->isSeeking) { - ass_printf(10, "seeking\n"); - - usleep(100000); - continue; - } - - if ((isContainerRunning) && (ass_track)) { - ASS_Image *img = NULL; - int change = 0; - unsigned long int playPts; - - if (context && context->playback) { - if (context->playback-> - Command(context, PLAYBACK_PTS, &playPts) < 0) - continue; - } - //FIXME: durch den sleep bleibt die cpu usage zw. 5 und 13%, ohne - // steigt sie bei Verwendung von subtiteln bis auf 95%. - // ich hoffe dadurch gehen keine subtitle verloren, wenn die playPts - // durch den sleep verschlafen wird. Besser wäre es den nächsten - // subtitel zeitpunkt zu bestimmen und solange zu schlafen. - usleep(10000); - if (!context->playback->mayWriteToFramebuffer) - continue; - getMutex(__LINE__); - checkRegions(); - - if (ass_renderer && ass_track) - img = - ass_render_frame(ass_renderer, ass_track, - playPts / 90.0, &change); - - ass_printf(150, "img %p pts %lu %f\n", img, playPts, - playPts / 90.0); - - if (img && ass_renderer && ass_track) { - /* the spec says, that if a new set of regions is present - * the complete display switches to the new state. So lets - * release the old regions on display. - */ - if (change != 0) - releaseRegions(); - - time_t now = time(NULL); - time_t undisplay = now + 10; - - if (ass_track && ass_track->events) - undisplay = - now + (ass_track->events->Duration + 500) / 90000; - - ASS_Image *it; - int x0 = screen_width - 1; - int y0 = screen_height - 1; - int x1 = 0; - int y1 = 0; - for (it = img; it; it = it->next) { - if (it->w && it->h) { - if (it->dst_x < x0) - x0 = it->dst_x; - if (it->dst_y < y0) - y0 = it->dst_y; - if (it->dst_x + it->w > x1) - x1 = it->dst_x + it->w; - if (it->dst_y + it->h > y1) - y1 = it->dst_y + it->h; - } - } - if (x1 > 0 && y1 > 0) { - x1++; - y1++; - int x, y; - uint32_t *dst = - destination + y0 * destStride / sizeof(uint32_t) + - x0; - int destStrideDiff = - destStride / sizeof(uint32_t) - (x1 - x0); - for (y = y0; y < y1; y++) { - for (x = x0; x < x1; x++) - *dst++ = 0x80808080; - dst += destStrideDiff; - } - storeRegion(x0, y0, x1 - x0, y1 - y0, undisplay); - needsBlit = 1; - } - - while (context && context->playback - && context->playback->isPlaying && img) { - WriterFBCallData_t out; - - ass_printf(100, - "w %d h %d s %d x %d y %d c %d chg %d now %ld und %ld\n", - img->w, img->h, img->stride, img->dst_x, - img->dst_y, img->color, change, now, - undisplay); - - /* api docu said w and h can be zero which - * means image should not be rendered - */ - if ((img->w != 0) && (img->h != 0) && writer) { - out.data = img->bitmap; - out.Width = img->w; - out.Height = img->h; - out.Stride = img->stride; - out.x = img->dst_x; - out.y = img->dst_y; - out.color = img->color; - - out.Screen_Width = screen_width; - out.Screen_Height = screen_height; - out.destination = destination; - out.destStride = destStride; - - if (context && context->playback - && context->playback->isPlaying && writer) - writer->writeData(&out); - - needsBlit = 1; - } - - /* Next image */ - img = img->next; - } - } - releaseMutex(__LINE__); - } else { - usleep(1000); - } - - if (needsBlit && framebufferBlit) - framebufferBlit(); - needsBlit = 0; - - /* cleanup no longer used but not overwritten regions */ - getMutex(__LINE__); - checkRegions(); - releaseMutex(__LINE__); - } /* while */ - - if (needsBlit && framebufferBlit) - framebufferBlit(); - needsBlit = 0; - - hasPlayThreadStarted = 0; - - ass_printf(10, "terminating\n"); - pthread_exit(NULL); -} - -/* **************************** */ -/* Container part for ass */ -/* **************************** */ - -int container_ass_init(Context_t * context) -{ - SubtitleOutputDef_t output; - - ass_printf(10, ">\n"); - - ass_library = ass_library_init(); - - if (!ass_library) { - ass_err("ass_library_init failed!\n"); - return cERR_CONTAINER_ASS_ERROR; - } - - if (debug_level >= 100) - ass_set_message_cb(ass_library, ass_msg_callback, NULL); - - ass_set_extract_fonts(ass_library, 1); - ass_set_style_overrides(ass_library, NULL); - - ass_renderer = ass_renderer_init(ass_library); - - if (!ass_renderer) { - ass_err("ass_renderer_init failed!\n"); - - if (ass_library) - ass_library_done(ass_library); - ass_library = NULL; - - return cERR_CONTAINER_ASS_ERROR; - } - - context->output->subtitle->Command(context, OUTPUT_GET_SUBTITLE_OUTPUT, - &output); - - screen_width = output.screen_width; - screen_height = output.screen_height; - destination = output.destination; - destStride = output.destStride; - framebufferBlit = output.framebufferBlit; - - ass_printf(10, "width %d, height %d\n", screen_width, screen_height); - - ass_set_frame_size(ass_renderer, screen_width, screen_height); - ass_set_margins(ass_renderer, (int) (0.03 * screen_height), - (int) (0.03 * screen_height), - (int) (0.03 * screen_width), - (int) (0.03 * screen_width)); - - ass_set_use_margins(ass_renderer, 1); -// ass_set_font_scale(ass_renderer, (ass_font_scale * screen_height) / 240.0); - - ass_set_hinting(ass_renderer, ASS_HINTING_LIGHT); -// ass_set_line_spacing(ass_renderer, (ass_line_spacing * screen_height) / 240.0); - ass_set_fonts(ass_renderer, ASS_FONT, "Arial", 0, NULL, 1); - - ass_set_aspect_ratio(ass_renderer, 1.0, 1.0); - - isContainerRunning = 1; - - return cERR_CONTAINER_ASS_NO_ERROR; -} - -int container_ass_process_data(Context_t * context - __attribute__ ((unused)), - SubtitleData_t * data) -{ - int first_kiss; - - ass_printf(20, ">\n"); - - if (!isContainerRunning) { - ass_err("Container not running\n"); - return cERR_CONTAINER_ASS_ERROR; - } - - if (ass_track == NULL) { - first_kiss = 1; - ass_track = ass_new_track(ass_library); - - if (ass_track == NULL) { - ass_err("error creating ass_track\n"); - return cERR_CONTAINER_ASS_ERROR; - } - ass_track->PlayResX = screen_width; - ass_track->PlayResY = screen_height; - } - - if ((data->extradata) && (first_kiss)) { - ass_printf(30, "processing private %d bytes\n", data->extralen); - ass_process_codec_private(ass_track, (char *) data->extradata, - data->extralen); - ass_printf(30, "processing private done\n"); - } - - if (data->data) { - ass_printf(30, "processing data %d bytes\n", data->len); - ass_process_data(ass_track, (char *) data->data, data->len); - ass_printf(30, "processing data done\n"); - } - - return cERR_CONTAINER_ASS_NO_ERROR; -} - -static int container_ass_stop(Context_t * context __attribute__ ((unused))) -{ - int ret = cERR_CONTAINER_ASS_NO_ERROR; - int wait_time = 20; - Writer_t *writer; - - ass_printf(10, "\n"); - - if (!isContainerRunning) { - ass_err("Container not running\n"); - return cERR_CONTAINER_ASS_ERROR; - } - - while ((hasPlayThreadStarted != 0) && (--wait_time) > 0) { - ass_printf(10, - "Waiting for ass thread to terminate itself, will try another %d times\n", - wait_time); - - usleep(100000); - } - - if (wait_time == 0) { - ass_err("Timeout waiting for thread!\n"); - - ret = cERR_CONTAINER_ASS_ERROR; - } - - getMutex(__LINE__); - - releaseRegions(); - - if (ass_track) - ass_free_track(ass_track); - - ass_track = NULL; - - if (ass_renderer) - ass_renderer_done(ass_renderer); - ass_renderer = NULL; - - if (ass_library) - ass_library_done(ass_library); - ass_library = NULL; - - isContainerRunning = 0; - - hasPlayThreadStarted = 0; - - writer = getDefaultFramebufferWriter(); - - if (writer) { - writer->reset(); - } - - releaseMutex(__LINE__); - - ass_printf(10, "ret %d\n", ret); - return ret; -} - -static int container_ass_switch_subtitle(Context_t * context, int *arg - __attribute__ ((unused))) -{ - int error; - int ret = cERR_CONTAINER_ASS_NO_ERROR; - pthread_attr_t attr; - - ass_printf(10, "\n"); - - if (!isContainerRunning) { - ass_err("Container not running\n"); - return cERR_CONTAINER_ASS_ERROR; - } - - if (context && context->playback && context->playback->isPlaying) { - ass_printf(10, "is Playing\n"); - } else { - ass_printf(10, "is NOT Playing\n"); - } - - if (hasPlayThreadStarted == 0) { - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - if ((error = - pthread_create(&PlayThread, &attr, (void *) &ASSThread, - context)) != 0) { - ass_printf(10, "Error creating thread, error:%d:%s\n", error, - strerror(error)); - - hasPlayThreadStarted = 0; - ret = cERR_CONTAINER_ASS_ERROR; - } else { - ass_printf(10, "Created thread\n"); - - hasPlayThreadStarted = 1; - } - } else { - ass_printf(10, "A thread already exists!\n"); - - ret = cERR_CONTAINER_ASS_ERROR; - } - - getMutex(__LINE__); - - releaseRegions(); - - /* free the track so extradata will be written next time - * process_data is called. - */ - if (ass_track) - ass_free_track(ass_track); - - ass_track = NULL; - - releaseMutex(__LINE__); - - ass_printf(10, "exiting with value %d\n", ret); - - return ret; -} - - -static int Command(void *_context, ContainerCmd_t command, void *argument) -{ - Context_t *context = (Context_t *) _context; - int ret = cERR_CONTAINER_ASS_NO_ERROR; - - ass_printf(50, "Command %d\n", command); - - switch (command) { - case CONTAINER_INIT:{ - ret = container_ass_init(context); - break; - } - case CONTAINER_STOP:{ - ret = container_ass_stop(context); - break; - } - case CONTAINER_SWITCH_SUBTITLE:{ - ret = container_ass_switch_subtitle(context, (int *) argument); - break; - } - case CONTAINER_DATA:{ - SubtitleData_t *data = (SubtitleData_t *) argument; - ret = container_ass_process_data(context, data); - break; - } - default: - ass_err("ContainerCmd %d not supported!\n", command); - ret = cERR_CONTAINER_ASS_ERROR; - break; - } - - ass_printf(50, "exiting with value %d\n", ret); - - return ret; -} - -static char *ASS_Capabilities[] = { "ass", NULL }; - -Container_t ASSContainer = { - "ASS", - &Command, - ASS_Capabilities -}; diff --git a/libeplayer3/container/text_srt.c b/libeplayer3/container/text_srt.c deleted file mode 100644 index 4aed9a3..0000000 --- a/libeplayer3/container/text_srt.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * subtitle handling for srt files. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* ***************************** */ -/* Includes */ -/* ***************************** */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "misc.h" -#include "subtitle.h" - -/* ***************************** */ -/* Makros/Constants */ -/* ***************************** */ - -#define SRT_DEBUG - -#ifdef SRT_DEBUG - -static short debug_level = 0; - -#define srt_printf(level, fmt, x...) do { \ -if (debug_level >= level) printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0) -#else -#define srt_printf(level, fmt, x...) -#endif - -#ifndef SRT_SILENT -#define srt_err(fmt, x...) do { printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0) -#else -#define srt_err(fmt, x...) -#endif - -/* Error Constants */ -#define cERR_SRT_NO_ERROR 0 -#define cERR_SRT_ERROR -1 - -#define TRACKWRAP 20 -#define MAXLINELENGTH 80 - -static const char FILENAME[] = "text_srt.c"; - -/* ***************************** */ -/* Types */ -/* ***************************** */ - -typedef struct { - char *File; - int Id; -} SrtTrack_t; - -static pthread_t thread_sub; - -/* ***************************** */ -/* Varaibles */ -/* ***************************** */ - -static SrtTrack_t *Tracks; -static int TrackCount = 0; -static int CurrentTrack = -1; //no as default. - -FILE *fsub = NULL; - -static int hasThreadStarted = 0; - -/* ***************************** */ -/* Prototypes */ -/* ***************************** */ - -/* ***************************** */ -/* MISC Functions */ -/* ***************************** */ - -void data_to_manager(Context_t * context, char *Text, - unsigned long long int Pts, double Duration) -{ - srt_printf(20, "--> Text= \"%s\"\n", Text); - - if (context && context->playback && context->playback->isPlaying) { - int sl = strlen(Text) - 1; - while (sl && (Text[sl] == '\n' || Text[sl] == '\r')) - Text[sl--] = '\0'; /*Delete last \n or \r */ - unsigned char *line = text_to_ass(Text, Pts, Duration); - srt_printf(50, "Sub text is %s\n", Text); - srt_printf(50, "Sub line is %s\n", line); - SubtitleData_t data; - data.data = line; - data.len = strlen((char *) line); - data.extradata = (unsigned char *) DEFAULT_ASS_HEAD; - data.extralen = strlen(DEFAULT_ASS_HEAD); - data.pts = Pts * 90; - data.duration = Duration; - - context->container->assContainer->Command(context, CONTAINER_DATA, - &data); - free(line); - } - - srt_printf(20, "<-- Text= \"%s\"\n", Text); -} - -/* ***************************** */ -/* Worker Thread */ -/* ***************************** */ - -static void *SrtSubtitleThread(void *data) -{ - int pos = 0; - char Data[MAXLINELENGTH]; - unsigned long long int Pts = 0; - double Duration = 0; - char *Text = NULL; - - Context_t *context = (Context_t *) data; - - srt_printf(10, "\n"); - - while (context && context->playback && context->playback->isPlaying - && fsub && fgets(Data, MAXLINELENGTH, fsub)) { - srt_printf(20, "pos=%d\n", pos); - - if (pos == 0) { - if (Data[0] == '\n' || Data[0] == '\0' - || Data[0] == 13 /* ^M */ ) - continue; /* Empty line not allowed here */ - pos++; - } else if (pos == 1) { - int ret, horIni, minIni, secIni, milIni, horFim, minFim, - secFim, milFim; - - ret = - sscanf(Data, "%d:%d:%d,%d --> %d:%d:%d,%d", &horIni, - &minIni, &secIni, &milIni, &horFim, &minFim, - &secFim, &milFim); - if (ret != 8) - continue; /* Data is not in correct format */ - - Pts = (horIni * 3600 + minIni * 60 + secIni) * 1000 + milIni; - Duration = - ((horFim * 3600 + minFim * 60 + secFim) * 1000 + milFim - - Pts) / 1000.0; - - pos++; - - } else if (pos == 2) { - srt_printf(20, "Data[0] = %d \'%c\'\n", Data[0], Data[0]); - - if (Data[0] == '\n' || Data[0] == '\0' - || Data[0] == 13 /* ^M */ ) { - if (Text == NULL) - Text = strdup(" \n"); /* better to display at least one character */ - - /*Hellmaster 1024 since we have waited, we have to check if we are still paying */ - data_to_manager(context, Text, Pts, Duration); - free(Text); - Text = NULL; - pos = 0; - continue; - } - - if (!Text) { - Text = strdup(Data); - } else { - int length = - strlen(Text) /* \0 -> \n */ +strlen(Data) + - 2 /* \0 */ ; - char *tmpText = Text; - Text = (char *) malloc(length); - - strcpy(Text, tmpText); - strcat(Text, Data); - free(tmpText); - } - } - } /* while */ - - hasThreadStarted = 0; - - if (Text) { - data_to_manager(context, Text, Pts, Duration); - free(Text); - Text = NULL; - } - - srt_printf(0, "thread has ended\n"); - - return NULL; -} - -/* ***************************** */ -/* Functions */ -/* ***************************** */ - -static void SrtManagerAdd(Context_t * context - __attribute__ ((unused)), SrtTrack_t track) -{ - srt_printf(10, "%s %d\n", track.File, track.Id); - - if (Tracks == NULL) { - Tracks = malloc(sizeof(SrtTrack_t) * TRACKWRAP); - } - - if (TrackCount < TRACKWRAP) { - Tracks[TrackCount].File = strdup(track.File); - Tracks[TrackCount].Id = track.Id; - TrackCount++; - } -} - -#if 0 -static char **SrtManagerList(Context_t * context __attribute__ ((unused))) -{ - char **tracklist = NULL; - - srt_printf(10, "\n"); - - if (Tracks != NULL) { - char help[256]; - int i = 0, j = 0; - - tracklist = malloc(sizeof(char *) * ((TrackCount * 2) + 1)); - - for (i = 0, j = 0; i < TrackCount; i++, j += 2) { - - sprintf(help, "%d", Tracks[i].Id); - tracklist[j] = strdup(help); - tracklist[j + 1] = strdup(Tracks[i].File); - } - tracklist[j] = NULL; - } - - return tracklist; -} -#endif - -static void SrtManagerDel(Context_t * context __attribute__ ((unused))) -{ - int i = 0; - - srt_printf(10, "\n"); - - if (Tracks != NULL) { - for (i = 0; i < TrackCount; i++) { - if (Tracks[i].File != NULL) - free(Tracks[i].File); - Tracks[i].File = NULL; - } - free(Tracks); - Tracks = NULL; - } - - TrackCount = 0; - CurrentTrack = -1; -} - - -static int SrtGetSubtitle(Context_t * context, char *Filename) -{ - struct dirent *dirzeiger; - DIR *dir; - int i = TEXTSRTOFFSET; - char *copyFilename = NULL; - char *FilenameExtension = NULL; - char *FilenameFolder = NULL; - char *FilenameShort = NULL; - - srt_printf(10, "\n"); - - if (Filename == NULL) { - srt_err("Filename NULL\n"); - return cERR_SRT_ERROR; - } - - srt_printf(10, "file: %s\n", Filename); - - copyFilename = strdup(Filename); - - if (copyFilename == NULL) { - srt_err("copyFilename NULL\n"); - return cERR_SRT_ERROR; - } - - FilenameFolder = dirname(copyFilename); - - srt_printf(10, "folder: %s\n", FilenameFolder); - - FilenameExtension = getExtension(copyFilename); - - if (FilenameExtension == NULL) { - srt_err("FilenameExtension NULL\n"); - free(copyFilename); - return cERR_SRT_ERROR; - } - - srt_printf(10, "ext: %s\n", FilenameExtension); - - FilenameShort = basename(copyFilename); - - /* cut extension */ - FilenameShort[strlen(FilenameShort) - strlen(FilenameExtension) - 1] = - '\0'; - - srt_printf(10, "basename: %s\n", FilenameShort); - srt_printf(10, "%s\n%s | %s | %s\n", copyFilename, FilenameFolder, - FilenameShort, FilenameExtension); - - if ((dir = opendir(FilenameFolder)) != NULL) { - while ((dirzeiger = readdir(dir)) != NULL) { - char subtitleFilename[PATH_MAX]; - char *subtitleExtension = NULL; - - srt_printf(20, "%s\n", (*dirzeiger).d_name); - - strcpy(subtitleFilename, (*dirzeiger).d_name); - - // Extension of Relativ Subtitle File Name - subtitleExtension = getExtension(subtitleFilename); - - if (subtitleExtension == NULL) - continue; - - if (strcmp(subtitleExtension, "srt") != 0) - continue; - - /* cut extension */ - subtitleFilename[strlen(subtitleFilename) - - strlen(subtitleExtension) - 1] = '\0'; - - srt_printf(10, "%s %s\n", FilenameShort, subtitleFilename); - - if (strncmp - (FilenameShort, subtitleFilename, - strlen(FilenameShort)) == 0) { - char absSubtitleFileName[PATH_MAX]; - /* found something of interest, so now make an absolut path name */ - - sprintf(absSubtitleFileName, "%s/%s.%s", FilenameFolder, - subtitleFilename, subtitleExtension); - - srt_printf(10, "SRT: %s [%s]\n", subtitleExtension, - subtitleFilename); - srt_printf(10, "\t->%s\n", absSubtitleFileName); - - SrtTrack_t SrtSubtitle = { - absSubtitleFileName, - i, - }; - - SrtManagerAdd(context, SrtSubtitle); - - Track_t Subtitle; - memset(&Subtitle, 0, sizeof(Subtitle)); - Subtitle.Name = subtitleExtension; - Subtitle.Encoding = "S_TEXT/SRT"; - Subtitle.Id = i++; - Subtitle.is_static = 1; - context->manager->subtitle->Command(context, MANAGER_ADD, &Subtitle); - } - } /* while */ - closedir(dir); - } - /* if dir */ - free(copyFilename); - - srt_printf(10, "<\n"); - return cERR_SRT_NO_ERROR; -} - -static int SrtOpenSubtitle(Context_t * context - __attribute__ ((unused)), int pid) -{ - srt_printf(10, "\n"); - - if (pid < TEXTSRTOFFSET) { - srt_err("trackid not for us\n"); - return cERR_SRT_ERROR; - } - - int trackid; - for (trackid = 0; trackid < TrackCount; trackid++) - if (Tracks[trackid].Id == pid) - break; - - if (trackid == TrackCount) { - srt_err("trackid not for us\n"); - return cERR_SRT_ERROR; - } - - srt_printf(10, "%s\n", Tracks[trackid].File); - - fsub = fopen(Tracks[trackid].File, "rb"); - - srt_printf(10, "%s\n", fsub ? "fsub!=NULL" : "fsub==NULL"); - - if (!fsub) { - srt_err("cannot open file %s\n", Tracks[trackid].File); - return cERR_SRT_ERROR; - } - return cERR_SRT_NO_ERROR; -} - -static int SrtCloseSubtitle(Context_t * context __attribute__ ((unused))) -{ - srt_printf(10, "\n"); - - if (fsub) - fclose(fsub); - - /* this closes the thread! */ - fsub = NULL; - - hasThreadStarted = 0; - - return cERR_SRT_NO_ERROR; -} - -static int SrtSwitchSubtitle(Context_t * context, int *arg) -{ - int ret = cERR_SRT_NO_ERROR; - - srt_printf(10, "arg:%d\n", *arg); - - ret = SrtCloseSubtitle(context); - - if (((ret |= SrtOpenSubtitle(context, *arg)) == cERR_SRT_NO_ERROR) - && (!hasThreadStarted)) { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&thread_sub, &attr, &SrtSubtitleThread, context); - - hasThreadStarted = 1; - } - - return ret; -} - -static int SrtDel(Context_t * context) -{ - int ret = cERR_SRT_NO_ERROR; - - srt_printf(10, "\n"); - - ret = SrtCloseSubtitle(context); - SrtManagerDel(context); - - return ret; -} - -static int Command(void *_context, ContainerCmd_t command, void *argument) -{ - Context_t *context = (Context_t *) _context; - int ret = cERR_SRT_NO_ERROR; - - srt_printf(10, "\n"); - - switch (command) { - case CONTAINER_INIT:{ - char *filename = (char *) argument; - SrtDel(context); - ret = SrtGetSubtitle(context, filename); - break; - } - case CONTAINER_DEL:{ - ret = SrtDel(context); - break; - } - case CONTAINER_SWITCH_SUBTITLE:{ - ret = SrtSwitchSubtitle(context, (int *) argument); - break; - } - default: - srt_err("ConatinerCmd not supported! %d\n", command); - break; - } - - srt_printf(10, "ret = %d\n", ret); - - return 0; -} - -static char *SrtCapabilities[] = { "srt", NULL }; - -Container_t SrtContainer = { - "SRT", - &Command, - SrtCapabilities -}; diff --git a/libeplayer3/container/text_ssa.c b/libeplayer3/container/text_ssa.c deleted file mode 100644 index 6d37d2b..0000000 --- a/libeplayer3/container/text_ssa.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * subtitle handling for ssa files. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* ***************************** */ -/* Includes */ -/* ***************************** */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "misc.h" -#include "subtitle.h" - -/* ***************************** */ -/* Makros/Constants */ -/* ***************************** */ - -#define SSA_DEBUG - -#ifdef SSA_DEBUG - -static short debug_level = 10; - -#define ssa_printf(level, fmt, x...) do { \ -if (debug_level >= level) printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0) -#else -#define ssa_printf(level, fmt, x...) -#endif - -#ifndef SSA_SILENT -#define ssa_err(fmt, x...) do { printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0) -#else -#define ssa_err(fmt, x...) -#endif - -/* Error Constants */ -#define cERR_SSA_NO_ERROR 0 -#define cERR_SSA_ERROR -1 - -#define TRACKWRAP 20 -#define MAXLINELENGTH 1000 - -static const char FILENAME[] = "text_ssa.c"; - -//Buffer size used in getLine function. Do not set to value less than 1 !!! -#define SSA_BUFFER_SIZE 14 - -/* ***************************** */ -/* Types */ -/* ***************************** */ - -typedef struct { - char *File; - int Id; -} SsaTrack_t; - -/* ***************************** */ -/* Varaibles */ -/* ***************************** */ - -static pthread_t thread_sub; - -static SsaTrack_t *Tracks; -static int TrackCount = 0; -FILE *fssa = NULL; - -static int hasThreadStarted = 0; - -/* ***************************** */ -/* Prototypes */ -/* ***************************** */ - -/* ***************************** */ -/* MISC Functions */ -/* ***************************** */ -char *SSAgetLine() -{ - char *strAux = NULL, *strInput; - char c[SSA_BUFFER_SIZE]; - int ch; - int k, tam, tamAux; - - k = tamAux = 0; - - if (SSA_BUFFER_SIZE > 0) { - - strInput = (char *) malloc(1 * sizeof(char)); - strInput[0] = '\0'; - - while (tamAux != 1) { - - if ((ch = fgetc(fssa)) != EOF) { - ungetc(ch, fssa); - fgets(c, SSA_BUFFER_SIZE, fssa); - strAux = (char *) strchr(c, '\n'); - tam = strlen(c); - if (strAux != NULL) { - tamAux = strlen(strAux); - tam--; - } - - k = k + tam; - strInput = - (char *) realloc(strInput, (k + 1) * sizeof(char)); - - if (k != tam) - strncat(strInput, c, tam); - else - strncpy(strInput, c, tam); - - strInput[k] = '\0'; - - } else { - tamAux = 1; - fclose(fssa); - fssa = NULL; - } - } - - } - - return strInput; - -} - -/* ***************************** */ -/* Worker Thread */ -/* ***************************** */ -static void *SsaSubtitleThread(void *Data) -{ - Context_t *context = (Context_t *) Data; - char *head = malloc(sizeof(char) * 1); - - ssa_printf(10, "\n"); - head[0] = '\0'; - - - while (context && context->playback && context->playback->isPlaying - && fssa) { - char *line = NULL; - - do { - line = SSAgetLine(); - if (strncmp(line, "Dialogue: ", 10)) { - int head_len = strlen(head); - int line_len = strlen(line); - head = realloc(head, line_len + head_len + 2); - memcpy(head + head_len, line, sizeof(char) * line_len + 1); - head[head_len + line_len] = '\n'; - head[head_len + line_len + 1] = '\0'; - } - } while (strncmp(line, "Dialogue: ", 10) != 0 && fssa); - - /*Hellmaster 1024 since we have waited, we have to check if we are still paying */ - if (context && context->playback && context->playback->isPlaying) { - SubtitleData_t data; - - data.data = (unsigned char *) line; - data.len = strlen(line); - data.extradata = (unsigned char *) head; - data.extralen = strlen(head); - data.pts = 0; - data.duration = 0.0; - context->container->assContainer->Command(context, - CONTAINER_DATA, - &data); - } - free(line); - line = NULL; - continue; - } - - hasThreadStarted = 0; - - if (head) { - free(head); - head = NULL; - } - ssa_printf(0, "thread has ended\n"); - - return NULL; -} - - -/* ***************************** */ -/* Functions */ -/* ***************************** */ - -static void SsaManagerAdd(Context_t * context - __attribute__ ((unused)), SsaTrack_t track) -{ - ssa_printf(10, "%s %d\n", track.File, track.Id); - - if (Tracks == NULL) { - Tracks = malloc(sizeof(SsaTrack_t) * TRACKWRAP); - } - - if (TrackCount < TRACKWRAP) { - Tracks[TrackCount].File = strdup(track.File); - Tracks[TrackCount].Id = track.Id; - TrackCount++; - } -} - -#if 0 -static char **SsaManagerList(Context_t * context __attribute__ ((unused))) -{ - char **tracklist = NULL; - - ssa_printf(10, "\n"); - - if (Tracks != NULL) { - char help[256]; - int i = 0, j = 0; - - tracklist = malloc(sizeof(char *) * ((TrackCount * 2) + 1)); - - for (i = 0, j = 0; i < TrackCount; i++, j += 2) { - - sprintf(help, "%d", Tracks[i].Id); - tracklist[j] = strdup(help); - tracklist[j + 1] = strdup(Tracks[i].File); - } - tracklist[j] = NULL; - } - - return tracklist; -} -#endif - -static void SsaManagerDel(Context_t * context __attribute__ ((unused))) -{ - int i = 0; - - ssa_printf(10, "\n"); - - if (Tracks != NULL) { - for (i = 0; i < TrackCount; i++) { - if (Tracks[i].File != NULL) - free(Tracks[i].File); - Tracks[i].File = NULL; - } - free(Tracks); - Tracks = NULL; - } - - TrackCount = 0; -} - -static int SsaGetSubtitle(Context_t * context, char *Filename) -{ - struct dirent *dirzeiger; - DIR *dir; - int i = TEXTSSAOFFSET; - char *copyFilename = NULL; - char *FilenameExtension = NULL; - char *FilenameFolder = NULL; - char *FilenameShort = NULL; - - ssa_printf(10, "\n"); - - if (Filename == NULL) { - ssa_err("Filename NULL\n"); - return cERR_SSA_ERROR; - } - - ssa_printf(10, "file: %s\n", Filename); - - copyFilename = strdup(Filename); - - if (copyFilename == NULL) { - ssa_err("copyFilename NULL\n"); - return cERR_SSA_ERROR; - } - - FilenameFolder = dirname(copyFilename); - - ssa_printf(10, "folder: %s\n", FilenameFolder); - - FilenameExtension = getExtension(copyFilename); - - if (FilenameExtension == NULL) { - ssa_err("FilenameExtension NULL\n"); - free(copyFilename); - return cERR_SSA_ERROR; - } - - ssa_printf(10, "ext: %s\n", FilenameExtension); - - FilenameShort = basename(copyFilename); - - /* cut extension */ - FilenameShort[strlen(FilenameShort) - strlen(FilenameExtension) - 1] = - '\0'; - - ssa_printf(10, "basename: %s\n", FilenameShort); - ssa_printf(10, "%s\n%s | %s | %s\n", copyFilename, FilenameFolder, - FilenameShort, FilenameExtension); - - if ((dir = opendir(FilenameFolder)) != NULL) { - while ((dirzeiger = readdir(dir)) != NULL) { - char subtitleFilename[PATH_MAX]; - char *subtitleExtension = NULL; - - ssa_printf(20, "%s\n", (*dirzeiger).d_name); - - strcpy(subtitleFilename, (*dirzeiger).d_name); - - // Extension of Relativ Subtitle File Name - subtitleExtension = getExtension(subtitleFilename); - - if (subtitleExtension == NULL) - continue; - - if (strcmp(subtitleExtension, "ssa") != 0 - && strcmp(subtitleExtension, "ass") != 0) - continue; - - /* cut extension */ - subtitleFilename[strlen(subtitleFilename) - - strlen(subtitleExtension) - 1] = '\0'; - - ssa_printf(10, "%s %s\n", FilenameShort, subtitleFilename); - - if (strncmp - (FilenameShort, subtitleFilename, - strlen(FilenameShort)) == 0) { - char absSubtitleFileName[PATH_MAX]; - /* found something of interest, so now make an absolut path name */ - - sprintf(absSubtitleFileName, "%s/%s.%s", FilenameFolder, - subtitleFilename, subtitleExtension); - - ssa_printf(10, "SSA: %s [%s]\n", subtitleExtension, - subtitleFilename); - ssa_printf(10, "\t->%s\n", absSubtitleFileName); - - SsaTrack_t SsaSubtitle = { - absSubtitleFileName, - i, - }; - - SsaManagerAdd(context, SsaSubtitle); - - Track_t Subtitle; - memset(&Subtitle, 0, sizeof(Subtitle)); - Subtitle.Name = subtitleExtension; - Subtitle.Encoding = "S_TEXT/SSA"; - Subtitle.Id = i++; - Subtitle.is_static = 1; - context->manager->subtitle->Command(context, MANAGER_ADD, &Subtitle); - } - } /* while */ - closedir(dir); - } - /* if dir */ - free(copyFilename); - - ssa_printf(10, "<\n"); - return cERR_SSA_NO_ERROR; -} - -static int SsaOpenSubtitle(Context_t * context - __attribute__ ((unused)), int pid) -{ - ssa_printf(10, "\n"); - - if (pid < TEXTSSAOFFSET) { - ssa_err("trackid not for us\n"); - return cERR_SSA_ERROR; - } - - int trackid; - for (trackid = 0; trackid < TrackCount; trackid++) - if (Tracks[trackid].Id == pid) - break; - - if (trackid == TrackCount) { - ssa_err("trackid not for us\n"); - return cERR_SSA_ERROR; - } - - ssa_printf(10, "%s\n", Tracks[trackid].File); - - fssa = fopen(Tracks[trackid].File, "rb"); - - ssa_printf(10, "%s\n", fssa ? "fssa!=NULL" : "fssa==NULL"); - - if (!fssa) { - ssa_err("cannot open file %s\n", Tracks[trackid].File); - return cERR_SSA_ERROR; - } - return cERR_SSA_NO_ERROR; -} - -static int SsaCloseSubtitle(Context_t * context __attribute__ ((unused))) -{ - ssa_printf(10, "\n"); - - if (fssa) - fclose(fssa); - - /* this closes the thread! */ - fssa = NULL; - - hasThreadStarted = 0; - - return cERR_SSA_NO_ERROR; -} - -static int SsaSwitchSubtitle(Context_t * context, int *arg) -{ - int ret = cERR_SSA_NO_ERROR; - - ssa_printf(10, "\n"); - - ret = SsaCloseSubtitle(context); - - if (((ret |= SsaOpenSubtitle(context, *arg)) == cERR_SSA_NO_ERROR) - && (!hasThreadStarted)) { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&thread_sub, &attr, &SsaSubtitleThread, context); - - hasThreadStarted = 1; - } - - return ret; -} - -static int SsaDel(Context_t * context) -{ - int ret = cERR_SSA_NO_ERROR; - - ssa_printf(10, "\n"); - - ret = SsaCloseSubtitle(context); - - SsaManagerDel(context); - - return ret; -} - -static int Command(void *_context, ContainerCmd_t command, void *argument) -{ - Context_t *context = (Context_t *) _context; - int ret = cERR_SSA_NO_ERROR; - - ssa_printf(10, "\n"); - - switch (command) { - case CONTAINER_INIT:{ - char *filename = (char *) argument; - SsaDel(context); - ret = SsaGetSubtitle(context, filename); - break; - } - case CONTAINER_DEL:{ - ret = SsaDel(context); - break; - } - case CONTAINER_SWITCH_SUBTITLE:{ - ret = SsaSwitchSubtitle(context, (int *) argument); - break; - } - default: - ssa_err("ConatinerCmd not supported! %d\n", command); - break; - } - - ssa_printf(10, "ret = %d\n", ret); - - return 0; -} - -static char *SsaCapabilities[] = { "ssa", NULL }; - -Container_t SsaContainer = { - "SSA", - &Command, - SsaCapabilities -}; diff --git a/libeplayer3/output/output_subtitle.c b/libeplayer3/output/output_subtitle.c deleted file mode 100644 index c3da391..0000000 --- a/libeplayer3/output/output_subtitle.c +++ /dev/null @@ -1,839 +0,0 @@ -/* - * Subtitle output to one registered client. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* ***************************** */ -/* Includes */ -/* ***************************** */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "output.h" -#include "subtitle.h" - -#include - -/* ***************************** */ -/* Makros/Constants */ -/* ***************************** */ - -#define SUBTITLE_DEBUG - -#ifdef SUBTITLE_DEBUG - -static short debug_level = 0; - -#define subtitle_printf(level, fmt, x...) do { \ -if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) -#else -#define subtitle_printf(level, fmt, x...) -#endif - -#ifndef SUBTITLE_SILENT -#define subtitle_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) -#else -#define subtitle_err(fmt, x...) -#endif - -/* Error Constants */ -#define cERR_SUBTITLE_NO_ERROR 0 -#define cERR_SUBTITLE_ERROR -1 - -static const char FILENAME[] = "subtitle.c"; - -/* -Number, Style, Name,, MarginL, MarginR, MarginV, Effect,, Text - -1038,0,tdk,,0000,0000,0000,,That's not good. -1037,0,tdk,,0000,0000,0000,,{\i1}Rack them up, rack them up,{\i0}\N{\i1}rack them up.{\i0} [90] -1036,0,tdk,,0000,0000,0000,,Okay, rack them up. -*/ - -#define PUFFERSIZE 20 - -/* ***************************** */ -/* Types */ -/* ***************************** */ - -struct sub_t { - char *text; - unsigned long long int pts; - unsigned long int milliDuration; -}; - - -/* ***************************** */ -/* Varaibles */ -/* ***************************** */ - -static pthread_mutex_t mutex; - -static pthread_t thread_sub; - -void *clientData = NULL; -void (*clientFunction) (long int, size_t, char *, void *); - -static struct sub_t subPuffer[PUFFERSIZE]; -static int readPointer = 0; -static int writePointer = 0; -static int hasThreadStarted = 0; -static int isSubtitleOpened = 0; -void (*dvbsubWrite)(AVSubtitle *, int64_t) = NULL; -void (*dvbsubAssWrite)(AVCodecContext *, AVSubtitle *, int) = NULL; -void (*dvbsubAssClear)(void) = NULL; - - -/* ***************************** */ -/* Prototypes */ -/* ***************************** */ - -/* ***************************** */ -/* MISC Functions */ -/* ***************************** */ -static void getMutex(int line) -{ - subtitle_printf(100, "%d requesting mutex\n", line); - - pthread_mutex_lock(&mutex); - - subtitle_printf(100, "%d received mutex\n", line); -} - -static void releaseMutex(int line) -{ - pthread_mutex_unlock(&mutex); - - subtitle_printf(100, "%d released mutex\n", line); -} - -void replace_all(char **string, char *search, char *replace) -{ - int len = 0; - char *ptr = NULL; - char tempString[512]; - char newString[512]; - - newString[0] = '\0'; - - if ((string == NULL) || (*string == NULL) || (search == NULL) - || (replace == NULL)) { - subtitle_err("null pointer passed\n"); - return; - } - - strncpy(tempString, *string, 511); - tempString[511] = '\0'; - - free(*string); - - while ((ptr = strstr(tempString, search)) != NULL) { - len = ptr - tempString; - strncpy(newString, tempString, len); - newString[len] = '\0'; - strcat(newString, replace); - - len += strlen(search); - strcat(newString, tempString + len); - - strcpy(tempString, newString); - } - - subtitle_printf(20, "strdup in line %d\n", __LINE__); - - if (newString[0] != '\0') - *string = strdup(newString); - else - *string = strdup(tempString); - -} - -int subtitle_ParseASS(char **Line) -{ - char *Text; - int i; - char *ptr1; - - if ((Line == NULL) || (*Line == NULL)) { - subtitle_err("null pointer passed\n"); - return cERR_SUBTITLE_ERROR; - } - - Text = strdup(*Line); - - subtitle_printf(10, "-> Text = %s\n", *Line); - - ptr1 = Text; - - for (i = 0; i < 9 && *ptr1 != '\0'; ptr1++) { - - subtitle_printf(20, "%s", ptr1); - - if (*ptr1 == ',') - i++; - } - - free(*Line); - - *Line = strdup(ptr1); - free(Text); - - replace_all(Line, "\\N", "\n"); - - replace_all(Line, "{\\i1}", ""); - replace_all(Line, "{\\i0}", ""); - - subtitle_printf(10, "<- Text=%s\n", *Line); - - return cERR_SUBTITLE_NO_ERROR; -} - -int subtitle_ParseSRT(char **Line) -{ - - if ((Line == NULL) || (*Line == NULL)) { - subtitle_err("null pointer passed\n"); - return cERR_SUBTITLE_ERROR; - } - - subtitle_printf(20, "-> Text=%s\n", *Line); - - replace_all(Line, "\x0d", ""); - replace_all(Line, "\n\n", "\\N"); - replace_all(Line, "\n", ""); - replace_all(Line, "\\N", "\n"); - replace_all(Line, "ö", "oe"); - replace_all(Line, "ä", "ae"); - replace_all(Line, "ü", "ue"); - replace_all(Line, "Ö", "Oe"); - replace_all(Line, "Ä", "Ae"); - replace_all(Line, "Ü", "Ue"); - replace_all(Line, "ß", "ss"); - - subtitle_printf(10, "<- Text=%s\n", *Line); - - return cERR_SUBTITLE_NO_ERROR; -} - -int subtitle_ParseSSA(char **Line) -{ - - if ((Line == NULL) || (*Line == NULL)) { - subtitle_err("null pointer passed\n"); - return cERR_SUBTITLE_ERROR; - } - - subtitle_printf(20, "-> Text=%s\n", *Line); - - replace_all(Line, "\x0d", ""); - replace_all(Line, "\n\n", "\\N"); - replace_all(Line, "\n", ""); - replace_all(Line, "\\N", "\n"); - replace_all(Line, "ö", "oe"); - replace_all(Line, "ä", "ae"); - replace_all(Line, "ü", "ue"); - replace_all(Line, "Ö", "Oe"); - replace_all(Line, "Ä", "Ae"); - replace_all(Line, "Ü", "Ue"); - replace_all(Line, "ß", "ss"); - - subtitle_printf(10, "<- Text=%s\n", *Line); - - return cERR_SUBTITLE_NO_ERROR; -} - -void addSub(Context_t * context, char *text, unsigned long long int pts, - unsigned long int milliDuration) -{ - int count = 20; - - subtitle_printf(50, "index %d\n", writePointer); - - if (context && context->playback && !context->playback->isPlaying) { - subtitle_err("1. aborting ->no playback\n"); - return; - } - - if (text == NULL) { - subtitle_err("null pointer passed\n"); - return; - } - - if (pts == 0) { - subtitle_err("pts 0\n"); - return; - } - - if (milliDuration == 0) { - subtitle_err("duration 0\n"); - return; - } - - while (subPuffer[writePointer].text != NULL) { - //List is full, wait till we got some free space - - if (context && context->playback && !context->playback->isPlaying) { - subtitle_err("2. aborting ->no playback\n"); - return; - } - -/* konfetti: we dont want to block forever here. if no buffer - * is available we start ring from the beginning and loose some stuff - * which is acceptable! - */ - subtitle_printf(10, "waiting on free buffer %d - %d (%d) ...\n", - writePointer, readPointer, count); - usleep(10000); - count--; - - if (count == 0) { - subtitle_err("abort waiting on buffer...\n"); - break; - } - } - - subtitle_printf(20, "from mkv: %s pts:%lld milliDuration:%lud\n", text, - pts, milliDuration); - - getMutex(__LINE__); - - if (count == 0) { - int i; - subtitle_err("freeing not delivered data\n"); - - //Reset all - readPointer = 0; - writePointer = 0; - - for (i = 0; i < PUFFERSIZE; i++) { - if (subPuffer[i].text != NULL) - free(subPuffer[i].text); - subPuffer[i].text = NULL; - subPuffer[i].pts = 0; - subPuffer[i].milliDuration = 0; - } - } - - subPuffer[writePointer].text = strdup(text); - subPuffer[writePointer].pts = pts; - subPuffer[writePointer].milliDuration = milliDuration; - - writePointer++; - - if (writePointer == PUFFERSIZE) - writePointer = 0; - - if (writePointer == readPointer) { - /* this should not happen, and means that there is nor reader or - * the reader has performance probs ;) - * the recovery is done at startup of this function - but next time - */ - subtitle_err("ups something went wrong. no more readers? \n"); - } - - releaseMutex(__LINE__); - - subtitle_printf(10, "<\n"); -} - -int getNextSub(char **text, unsigned long long int *pts, - long int *milliDuration) -{ - - subtitle_printf(50, "index %d\n", readPointer); - - if (text == NULL) { - subtitle_err("null pointer passed\n"); - return cERR_SUBTITLE_ERROR; - } - - getMutex(__LINE__); - - if (subPuffer[readPointer].text == NULL) { - /* this is acutally not an error, because it may happen - * that there is no subtitle for a while - */ - subtitle_printf(200, "null in subPuffer\n"); - releaseMutex(__LINE__); - return cERR_SUBTITLE_ERROR; - } - - *text = strdup(subPuffer[readPointer].text); - free(subPuffer[readPointer].text); - subPuffer[readPointer].text = NULL; - - *pts = subPuffer[readPointer].pts; - subPuffer[readPointer].pts = 0; - - *milliDuration = subPuffer[readPointer].milliDuration; - subPuffer[readPointer].milliDuration = 0; - - readPointer++; - - if (readPointer == PUFFERSIZE) - readPointer = 0; - - if (writePointer == readPointer) { - /* this may happen, in normal case the reader is ones ahead the - * writer. So this is the normal case that we eat the data - * and have the reader reached. - */ - subtitle_printf(20, - "ups something went wrong. no more writers? \n"); - } - - releaseMutex(__LINE__); - - subtitle_printf(20, "readPointer %d\n", readPointer); - subtitle_printf(10, "<\n"); - - return cERR_SUBTITLE_NO_ERROR; -} - -/* **************************** */ -/* Worker Thread */ -/* **************************** */ - -static void *SubtitleThread(void *data) -{ - Context_t *context = (Context_t *) data; - char *subText = NULL; - long int subMilliDuration = 0; - unsigned long long int subPts = 0; - unsigned long long int Pts = 0; - - subtitle_printf(10, "\n"); - - while (context->playback->isCreationPhase) { - subtitle_err("Thread waiting for end of init phase...\n"); - usleep(1000); - } - - subtitle_printf(10, "done\n"); - - while (context && context->playback && context->playback->isPlaying) { - - int curtrackid = -1; - - if (context && context->manager && context->manager->subtitle) - context->manager->subtitle->Command(context, MANAGER_GET, - &curtrackid); - - subtitle_printf(50, "curtrackid %d\n", curtrackid); - - if (curtrackid >= 0) { - if (getNextSub(&subText, &subPts, &subMilliDuration) != 0) { - usleep(500000); - continue; - } - - if (context && context->playback) - context->playback->Command(context, PLAYBACK_PTS, &Pts); - else - return NULL; - - if (Pts > subPts) { - subtitle_printf(10, "subtitle is to late, ignoring\n"); - if (subText != NULL) - free(subText); - continue; - } - - subtitle_printf(20, "Pts:%llu < subPts%llu duration %ld\n", - Pts, subPts, subMilliDuration); - - while (context && - context->playback && - context->playback->isPlaying && Pts < subPts) { - - unsigned long int diff = subPts - Pts; - diff = (diff * 1000) / 90.0; - - subtitle_printf(50, "DIFF: %lud\n", diff); - - if (diff > 100) - usleep(diff); - - if (context && context->playback) - context->playback->Command(context, PLAYBACK_PTS, - &Pts); - else { - subtitle_err("no playback ? terminated?\n"); - break; - } - subtitle_printf(20, "cur: %llu wanted: %llu\n", Pts, - subPts); - } - - if (context && - context->playback && - context->playback->isPlaying && subText != NULL) { - - if (clientFunction != NULL) - clientFunction(subMilliDuration, strlen(subText), - subText, clientData); - else - subtitle_printf(10, - "writing Sub failed (%ld) (%d) \"%s\"\n", - subMilliDuration, strlen(subText), - subText); - - free(subText); - } - - } /* trackID >= 0 */ - else //Wait - usleep(500000); - - } /* outer while */ - - subtitle_printf(0, "has ended\n"); - - hasThreadStarted = 0; - - return NULL; -} - -/* ***************************** */ -/* Functions */ -/* ***************************** */ - -static int Write(void *_context, void *data) -{ - Context_t *context = (Context_t *) _context; - char *Encoding = NULL; - char *Text; - SubtitleOut_t *out; - int DataLength; - unsigned long long int Pts; - float Duration; - - subtitle_printf(10, "\n"); - - if (data == NULL) { - subtitle_err("null pointer passed\n"); - return cERR_SUBTITLE_ERROR; - } - - out = (SubtitleOut_t *) data; - - if (out->type == eSub_Txt) { - Text = strdup((const char *) out->u.text.data); - } else { -/* fixme handle gfx subs from container_ass and send it to - * the callback. this must be implemented also in e2/neutrino - * then. - */ - subtitle_err("subtitle gfx currently not handled\n"); - return cERR_SUBTITLE_ERROR; - } - - DataLength = out->u.text.len; - Pts = out->pts; - Duration = out->duration; - - context->manager->subtitle->Command(context, MANAGER_GETENCODING, - &Encoding); - - if (Encoding == NULL) { - subtitle_err("encoding unknown\n"); - free(Text); - return cERR_SUBTITLE_ERROR; - } - - subtitle_printf(20, "Encoding:%s Text:%s Len:%d\n", Encoding, Text, - DataLength); - - if (!strncmp("S_TEXT/SSA", Encoding, 10) || - !strncmp("S_SSA", Encoding, 5)) - subtitle_ParseSSA(&Text); - - else if (!strncmp("S_TEXT/ASS", Encoding, 10) || - !strncmp("S_AAS", Encoding, 5)) - subtitle_ParseASS(&Text); - - else if (!strncmp("S_TEXT/SRT", Encoding, 10) || - !strncmp("S_SRT", Encoding, 5)) - subtitle_ParseSRT(&Text); - else { - subtitle_err("unknown encoding %s\n", Encoding); - return cERR_SUBTITLE_ERROR; - } - - subtitle_printf(10, "Text:%s Duration:%f\n", Text, Duration); - - addSub(context, Text, Pts, Duration * 1000); - - free(Text); - free(Encoding); - - subtitle_printf(10, "<\n"); - - return cERR_SUBTITLE_NO_ERROR; -} - -static int subtitle_Open(Context_t * context __attribute__ ((unused))) -{ - int i; - - subtitle_printf(10, "\n"); - - if (isSubtitleOpened == 1) { - subtitle_err("already opened! ignoring\n"); - return cERR_SUBTITLE_ERROR; - } - - getMutex(__LINE__); - - //Reset all - readPointer = 0; - writePointer = 0; - - for (i = 0; i < PUFFERSIZE; i++) { - subPuffer[i].text = NULL; - subPuffer[i].pts = 0; - subPuffer[i].milliDuration = 0; - } - - isSubtitleOpened = 1; - - releaseMutex(__LINE__); - - subtitle_printf(10, "<\n"); - - return cERR_SUBTITLE_NO_ERROR; -} - -static int subtitle_Close(Context_t * context __attribute__ ((unused))) -{ - int i; - - subtitle_printf(10, "\n"); - - getMutex(__LINE__); - - //Reset all - readPointer = 0; - writePointer = 0; - - for (i = 0; i < PUFFERSIZE; i++) { - if (subPuffer[i].text != NULL) - free(subPuffer[i].text); - - subPuffer[i].text = NULL; - subPuffer[i].pts = 0; - subPuffer[i].milliDuration = 0; - } - - isSubtitleOpened = 0; - - releaseMutex(__LINE__); - - subtitle_printf(10, "<\n"); - - return cERR_SUBTITLE_NO_ERROR; -} - -static int subtitle_Play(Context_t * context) -{ - subtitle_printf(10, "\n"); - - if (hasThreadStarted == 0) { - pthread_attr_t attr; - - pthread_attr_init(&attr); - - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - if (pthread_create - (&thread_sub, &attr, &SubtitleThread, (void *) context) != 0) { - subtitle_err("Error creating thread\n"); - hasThreadStarted = 0; - } else { - subtitle_printf(10, "Created thread\n"); - hasThreadStarted = 1; - } - } else { - subtitle_err("thread already created.\n"); - return cERR_SUBTITLE_ERROR; - } - - subtitle_printf(10, "<\n"); - - return cERR_SUBTITLE_NO_ERROR; -} - -static int subtitle_Stop(Context_t * context __attribute__ ((unused))) -{ - int wait_time = 20; - int i; - - subtitle_printf(10, "\n"); - - while ((hasThreadStarted != 0) && (--wait_time) > 0) { - subtitle_printf(10, - "Waiting for subtitle thread to terminate itself, will try another %d times\n", - wait_time); - usleep(100000); - } - - if (wait_time == 0) { - subtitle_err("Timeout waiting for thread!\n"); - - return cERR_SUBTITLE_ERROR; - } - - hasThreadStarted = 0; - - /* konfetti: thread has ended, so nobody will eat the date... - * free the data... - */ - - getMutex(__LINE__); - - //Reset all - readPointer = 0; - writePointer = 0; - - for (i = 0; i < PUFFERSIZE; i++) { - if (subPuffer[i].text != NULL) - free(subPuffer[i].text); - - subPuffer[i].text = NULL; - subPuffer[i].pts = 0; - subPuffer[i].milliDuration = 0; - } - - releaseMutex(__LINE__); - - subtitle_printf(10, "<\n"); - - return cERR_SUBTITLE_NO_ERROR; -} - -void subtitle_SignalConnect(void (*fkt) (long int, size_t, char *, void *)) -{ - subtitle_printf(10, "%p\n", fkt); - - clientFunction = fkt; -} - -void subtitle_SignalConnectBuffer(void *data) -{ - subtitle_printf(10, "%p\n", data); - - clientData = data; -} - -static int Command(void *_context, OutputCmd_t command, void *argument) -{ - Context_t *context = (Context_t *) _context; - int ret = cERR_SUBTITLE_NO_ERROR; - - subtitle_printf(50, "%d\n", command); - - switch (command) { - case OUTPUT_OPEN:{ - ret = subtitle_Open(context); - break; - } - case OUTPUT_CLOSE:{ - ret = subtitle_Close(context); - break; - } - case OUTPUT_PLAY:{ - ret = subtitle_Play(context); - break; - } - case OUTPUT_STOP:{ - ret = subtitle_Stop(context); - break; - } - case OUTPUT_SWITCH:{ - subtitle_err("Subtitle Switch not implemented\n"); - ret = cERR_SUBTITLE_ERROR; - break; - } - case OUTPUT_GET_SUBTITLE_OUTPUT:{ - SubtitleOutputDef_t *out = (SubtitleOutputDef_t *) argument; - out->dvbsubWrite = (void (*)(void *, int64_t))dvbsubWrite; - out->dvbsubAssWrite = (void (*)(void *, void *, int))dvbsubAssWrite; - out->dvbsubAssClear = (void (*)(void))dvbsubAssClear; - break; - } - case OUTPUT_SET_SUBTITLE_OUTPUT:{ - SubtitleOutputDef_t *out = (SubtitleOutputDef_t *) argument; - dvbsubWrite = (void (*)(AVSubtitle *, int64_t))out->dvbsubWrite; - dvbsubAssWrite = (void (*)(AVCodecContext *, AVSubtitle *, int))out->dvbsubAssWrite; - dvbsubAssClear = (void (*)(void))out->dvbsubAssClear; - break; - } - case OUTPUT_SUBTITLE_REGISTER_FUNCTION:{ - subtitle_SignalConnect(argument); - break; - } - case OUTPUT_SUBTITLE_REGISTER_BUFFER:{ - subtitle_SignalConnectBuffer(argument); - break; - } - case OUTPUT_FLUSH:{ - subtitle_err("Subtitle Flush not implemented\n"); - ret = cERR_SUBTITLE_ERROR; - break; - } - case OUTPUT_PAUSE:{ - subtitle_err("Subtitle Pause not implemented\n"); - ret = cERR_SUBTITLE_ERROR; - break; - } - case OUTPUT_CONTINUE:{ - subtitle_err("Subtitle Continue not implemented\n"); - ret = cERR_SUBTITLE_ERROR; - break; - } - default: - subtitle_err("OutputCmd %d not supported!\n", command); - ret = cERR_SUBTITLE_ERROR; - break; - } - - subtitle_printf(50, "exiting with value %d\n", ret); - - return ret; -} - - -static char *SubtitleCapabilitis[] = { "subtitle", NULL }; - -struct Output_s SubtitleOutput = { - "Subtitle", - &Command, - &Write, - SubtitleCapabilitis -}; diff --git a/libeplayer3/output/writer/framebuffer.c b/libeplayer3/output/writer/framebuffer.c deleted file mode 100644 index ba673b4..0000000 --- a/libeplayer3/output/writer/framebuffer.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * framebuffer output/writer handling. - * - * This is a hacky implementation of a framebuffer output for the subtitling. - * This is ment as a POV, later this should be implemented in enigma2 and - * neutrino. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* ***************************** */ -/* Includes */ -/* ***************************** */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "output.h" -#include "debug.h" -#include "misc.h" -#include "writer.h" - -/* ***************************** */ -/* Makros/Constants */ -/* ***************************** */ - -#define FB_DEBUG - -#ifdef FB_DEBUG - -static short debug_level = 0; - -#define fb_printf(level, fmt, x...) do { \ -if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) -#else -#define fb_printf(level, fmt, x...) -#endif - -#ifndef FB_SILENT -#define fb_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) -#else -#define fb_err(fmt, x...) -#endif - -#define _r(c) ((c)>>24) -#define _g(c) (((c)>>16)&0xFF) -#define _b(c) (((c)>>8)&0xFF) -#define _a(c) ((c)&0xFF) - -/* ***************************** */ -/* Types */ -/* ***************************** */ - -/* ***************************** */ -/* Varaibles */ -/* ***************************** */ - -/* ***************************** */ -/* Prototypes */ -/* ***************************** */ - -/* ***************************** */ -/* MISC Functions */ -/* ***************************** */ - - -/* ***************************** */ -/* Writer Functions */ -/* ***************************** */ - -static int reset() -{ - return 0; -} - -static int writeData(void *_call) -{ - int res = 0; - - WriterFBCallData_t *call = (WriterFBCallData_t *) _call; - - fb_printf(100, "\n"); - - if (!call) { - fb_err("call data is NULL...\n"); - return 0; - } - - if (!call->destination) { - fb_err("frame buffer == NULL. ignoring ...\n"); - return 0; - } - - int dst_stride = call->destStride / sizeof(uint32_t); - int dst_delta = dst_stride - call->Width; - uint32_t *dst = call->destination + call->y * dst_stride + call->x; - - if (call->data) { - int src_delta = call->Stride - call->Width; - unsigned char *src = call->data; - static uint32_t last_color = 0, colortable[256]; - - if (last_color != call->color) { - // call->color is rgba, our spark frame buffer is argb - uint32_t c = call->color >> 8, a = 255 - (call->color & 0xff); - int i; - for (i = 0; i < 256; i++) { - uint32_t k = (a * i) >> 8; - colortable[i] = k ? (c | (k << 24)) : 0; - } - last_color = call->color; - } - - fb_printf(100, "x %d\n", call->x); - fb_printf(100, "y %d\n", call->y); - fb_printf(100, "width %d\n", call->Width); - fb_printf(100, "height %d\n", call->Height); - fb_printf(100, "stride %d\n", call->Stride); - fb_printf(100, "color 0x%.8x\n", call->color); - fb_printf(100, "data %p\n", call->data); - fb_printf(100, "dest %p\n", call->destination); - fb_printf(100, "dest.stride %d\n", call->destStride); - - unsigned char *src_final = src + call->Height * call->Width; - for (; src < src_final; dst += dst_delta, src += src_delta) { - u_char *src_end = src + call->Width; - for (; src < src_end; dst++, src++) { - uint32_t c = colortable[*src]; - if (c) - *dst = c; - } - } - } else { - uint32_t *dst_final = - dst + call->Width + call->Height * dst_stride; - for (; dst < dst_final; dst += dst_delta) { - uint32_t *dst_end = dst + call->Width; - for (; dst < dst_end; dst++) - *dst = 0; - } - } - - fb_printf(100, "< %d\n", res); - return res; -} - -/* ***************************** */ -/* Writer Definition */ -/* ***************************** */ -static WriterCaps_t caps = { - "framebuffer", - eGfx, - "framebuffer", - 0 -}; - -struct Writer_s WriterFramebuffer = { - &reset, - &writeData, - NULL, - &caps -};