From 35da5243e7711166cf4a80fc27d93da2fd3d3145 Mon Sep 17 00:00:00 2001 From: martii Date: Fri, 26 Jul 2013 16:59:58 +0200 Subject: [PATCH] libeplayer3: initial attempt to unbreak ass/ssa subtitles --- libeplayer3/container/container_ass.c | 8 +- libeplayer3/container/container_ffmpeg.c | 98 +++++++++++++----------- libeplayer3/container/text_srt.c | 16 +++- libeplayer3/container/text_ssa.c | 18 +++-- libeplayer3/include/common.h | 2 +- libeplayer3/manager/audio.c | 2 +- libeplayer3/manager/dvbsubtitle.c | 2 +- libeplayer3/manager/subtitle.c | 23 +++--- libeplayer3/manager/teletext.c | 2 +- libeplayer3/manager/video.c | 2 +- libeplayer3/output/writer/framebuffer.c | 39 +++++----- libeplayer3/playback/playback.c | 8 +- 12 files changed, 123 insertions(+), 97 deletions(-) diff --git a/libeplayer3/container/container_ass.c b/libeplayer3/container/container_ass.c index a2611c9..dd4de10 100644 --- a/libeplayer3/container/container_ass.c +++ b/libeplayer3/container/container_ass.c @@ -55,7 +55,7 @@ #ifdef ASS_DEBUG -static short debug_level = 0; +static short debug_level = 10; #define ass_printf(level, fmt, x...) do { \ if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) @@ -116,8 +116,8 @@ static unsigned char isContainerRunning = 0; static ASS_Library *ass_library; static ASS_Renderer *ass_renderer; -static float ass_font_scale = 0.7; -static float ass_line_spacing = 0.7; +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; @@ -592,7 +592,7 @@ int container_ass_init(Context_t *context) (int)(0.03 * screen_width ), (int)(0.03 * screen_width ) ); } - ass_set_use_margins(ass_renderer, 0 ); + 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); diff --git a/libeplayer3/container/container_ffmpeg.c b/libeplayer3/container/container_ffmpeg.c index 54e8ba9..9080da5 100644 --- a/libeplayer3/container/container_ffmpeg.c +++ b/libeplayer3/container/container_ffmpeg.c @@ -427,12 +427,6 @@ static void FFMPEGThread(Context_t *context) { if (av_read_frame(avContext, &packet) == 0 ) { - if (!packet.data) { - ffmpeg_err("no data ->end of file reached ? \n"); - releaseMutex(FILENAME, __FUNCTION__,__LINE__); - break; - } - long long int pts; Track_t * videoTrack = NULL; Track_t * audioTrack = NULL; @@ -706,7 +700,7 @@ static void FFMPEGThread(Context_t *context) { if (duration > 0.0) { /* is there a decoder ? */ - if (avcodec_find_decoder(((AVStream*) subtitleTrack->stream)->codec->codec_id) != NULL) + if (((AVStream*) subtitleTrack->stream)->codec->codec) { AVSubtitle sub; int got_sub_ptr; @@ -739,41 +733,41 @@ static void FFMPEGThread(Context_t *context) { } } - } - if(((AVStream*)subtitleTrack->stream)->codec->codec_id == AV_CODEC_ID_SSA) - { - SubtitleData_t data; + if(((AVStream*)subtitleTrack->stream)->codec->codec_id == AV_CODEC_ID_SSA) + { + SubtitleData_t data; - ffmpeg_printf(10, "videoPts %lld\n", currentVideoPts); + ffmpeg_printf(10, "videoPts %lld\n", currentVideoPts); - data.data = packet.data; - data.len = packet.size; - data.extradata = subtitleTrack->extraData; - data.extralen = subtitleTrack->extraSize; - data.pts = pts; - data.duration = duration; + data.data = packet.data; + data.len = packet.size; + data.extradata = subtitleTrack->extraData; + data.extralen = subtitleTrack->extraSize; + data.pts = pts; + data.duration = duration; - context->container->assContainer->Command(context, CONTAINER_DATA, &data); - } - else - { - /* hopefully native text ;) */ + context->container->assContainer->Command(context, CONTAINER_DATA, &data); + } + else + { + /* hopefully native text ;) */ - unsigned char* line = text_to_ass((char *)packet.data,pts/90,duration); - ffmpeg_printf(50,"text line is %s\n",(char *)packet.data); - ffmpeg_printf(50,"Sub line is %s\n",line); - ffmpeg_printf(20, "videoPts %lld %f\n", currentVideoPts,currentVideoPts/90000.0); - 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; - data.duration = duration; + unsigned char* line = text_to_ass((char *)packet.data,pts/90,duration); + ffmpeg_printf(50,"text line is %s\n",(char *)packet.data); + ffmpeg_printf(50,"Sub line is %s\n",line); + ffmpeg_printf(20, "videoPts %lld %f\n", currentVideoPts,currentVideoPts/90000.0); + 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; + data.duration = duration; - context->container->assContainer->Command(context, CONTAINER_DATA, &data); - free(line); + context->container->assContainer->Command(context, CONTAINER_DATA, &data); + free(line); + } } } /* duration */ } @@ -818,12 +812,15 @@ static void FFMPEGThread(Context_t *context) { //ffmpeg_err("writing data to teletext fifo failed\n"); } } + } else { // av_read_frame failed + ffmpeg_err("no data ->end of file reached ? \n"); + av_free_packet(&packet); + releaseMutex(FILENAME, __FUNCTION__,__LINE__); + break; // while } av_free_packet(&packet); - releaseMutex(FILENAME, __FUNCTION__,__LINE__); - } /* while */ if (swr) @@ -924,10 +921,10 @@ int container_ffmpeg_init(Context_t *context, char * filename) terminating = 0; latestPts = 0; isContainerRunning = 1; - return container_ffmpeg_update_tracks(context, filename); + return container_ffmpeg_update_tracks(context, filename, 1); } -int container_ffmpeg_update_tracks(Context_t *context, char *filename) +int container_ffmpeg_update_tracks(Context_t *context, char *filename, int initial) { if (terminating) return cERR_CONTAINER_FFMPEG_NO_ERROR; @@ -942,13 +939,14 @@ int container_ffmpeg_update_tracks(Context_t *context, char *filename) int teletextId = -1; context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); - context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack); + if (initial) + context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack); context->manager->dvbsubtitle->Command(context, MANAGER_GET_TRACK, &dvbsubtitleTrack); context->manager->teletext->Command(context, MANAGER_GET_TRACK, &teletextTrack); if (audioTrack) audioId = ((AVStream *) (audioTrack->stream))->id; - if (subtitleTrack) + if (initial && subtitleTrack) subtitleId = ((AVStream *) (subtitleTrack->stream))->id; if (dvbsubtitleTrack) dvbsubtitleId = ((AVStream *) (dvbsubtitleTrack->stream))->id; @@ -961,7 +959,7 @@ int container_ffmpeg_update_tracks(Context_t *context, char *filename) context->manager->video->Command(context, MANAGER_DEL, NULL); if (context->manager->audio) context->manager->audio->Command(context, MANAGER_DEL, NULL); - if (context->manager->subtitle) + if (initial && context->manager->subtitle) context->manager->subtitle->Command(context, MANAGER_DEL, NULL); if (context->manager->dvbsubtitle) context->manager->dvbsubtitle->Command(context, MANAGER_DEL, NULL); @@ -1319,11 +1317,21 @@ int container_ffmpeg_update_tracks(Context_t *context, char *filename) if (context->manager->dvbsubtitle->Command(context, MANAGER_ADD, &track) < 0) { ffmpeg_err("failed to add dvbsubtitle track %d\n", n); } - } else if (context->manager->subtitle) - if (context->manager->subtitle->Command(context, MANAGER_ADD, &track) < 0) { + } else if (initial && context->manager->subtitle) { + if (!stream->codec->codec) { + stream->codec->codec = avcodec_find_decoder(stream->codec->codec_id); + if (!stream->codec->codec) + ffmpeg_err("avcodec_find_decoder failed for subtitle track %d\n", n); + else if (avcodec_open2(stream->codec, stream->codec->codec, NULL)) { + ffmpeg_err("avcodec_open2 failed for subtitle track %d\n", n); + stream->codec->codec = NULL; + } + } + if (stream->codec->codec && context->manager->subtitle->Command(context, MANAGER_ADD, &track) < 0) { /* konfetti: fixme: is this a reason to return with error? */ ffmpeg_err("failed to add subtitle track %d\n", n); } + } break; } diff --git a/libeplayer3/container/text_srt.c b/libeplayer3/container/text_srt.c index 5f5f529..c051b51 100644 --- a/libeplayer3/container/text_srt.c +++ b/libeplayer3/container/text_srt.c @@ -21,11 +21,11 @@ /* Includes */ /* ***************************** */ +#include #include #include #include #include -#include #include #include #include @@ -384,15 +384,23 @@ static int SrtGetSubtitle(Context_t *context, char * Filename) { return cERR_SRT_NO_ERROR; } -static int SrtOpenSubtitle(Context_t *context __attribute__((unused)), int trackid) { +static int SrtOpenSubtitle(Context_t *context __attribute__((unused)), int pid) { srt_printf(10, "\n"); - if(trackid < TEXTSRTOFFSET || (trackid % TEXTSRTOFFSET) >= TrackCount) { + if(pid < TEXTSRTOFFSET) { srt_err("trackid not for us\n"); return cERR_SRT_ERROR; } - trackid %= TEXTSRTOFFSET; + 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); diff --git a/libeplayer3/container/text_ssa.c b/libeplayer3/container/text_ssa.c index 436c590..96d4b21 100644 --- a/libeplayer3/container/text_ssa.c +++ b/libeplayer3/container/text_ssa.c @@ -47,7 +47,7 @@ #ifdef SSA_DEBUG -static short debug_level = 0; +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) @@ -263,7 +263,6 @@ static void SsaManagerDel(Context_t * context __attribute__((unused))) { for (i = 0; i < TrackCount; i++) { if (Tracks[i].File != NULL) free(Tracks[i].File); - Tracks[i].File = NULL; } free(Tracks); @@ -386,15 +385,24 @@ static int SsaGetSubtitle(Context_t *context, char * Filename) { return cERR_SSA_NO_ERROR; } -static int SsaOpenSubtitle(Context_t *context __attribute__((unused)), int trackid) { + +static int SsaOpenSubtitle(Context_t *context __attribute__((unused)), int pid) { ssa_printf(10, "\n"); - if(trackid < TEXTSSAOFFSET || (trackid % TEXTSSAOFFSET) >= TrackCount ) { + if(pid < TEXTSSAOFFSET) { ssa_err("trackid not for us\n"); return cERR_SSA_ERROR; } - trackid %= TEXTSSAOFFSET; + 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); diff --git a/libeplayer3/include/common.h b/libeplayer3/include/common.h index ba6615b..6147750 100644 --- a/libeplayer3/include/common.h +++ b/libeplayer3/include/common.h @@ -14,5 +14,5 @@ typedef struct Context_s { ManagerHandler_t * manager; } Context_t; -int container_ffmpeg_update_tracks(Context_t *context, char *filename); +int container_ffmpeg_update_tracks(Context_t *context, char *filename, int initial); #endif diff --git a/libeplayer3/manager/audio.c b/libeplayer3/manager/audio.c index 326b4ce..034e698 100644 --- a/libeplayer3/manager/audio.c +++ b/libeplayer3/manager/audio.c @@ -180,7 +180,7 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) { break; } case MANAGER_LIST: { - container_ffmpeg_update_tracks(context, context->playback->uri); + container_ffmpeg_update_tracks(context, context->playback->uri, 0); *((char***)argument) = (char **)ManagerList(context); break; } diff --git a/libeplayer3/manager/dvbsubtitle.c b/libeplayer3/manager/dvbsubtitle.c index 272cadf..3d66f12 100644 --- a/libeplayer3/manager/dvbsubtitle.c +++ b/libeplayer3/manager/dvbsubtitle.c @@ -180,7 +180,7 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) { break; } case MANAGER_LIST: { - container_ffmpeg_update_tracks(context, context->playback->uri); + container_ffmpeg_update_tracks(context, context->playback->uri, 0); *((char***)argument) = (char **)ManagerList(context); break; } diff --git a/libeplayer3/manager/subtitle.c b/libeplayer3/manager/subtitle.c index fdf7423..0caeb24 100644 --- a/libeplayer3/manager/subtitle.c +++ b/libeplayer3/manager/subtitle.c @@ -36,7 +36,7 @@ #ifdef SUBTITLE_MGR_DEBUG -static short debug_level = 0; +static short debug_level = 20; #define subtitle_mgr_printf(level, x...) do { \ if (debug_level >= level) printf(x); } while (0) @@ -179,7 +179,7 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) { break; } case MANAGER_LIST: { - container_ffmpeg_update_tracks(context, context->playback->uri); + container_ffmpeg_update_tracks(context, context->playback->uri, 0); *((char***)argument) = (char **)ManagerList(context); break; } @@ -191,7 +191,7 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) { break; } case MANAGER_GET_TRACK: { - subtitle_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__); + //subtitle_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__); if ((TrackCount > 0) && (CurrentTrack >=0)) { @@ -220,15 +220,16 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) { break; } case MANAGER_SET: { - int id = *((int*)argument); + int i; + subtitle_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, *((int*)argument)); - subtitle_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, id); - - if (id < TrackCount) - CurrentTrack = id; - else - { - subtitle_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, id); + for (i = 0; i < TrackCount; i++) + if (Tracks[i].Id == *((int*)argument)) { + CurrentTrack = i; + break; + } + if (i == TrackCount) { + subtitle_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, *((int*)argument)); ret = cERR_SUBTITLE_MGR_ERROR; } break; diff --git a/libeplayer3/manager/teletext.c b/libeplayer3/manager/teletext.c index 19f67d5..9bf94a7 100644 --- a/libeplayer3/manager/teletext.c +++ b/libeplayer3/manager/teletext.c @@ -180,7 +180,7 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) { break; } case MANAGER_LIST: { - container_ffmpeg_update_tracks(context, context->playback->uri); + container_ffmpeg_update_tracks(context, context->playback->uri, 0); *((char***)argument) = (char **)ManagerList(context); break; } diff --git a/libeplayer3/manager/video.c b/libeplayer3/manager/video.c index a73c522..c18e647 100644 --- a/libeplayer3/manager/video.c +++ b/libeplayer3/manager/video.c @@ -176,7 +176,7 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) { break; } case MANAGER_LIST: { - container_ffmpeg_update_tracks(context, context->playback->uri); + container_ffmpeg_update_tracks(context, context->playback->uri, 0); *((char***)argument) = (char **)ManagerList(context); break; } diff --git a/libeplayer3/output/writer/framebuffer.c b/libeplayer3/output/writer/framebuffer.c index e304784..c6666b8 100644 --- a/libeplayer3/output/writer/framebuffer.c +++ b/libeplayer3/output/writer/framebuffer.c @@ -100,7 +100,6 @@ static int reset() static int writeData(void* _call) { - unsigned char a; int res = 0; WriterFBCallData_t* call = (WriterFBCallData_t*) _call; @@ -121,51 +120,53 @@ static int writeData(void* _call) if (call->data != NULL) { - unsigned int opacity = 255 - ((unsigned int)_a(call->color)); + unsigned int a = (unsigned int)_a(call->color); unsigned int r = (unsigned int)_r(call->color); unsigned int g = (unsigned int)_g(call->color); - unsigned int b = (unsigned int) _b(call->color); + unsigned int b = (unsigned int)_b(call->color); + unsigned int opacity = 255 - a; int src_stride = call->Stride; int dst_stride = call->destStride; int dst_delta = dst_stride - call->Width*4; unsigned int x,y; const unsigned char *src = call->data; unsigned char *dst = call->destination + (call->y * dst_stride + call->x * 4); +#if 1 // !HAVE_SPARK_HARDWARE + unsigned int k; +#else unsigned int k,ck,t; +#endif 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 %d\n", call->color); + 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); - fb_printf(100, "r 0x%hhx, g 0x%hhx, b 0x%hhx, a 0x%hhx, opacity %d\n", r, g, b, a, opacity); + fb_printf(100, "r 0x%hhx, g 0x%hhx, b 0x%hhx, a 0x%hhx, opacity 0x%hhx\n", r, g, b, a, opacity); for (y=0;yHeight;y++) { for (x = 0; x < call->Width; x++) { - k = ((unsigned)src[x]) * opacity / 255; - ck = 255 - k; -#if HAVE_SPARK_HARDWARE - *dst++ = 0; - t = *dst; - *dst++ = (k*r + ck*t) / 255; - t = *dst; - *dst++ = (k*b + ck*t) / 255; - t = *dst; - *dst++ = (k*g + ck*t) / 255; + k = ((unsigned)src[x]) * opacity / 256; +#if 1 // HAVE_SPARK_HARDWARE + *dst++ = b; + *dst++ = g; + *dst++ = r; + *dst++ = k; #else + ck = 255 - k; t = *dst; - *dst++ = (k*b + ck*t) / 255; + *dst++ = (k*b + ck*t) / 256; t = *dst; - *dst++ = (k*g + ck*t) / 255; + *dst++ = (k*g + ck*t) / 256; t = *dst; - *dst++ = (k*r + ck*t) / 255; + *dst++ = (k*r + ck*t) / 256; *dst++ = 0; #endif } @@ -179,7 +180,7 @@ static int writeData(void* _call) for (y = 0; y < call->Height; y++) memset(call->destination + ((call->y + y) * call->destStride) + call->x * 4, 0, call->Width * 4); } - + fb_printf(100, "< %d\n", res); return res; } diff --git a/libeplayer3/playback/playback.c b/libeplayer3/playback/playback.c index 5291c66..08c8944 100644 --- a/libeplayer3/playback/playback.c +++ b/libeplayer3/playback/playback.c @@ -135,7 +135,7 @@ status = 1; if (count == 200) { - playback_err("something went wrong, expect end but never reached?\n"); +// playback_err("something went wrong, expect end but never reached?\n"); dieNow = 1; } usleep(10000); @@ -830,7 +830,7 @@ static int PlaybackSwitchSubtitle(Context_t *context, int* track) { if (context->manager && context->manager->subtitle) { int trackid; - if (context->manager->subtitle->Command(context, *track == 0xffff ? MANAGER_DEL : MANAGER_SET, track) < 0) + if (context->manager->subtitle->Command(context, MANAGER_SET, track) < 0) { playback_err("manager set track failed\n"); } @@ -896,7 +896,7 @@ static int PlaybackSwitchDVBSubtitle(Context_t *context, int* pid) { playback_err("no dvbsubtitle\n"); if (*pid == 0xffff) - container_ffmpeg_update_tracks(context, context->playback->uri); + container_ffmpeg_update_tracks(context, context->playback->uri, 0); playback_printf(10, "exiting with value %d\n", ret); @@ -917,7 +917,7 @@ static int PlaybackSwitchTeletext(Context_t *context, int* pid) { playback_err("no ttxsubtitle\n"); if (*pid == 0xffff) - container_ffmpeg_update_tracks(context, context->playback->uri); + container_ffmpeg_update_tracks(context, context->playback->uri, 0); playback_printf(10, "exiting with value %d\n", ret);