static void* dvbsub_thread(void* /*arg*/) { struct timespec restartWait; struct timeval now; set_threadname("dvbsub:main"); sub_debug.print(Debug::VERBOSE, "%s started\n", __FUNCTION__); if (!dvbSubtitleConverter) dvbSubtitleConverter = new cDvbSubtitleConverter; int timeout = 1000000; #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE CFrameBuffer *fb = CFrameBuffer::getInstance(); int xres = fb->getScreenWidth(true); int yres = fb->getScreenHeight(true); int clr_x0 = xres, clr_y0 = yres, clr_x1 = 0, clr_y1 = 0; uint32_t colortable[256]; memset(colortable, 0, sizeof(colortable)); uint32_t last_color = 0; #endif while(dvbsub_running) { #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE if (ass_track) { usleep(100000); // FIXME ... should poll instead OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(ass_mutex); if (!ass_track) continue; if (ass_size != sub_font_size) { ass_size = sub_font_size; ass_set_font_scale(ass_renderer, ((double) ass_size)/ASS_CUSTOM_FONT_SIZE); } int detect_change = 0; int64_t pts; getPlayerPts(&pts); ASS_Image *image = ass_render_frame(ass_renderer, ass_track, pts/90, &detect_change); if (detect_change) { if (clr_x1 && clr_y1) { fb->paintBox(clr_x0, clr_y0, clr_x1 + 1, clr_y1 + 1, 0); clr_x0 = xres; clr_y0 = yres; clr_x1 = clr_y1 = 0; } while (image) { if (last_color != image->color) { last_color = image->color; uint32_t c = last_color >> 8, a = 255 - (last_color & 0xff); for (int i = 0; i < 256; i++) { uint32_t k = (a * i) >> 8; colortable[i] = k ? (c | (k << 24)) : 0; } } if (image->w && image->h && image->dst_x > -1 && image->dst_x + image->w < xres && image->dst_y > -1 && image->dst_y + image->h < yres) { if (image->dst_x < clr_x0) clr_x0 = image->dst_x; if (image->dst_y < clr_y0) clr_y0 = image->dst_y; if (image->dst_x + image->w > clr_x1) clr_x1 = image->dst_x + image->w; if (image->dst_y + image->h > clr_y1) clr_y1 = image->dst_y + image->h; uint32_t *lfb = fb->getFrameBufferPointer() + image->dst_x + xres * image->dst_y; unsigned char *bm = image->bitmap; int bm_add = image->stride - image->w; int lfb_add = xres - image->w; for (int y = 0; y < image->h; y++) { for (int x = 0; x < image->w; x++) { if (*bm) *lfb = colortable[*bm]; lfb++, bm++; } lfb += lfb_add; bm += bm_add; } } image = image->next; } fb->getInstance()->blit(); } continue; } else { if (clr_x1 && clr_y1) {
static void *ass_reader_thread(void *) { set_threadname("ass_reader_thread"); while (!sem_wait(&ass_sem)) { if (!ass_reader_running) break; ass_data *a = (ass_data *) ass_queue.pop(); if (!a) { if (!ass_reader_running) break; continue; } OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(ass_mutex); std::map<int,ASS_Track*>::iterator it = ass_map.find(a->pid); ASS_Track *track; if (it == ass_map.end()) { CFrameBuffer *fb = CFrameBuffer::getInstance(); int xres = fb->getScreenWidth(true); int yres = fb->getScreenHeight(true); if (!ass_library) { ass_library = ass_library_init(); ass_set_extract_fonts(ass_library, 1); ass_set_style_overrides(ass_library, NULL); ass_renderer = ass_renderer_init(ass_library); ass_set_frame_size(ass_renderer, xres, yres); ass_set_margins(ass_renderer, 3 * yres / 100, 3 * yres / 100, 3 * xres / 100, 3 * xres / 100); ass_set_use_margins(ass_renderer, 1); ass_set_hinting(ass_renderer, ASS_HINTING_LIGHT); ass_set_aspect_ratio(ass_renderer, 1.0, 1.0); ass_font = *sub_font_file; ass_set_fonts(ass_renderer, ass_font.c_str(), "Arial", 0, NULL, 1); } track = ass_new_track(ass_library); track->PlayResX = xres; track->PlayResY = yres; ass_size = sub_font_size; ass_set_font_scale(ass_renderer, ((double) ass_size)/ASS_CUSTOM_FONT_SIZE); if (a->c->subtitle_header) { std::string ass_hdr = ass_subtitle_header_default(); if (ass_hdr.compare((char*) a->c->subtitle_header)) { ass_process_codec_private(track, (char *) a->c->subtitle_header, a->c->subtitle_header_size); } else { // This is the FFMPEG default ASS header. Use something more suitable instead: ass_hdr = ass_subtitle_header_custom(); ass_process_codec_private(track, (char *) ass_hdr.c_str(), ass_hdr.length()); } } ass_map[a->pid] = track; if (a->pid == dvbsub_pid) ass_track = track; //fprintf(stderr, "### got subtitle track %d, subtitle header: \n---\n%s\n---\n", pid, c->subtitle_header); } else track = it->second; for (unsigned int i = 0; i < a->sub.num_rects; i++) if (a->sub.rects[i]->ass) ass_process_data(track, a->sub.rects[i]->ass, strlen(a->sub.rects[i]->ass)); avsubtitle_free(&a->sub); delete a; } ass_reader_running = false; pthread_exit(NULL); }