From eace70f1c1c7ba7339713666a76213acf1125202 Mon Sep 17 00:00:00 2001 From: Tuomas Virtanen Date: Mon, 15 Jan 2018 20:04:09 +0200 Subject: Dump reorganized code --- src/internal/subtitle/renderers/kitsubass.c | 188 +++++++++++++++++++++++ src/internal/subtitle/renderers/kitsubimage.c | 51 ++++++ src/internal/subtitle/renderers/kitsubrenderer.c | 32 ++++ 3 files changed, 271 insertions(+) create mode 100644 src/internal/subtitle/renderers/kitsubass.c create mode 100644 src/internal/subtitle/renderers/kitsubimage.c create mode 100644 src/internal/subtitle/renderers/kitsubrenderer.c (limited to 'src/internal/subtitle/renderers') diff --git a/src/internal/subtitle/renderers/kitsubass.c b/src/internal/subtitle/renderers/kitsubass.c new file mode 100644 index 0000000..d0c5a80 --- /dev/null +++ b/src/internal/subtitle/renderers/kitsubass.c @@ -0,0 +1,188 @@ +#include +#include + +#include +#include + +#include "kitchensink/kiterror.h" +#include "kitchensink/internal/kitlibstate.h" +#include "kitchensink/internal/utils/kithelpers.h" +#include "kitchensink/internal/subtitle/renderers/kitsubass.h" + +// For compatibility +#ifndef ASS_FONTPROVIDER_AUTODETECT +#define ASS_FONTPROVIDER_AUTODETECT 1 +#endif + +typedef struct Kit_ASSSubtitleRenderer { + ASS_Renderer *renderer; + ASS_Track *track; +} Kit_ASSSubtitleRenderer; + +static void _ProcessAssImage(SDL_Surface *surface, const ASS_Image *img) { + unsigned char r = ((img->color) >> 24) & 0xFF; + unsigned char g = ((img->color) >> 16) & 0xFF; + unsigned char b = ((img->color) >> 8) & 0xFF; + unsigned char a = (img->color) & 0xFF; + unsigned char *src = img->bitmap; + unsigned char *dst = surface->pixels; + unsigned int an, ao, x, y, x_off; + dst += img->dst_y * surface->pitch; + + for(y = 0; y < img->h; y++) { + for(x = 0; x < img->w; x++) { + x_off = (img->dst_x + x) * 4; + an = ((255 - a) * src[x]) >> 8; // New alpha + ao = dst[x_off + 3]; // Original alpha + if(ao == 0) { + dst[x_off + 0] = r; + dst[x_off + 1] = g; + dst[x_off + 2] = b; + dst[x_off + 3] = an; + } else { + dst[x_off + 3] = 255 - (255 - dst[x_off + 3]) * (255 - an) / 255; + if(dst[x_off + 3] != 0) { + dst[x_off + 0] = (dst[x_off + 0] * ao * (255-an) / 255 + r * an ) / dst[x_off + 3]; + dst[x_off + 1] = (dst[x_off + 1] * ao * (255-an) / 255 + g * an ) / dst[x_off + 3]; + dst[x_off + 2] = (dst[x_off + 2] * ao * (255-an) / 255 + b * an ) / dst[x_off + 3]; + } + } + } + src += img->stride; + dst += surface->pitch; + } +} + +static int ren_render_ass_cb(Kit_SubtitleRenderer *ren, void *src, double start_pts, void *dst) { + assert(ren != NULL); + assert(src != NULL); + assert(dst != NULL); + + Kit_ASSSubtitleRenderer *ass_ren = ren->userdata; + AVSubtitle *sub = src; + SDL_Surface *surface = dst; + unsigned int now = start_pts * 1000; + int change = 0; + + // Read incoming subtitle packets to libASS + for(int r = 0; r < sub->num_rects; r++) { + if(sub->rects[r]->ass == NULL) + continue; + ass_process_data(ass_ren->track, sub->rects[r]->ass, strlen(sub->rects[r]->ass)); + } + + // Ask libass to render frames. If there are no changes since last render, stop here. + ASS_Image *image = ass_render_frame(ass_ren->renderer, ass_ren->track, now, &change); + if(change <= 0) { + return -1; + } + + for(; image; image = image->next) { + if(image->w == 0 || image->h == 0) + continue; + _ProcessAssImage(surface, image); + } + + // We tell subtitle handler to clear output before adding this frame. + return 0; +} + +static void ren_close_ass_cb(Kit_SubtitleRenderer *ren) { + if(ren == NULL) return; + + Kit_ASSSubtitleRenderer *ass_ren = ren->userdata; + ass_renderer_done(ass_ren->renderer); + free(ass_ren); +} + +Kit_SubtitleRenderer* Kit_CreateASSSubtitleRenderer(const Kit_Decoder *dec, int w, int h) { + assert(dec != NULL); + assert(w >= 0); + assert(h >= 0); + + // Make sure that libass library has been initialized + get handle + Kit_LibraryState *state = Kit_GetLibraryState(); + if(state->libass_handle == NULL) { + Kit_SetError("Libass library has not been initialized"); + return NULL; + } + + // First allocate the generic decoder component + Kit_SubtitleRenderer *ren = Kit_CreateSubtitleRenderer(); + if(ren == NULL) { + goto exit_0; + } + + // Next, allocate ASS subtitle renderer context. + Kit_ASSSubtitleRenderer *ass_ren = calloc(1, sizeof(Kit_ASSSubtitleRenderer)); + if(ass_ren == NULL) { + goto exit_1; + } + + // Initialize libass renderer + ASS_Renderer *ass_renderer = ass_renderer_init(state->libass_handle); + if(ass_renderer == NULL) { + Kit_SetError("Unable to initialize libass renderer"); + goto exit_2; + } + + // Read fonts from attachment streams and give them to libass + for(int j = 0; j < dec->format_ctx->nb_streams; j++) { + AVStream *st = dec->format_ctx->streams[j]; + if(st->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT && attachment_is_font(st)) { + const AVDictionaryEntry *tag = av_dict_get( + st->metadata, + "filename", + NULL, + AV_DICT_MATCH_CASE); + if(tag) { + ass_add_font( + state->libass_handle, + tag->value, + (char*)st->codec->extradata, + st->codec->extradata_size); + } + } + } + + // Init libass fonts and window frame size + ass_set_fonts( + ass_renderer, + NULL, "sans-serif", + ASS_FONTPROVIDER_AUTODETECT, + NULL, 1); + ass_set_frame_size(ass_renderer, w, h); + ass_set_hinting(ass_renderer, ASS_HINTING_NONE); + + // Initialize libass track + ASS_Track *ass_track = ass_new_track(state->libass_handle); + if(ass_track == NULL) { + Kit_SetError("Unable to initialize libass track"); + goto exit_3; + } + + // Set up libass track headers (ffmpeg provides these) + if(dec->codec_ctx->subtitle_header) { + ass_process_codec_private( + ass_track, + (char*)dec->codec_ctx->subtitle_header, + dec->codec_ctx->subtitle_header_size); + } + + // Set callbacks and userdata, and we're go + ass_ren->renderer = ass_renderer; + ass_ren->track = ass_track; + ren->ren_render = ren_render_ass_cb; + ren->ren_close = ren_close_ass_cb; + ren->userdata = ass_ren; + return ren; + +exit_3: + ass_renderer_done(ass_renderer); +exit_2: + free(ass_ren); +exit_1: + Kit_CloseSubtitleRenderer(ren); +exit_0: + return NULL; +} diff --git a/src/internal/subtitle/renderers/kitsubimage.c b/src/internal/subtitle/renderers/kitsubimage.c new file mode 100644 index 0000000..15a7432 --- /dev/null +++ b/src/internal/subtitle/renderers/kitsubimage.c @@ -0,0 +1,51 @@ +#include "kitchensink/internal/subtitle/renderers/kitsubimage.h" + +int filler() { return 0; } + +/* +void _HandleBitmapSubtitle(Kit_SubtitlePacket** spackets, int *n, Kit_Player *player, double pts, AVSubtitle *sub, AVSubtitleRect *rect) { + if(rect->nb_colors == 256) { + // Paletted image based subtitles. Convert and set palette. + SDL_Surface *s = SDL_CreateRGBSurfaceFrom( + rect->data[0], + rect->w, rect->h, 8, + rect->linesize[0], + 0, 0, 0, 0); + + SDL_SetPaletteColors(s->format->palette, (SDL_Color*)rect->data[1], 0, 256); + + Uint32 rmask, gmask, bmask, amask; + #if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; + gmask = 0x00ff0000; + bmask = 0x0000ff00; + amask = 0x000000ff; + #else + rmask = 0x000000ff; + gmask = 0x0000ff00; + bmask = 0x00ff0000; + amask = 0xff000000; + #endif + SDL_Surface *tmp = SDL_CreateRGBSurface( + 0, rect->w, rect->h, 32, + rmask, gmask, bmask, amask); + SDL_BlitSurface(s, NULL, tmp, NULL); + SDL_FreeSurface(s); + + SDL_Rect *dst_rect = malloc(sizeof(SDL_Rect)); + dst_rect->x = rect->x; + dst_rect->y = rect->y; + dst_rect->w = rect->w; + dst_rect->h = rect->h; + + double start = pts + (sub->start_display_time / 1000.0f); + double end = -1; + if(sub->end_display_time < UINT_MAX) { + end = pts + (sub->end_display_time / 1000.0f); + } + + spackets[(*n)++] = _CreateSubtitlePacket(start, end, dst_rect, tmp); + } +} + +*/ \ No newline at end of file diff --git a/src/internal/subtitle/renderers/kitsubrenderer.c b/src/internal/subtitle/renderers/kitsubrenderer.c new file mode 100644 index 0000000..f7f95a7 --- /dev/null +++ b/src/internal/subtitle/renderers/kitsubrenderer.c @@ -0,0 +1,32 @@ +#include +#include + +#include "kitchensink/kiterror.h" +#include "kitchensink/internal/subtitle/renderers/kitsubrenderer.h" + + +Kit_SubtitleRenderer* Kit_CreateSubtitleRenderer() { + // Allocate renderer and make sure allocation was a success + Kit_SubtitleRenderer *ren = calloc(1, sizeof(Kit_SubtitleRenderer)); + if(ren == NULL) { + Kit_SetError("Unable to allocate kit subtitle renderer"); + return NULL; + } + return ren; +} + +int Kit_RunSubtitleRenderer(Kit_SubtitleRenderer *ren, void *src, double start_pts, void *surface) { + if(ren == NULL) + return 1; + if(ren->ren_render != NULL) + return ren->ren_render(ren, src, start_pts, surface); + return 1; +} + +void Kit_CloseSubtitleRenderer(Kit_SubtitleRenderer *ren) { + if(ren == NULL) + return; + if(ren->ren_close != NULL) + ren->ren_close(ren); + free(ren); +} -- cgit v1.2.3