cDvbSubtitleConverter::cDvbSubtitleConverter(void) { dbgconverter("cDvbSubtitleConverter: new converter\n"); bitmaps = new cList<cDvbSubtitleBitmaps>; pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); pthread_mutex_init(&mutex, &attr); running = false; avctx = NULL; avcodec = NULL; avcodec_register_all(); avcodec = avcodec_find_decoder(CODEC_ID_DVB_SUBTITLE); if (!avcodec) { dbgconverter("cDvbSubtitleConverter: unable to get dvb subtitle codec!\n"); return; } avctx = avcodec_alloc_context(); if (avcodec_open(avctx, avcodec) < 0) dbgconverter("cDvbSubtitleConverter: unable to open codec !\n"); av_log_set_level(99); if(DebugConverter) av_log_set_level(AV_LOG_INFO); min_x = CFrameBuffer::getInstance()->getScreenWidth(); min_y = CFrameBuffer::getInstance()->getScreenHeight(); max_x = CFrameBuffer::getInstance()->getScreenX(); max_y = CFrameBuffer::getInstance()->getScreenY(); Timeout.Set(0xFFFF*1000); }
void cDvbSubtitleBitmaps::Draw(int &min_x, int &min_y, int &max_x, int &max_y) { int i; int stride = CFrameBuffer::getInstance()->getScreenWidth(true); int wd = CFrameBuffer::getInstance()->getScreenWidth(); int xstart = CFrameBuffer::getInstance()->getScreenX(); int yend = CFrameBuffer::getInstance()->getScreenY() + CFrameBuffer::getInstance()->getScreenHeight(); //int ystart = CFrameBuffer::getInstance()->getScreenY(); //uint32_t *sublfb = CFrameBuffer::getInstance()->getFrameBufferPointer(); dbgconverter("cDvbSubtitleBitmaps::Draw: %d bitmaps, x= %d, width= %d yend=%d stride %d\n", Count(), xstart, wd, yend, stride); int sw = CFrameBuffer::getInstance()->getScreenWidth(true); int sh = CFrameBuffer::getInstance()->getScreenHeight(true); for (i = 0; i < Count(); i++) { //NOTE remove me //printf("color:%d width:%d height:%d at x:%d y:%d\n", sub.rects[i]->nb_colors, sub.rects[i]->w, sub.rects[i]->h, sub.rects[i]->x, sub.rects[i]->y); uint32_t * colors = (uint32_t *) sub.rects[i]->pict.data[1]; int width = sub.rects[i]->w; int height = sub.rects[i]->h; int h2 = (width == 1280) ? 720 : 576; int xoff = sub.rects[i]->x * sw / width; int yoff = sub.rects[i]->y * sh / h2; int nw = width * sw / width; int nh = height * sh / h2; dbgconverter("cDvbSubtitleBitmaps::Draw: #%d at %d,%d size %dx%d colors %d (x=%d y=%d w=%d h=%d) \n", i+1, sub.rects[i]->x, sub.rects[i]->y, sub.rects[i]->w, sub.rects[i]->h, sub.rects[i]->nb_colors, xoff, yoff, nw, nh); // resize color to 32 bit fb_pixel_t * newdata = simple_resize32(sub.rects[i]->pict.data[0], colors, sub.rects[i]->nb_colors, width, height, nw, nh); // blit2fb CFrameBuffer::getInstance()->blit2FB(newdata, nw, nh, xoff, yoff, 0, 0, true); free(newdata); // recalculate min_x min_y max_x max_y if(min_x > xoff) min_x = xoff; if(min_y > yoff) min_y = yoff; if(max_x < (xoff + nw)) max_x = xoff + nw; if(max_y < (yoff + nh)) max_y = yoff + nh; } if(Count()) dbgconverter("cDvbSubtitleBitmaps::Draw: finish, min/max screen: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); dbgconverter("\n"); }
int cDvbSubtitleConverter::Action(void) { int WaitMs = WAITMS; if (!running) return 0; if(!avctx) { dbgconverter("cDvbSubtitleConverter::Action: no context\n"); return -1; } Lock(); if (cDvbSubtitleBitmaps *sb = bitmaps->First()) { int64_t STC; dvbsub_get_stc(&STC); int64_t Delta = 0; Delta = LimitTo32Bit(sb->Pts()) - LimitTo32Bit(STC); Delta /= 90; // STC and PTS are in 1/90000s dbgconverter("cDvbSubtitleConverter::Action: PTS: %lld STC: %lld (%lld) timeout: %d\n", sb->Pts(), STC, Delta, sb->Timeout()); if (Delta <= MAXDELTA) { if (Delta <= SHOW_DELTA) { dbgconverter("cDvbSubtitleConverter::Action: Got %d bitmaps, showing #%d\n", bitmaps->Count(), sb->Index() + 1); if (running) { Clear(); sb->Draw(min_x, min_y, max_x, max_y); Timeout.Set(sb->Timeout()); } if(sb->Count()) WaitMs = MIN_DISPLAY_TIME; bitmaps->Del(sb, true); } else if (Delta < WaitMs) WaitMs = (Delta > SHOW_DELTA) ? Delta - SHOW_DELTA : Delta; } else bitmaps->Del(sb, true); } else { if (Timeout.TimedOut()) { dbgconverter("cDvbSubtitleConverter::Action: timeout, elapsed %lld\n", Timeout.Elapsed()); Clear(); Timeout.Set(0xFFFF*1000); } } Unlock(); if(WaitMs != WAITMS) dbgconverter("cDvbSubtitleConverter::Action: finish, WaitMs %d\n", WaitMs); return WaitMs*1000; }
int cDvbSubtitleConverter::Convert(const uchar *Data, int Length, int64_t pts) { AVPacket avpkt; int got_subtitle = 0; static cDvbSubtitleBitmaps *Bitmaps = NULL; if(!avctx) { dbgconverter("cDvbSubtitleConverter::Convert: no context\n"); return -1; } if(Bitmaps == NULL) Bitmaps = new cDvbSubtitleBitmaps(pts); AVSubtitle * sub = Bitmaps->GetSub(); av_init_packet(&avpkt); avpkt.data = (uint8_t*) Data; avpkt.size = Length; dbgconverter("cDvbSubtitleConverter::Convert: sub %x pkt %x pts %lld\n", sub, &avpkt, pts); //avctx->sub_id = (anc_page << 16) | comp_page; //FIXME not patched ffmpeg needs this ! #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 64, 0) avcodec_decode_subtitle2(avctx, sub, &got_subtitle, &avpkt); #else avcodec_decode_subtitle(avctx, sub, &got_subtitle, avpkt.data, avpkt.size); #endif dbgconverter("cDvbSubtitleConverter::Convert: pts %lld subs ? %s, %d bitmaps\n", pts, got_subtitle? "yes" : "no", sub->num_rects); if(got_subtitle) { if(DebugConverter) { unsigned int i; for(i = 0; i < sub->num_rects; i++) { dbgconverter("cDvbSubtitleConverter::Convert: #%d at %d,%d size %d x %d colors %d\n", i+1, sub->rects[i]->x, sub->rects[i]->y, sub->rects[i]->w, sub->rects[i]->h, sub->rects[i]->nb_colors); } } bitmaps->Add(Bitmaps); Bitmaps = NULL; } return 0; }
int cDvbSubtitleConverter::Convert(const uchar *Data, int Length) { if (Data && Length > 8) { int PayloadOffset = PesPayloadOffset(Data); if (Length > PayloadOffset) { int64_t pts = PesGetPts(Data); if (pts) dbgconverter("Converter PTS: %"PRId64"\n", pts); const uchar *data = Data + PayloadOffset; int length = Length - PayloadOffset; if (length > 3) { if (data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F) { data += 2; length -= 2; } const uchar *b = data; while (length > 0) { if (b[0] == 0x0F) { int n = ExtractSegment(b, length, pts); if (n < 0) break; b += n; length -= n; } else break; } } } return Length; } return 0; }
void cDvbSubtitleConverter::Clear(void) { dbgconverter("cDvbSubtitleConverter::Clear: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); if(running && (max_x-min_x > 0) && (max_y-min_y > 0)) { CFrameBuffer::getInstance()->paintBackgroundBoxRel (min_x, min_y, max_x-min_x, max_y-min_y); //CFrameBuffer::getInstance()->paintBackground(); } }
void cDvbSubtitleConverter::Reset(void) { dbgconverter("Converter reset -----------------------\n"); Lock(); bitmaps->Clear(); Unlock(); Timeout.Set(0xFFFF*1000); }
void cDvbSubtitleConverter::Action(void) { int LastSetupLevel = setupLevel; cTimeMs Timeout; while (Running()) { int WaitMs = 100; if (!frozen) { LOCK_THREAD; if (osd) { int NewSetupLevel = setupLevel; if (Timeout.TimedOut() || LastSetupLevel != NewSetupLevel) { DELETENULL(osd); } LastSetupLevel = NewSetupLevel; } if (cDvbSubtitleBitmaps *sb = bitmaps->First()) { int64_t STC = cDevice::PrimaryDevice()->GetSTC(); int64_t Delta = LimitTo32Bit(sb->Pts()) - LimitTo32Bit(STC); // some devices only deliver 32 bits if (Delta > (int64_t(1) << 31)) Delta -= (int64_t(1) << 32); else if (Delta < -((int64_t(1) << 31) - 1)) Delta += (int64_t(1) << 32); Delta /= 90; // STC and PTS are in 1/90000s if (Delta <= MAXDELTA) { if (Delta <= 0) { dbgconverter("Got %d bitmaps, showing #%d\n", bitmaps->Count(), sb->Index() + 1); if (AssertOsd()) { sb->Draw(osd); Timeout.Set(sb->Timeout() * 1000); dbgconverter("PTS: %"PRId64" STC: %"PRId64" (%"PRId64") timeout: %d\n", sb->Pts(), cDevice::PrimaryDevice()->GetSTC(), Delta, sb->Timeout()); } bitmaps->Del(sb); } else if (Delta < WaitMs) WaitMs = Delta; } else bitmaps->Del(sb); } } cCondWait::SleepMs(WaitMs); } }
void cDvbSubtitleConverter::Clear(void) { dbgconverter("cDvbSubtitleConverter::Clear: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x - min_x, max_y - min_y); if(running && (max_x - min_x > 0) && (max_y - min_y > 0)) { CFrameBuffer::getInstance()->paintBackgroundBoxRel (min_x, min_y, max_x - min_x, max_y-min_y); #if !defined USE_OPENGL CFrameBuffer::getInstance()->blit(); #endif } }
cDvbSubtitleConverter::cDvbSubtitleConverter(void) { dbgconverter("cDvbSubtitleConverter: new converter\n"); bitmaps = new cList<cDvbSubtitleBitmaps>; pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); pthread_mutex_init(&mutex, &attr); running = false; #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE painted = false; #endif avctx = NULL; avcodec = NULL; avcodec_register_all(); avcodec = avcodec_find_decoder(CODEC_DVB_SUB);//CODEC_ID_DVB_SUBTITLE or AV_CODEC_ID_DVB_SUBTITLE from 57.1.100 if (!avcodec) { dbgconverter("cDvbSubtitleConverter: unable to get dvb subtitle codec!\n"); return; } avctx = avcodec_alloc_context3(avcodec); if (avcodec_open2(avctx, avcodec, NULL) < 0) dbgconverter("cDvbSubtitleConverter: unable to open codec !\n"); av_log_set_level(AV_LOG_PANIC); //if(DebugConverter) // av_log_set_level(AV_LOG_INFO); screen_w = min_x = CFrameBuffer::getInstance()->getScreenWidth(); screen_h = min_y = CFrameBuffer::getInstance()->getScreenHeight(); screen_x = max_x = CFrameBuffer::getInstance()->getScreenX(); screen_y = max_y = CFrameBuffer::getInstance()->getScreenY(); Timeout.Set(0xFFFF*1000); }
void cDvbSubtitleConverter::Clear(void) { #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE if (running && painted) { CFrameBuffer::getInstance()->Clear(); painted = false; } #else dbgconverter("cDvbSubtitleConverter::Clear: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); if(running && (max_x-min_x > 0) && (max_y-min_y > 0)) { CFrameBuffer::getInstance()->paintBackgroundBoxRel (min_x, min_y, max_x-min_x, max_y-min_y); //CFrameBuffer::getInstance()->paintBackground(); } #endif }
void cDvbSubtitleConverter::Reset(void) { dbgconverter("Converter reset -----------------------\n"); dvbSubtitleAssembler->Reset(); Lock(); pages->Clear(); bitmaps->Clear(); DELETENULL(osd); frozen = false; ddsVersionNumber = -1; displayWidth = windowWidth = 720; displayHeight = windowHeight = 576; windowHorizontalOffset = 0; windowVerticalOffset = 0; Unlock(); }
void cDvbSubtitleConverter::Pause(bool pause) { dbgconverter("cDvbSubtitleConverter::Pause: %s\n", pause ? "pause" : "resume"); if(pause) { if(!running) return; Lock(); Clear(); running = false; Unlock(); //Reset(); } else { //Reset(); running = true; } }
cDvbSubtitleBitmaps::~cDvbSubtitleBitmaps() { dbgconverter("cDvbSubtitleBitmaps::delete: PTS: %lld rects %d\n", pts, Count()); int i; if(sub.rects) { for (i = 0; i < Count(); i++) { av_freep(&sub.rects[i]->pict.data[0]); av_freep(&sub.rects[i]->pict.data[1]); av_freep(&sub.rects[i]); } av_free(sub.rects); } memset(&sub, 0, sizeof(AVSubtitle)); }
int cDvbSubtitleConverter::ConvertFragments(const uchar *Data, int Length) { if (Data && Length > 8) { int PayloadOffset = PesPayloadOffset(Data); int SubstreamHeaderLength = 4; bool ResetSubtitleAssembler = Data[PayloadOffset + 3] == 0x00; // Compatibility mode for old subtitles plugin: if ((Data[7] & 0x01) && (Data[PayloadOffset - 3] & 0x81) == 0x01 && Data[PayloadOffset - 2] == 0x81) { PayloadOffset--; SubstreamHeaderLength = 1; ResetSubtitleAssembler = Data[8] >= 5; } if (Length > PayloadOffset + SubstreamHeaderLength) { int64_t pts = PesHasPts(Data) ? PesGetPts(Data) : 0; if (pts) dbgconverter("Converter PTS: %"PRId64"\n", pts); const uchar *data = Data + PayloadOffset + SubstreamHeaderLength; // skip substream header int length = Length - PayloadOffset - SubstreamHeaderLength; // skip substream header if (ResetSubtitleAssembler) dvbSubtitleAssembler->Reset(); if (length > 3) { if (data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F) dvbSubtitleAssembler->Put(data + 2, length - 2); else dvbSubtitleAssembler->Put(data, length); int Count; while (true) { unsigned char *b = dvbSubtitleAssembler->Get(Count); if (b && b[0] == 0x0F) { if (ExtractSegment(b, Count, pts) == -1) break; } else break; } } } return Length; } return 0; }
void cDvbSubtitleConverter::Pause(bool pause) { dbgconverter("cDvbSubtitleConverter::Pause: %s\n", pause ? "pause" : "resume"); if(pause) { if(!running) return; Lock(); Clear(); running = false; Unlock(); //Reset(); } else { // Assume that we've switched channel. Drop the existing display_definition. avctx->width = 0; avctx->height = 0; //Reset(); running = true; } }
cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int64_t pPts) { dbgconverter("cDvbSubtitleBitmaps::new: PTS: %lld\n", pts); pts = pPts; }
int cDvbSubtitleConverter::Action(void) { int WaitMs = WAITMS; if (!running) return 0; if(!avctx) { dbgconverter("cDvbSubtitleConverter::Action: no context\n"); return -1; } min_x = min_y = 0; max_x = 720; max_y = 576; if (avctx->width && avctx->height) { min_x = 0; min_y = 0; max_x = avctx->width; max_y = avctx->height; dbgconverter("cDvbSubtitleConverter::Action: Display Definition: min_x=%d min_y=%d max_x=%d max_y=%d\n", min_x, min_y, max_x, max_y); } Lock(); if (cDvbSubtitleBitmaps *sb = bitmaps->First()) { int64_t STC; dvbsub_get_stc(&STC); int64_t Delta = 0; Delta = LimitTo32Bit(sb->Pts()) - LimitTo32Bit(STC); Delta /= 90; // STC and PTS are in 1/90000s // dbgconverter("cDvbSubtitleConverter::Action: PTS: %016llx STC: %016llx (%lld) timeout: %d\n", sb->Pts(), STC, Delta, sb->Timeout()); if (Delta <= MAXDELTA) { if (Delta <= SHOW_DELTA) { dbgconverter("cDvbSubtitleConverter::Action: PTS: %012llx STC: %012llx (%lld) timeout: %d bmp %d/%d\n", sb->Pts(), STC, Delta, sb->Timeout(), bitmaps->Count(), sb->Index() + 1); // dbgconverter("cDvbSubtitleConverter::Action: Got %d bitmaps, showing #%d\n", bitmaps->Count(), sb->Index() + 1); if (running) { Clear(); sb->Draw(min_x, min_y, max_x, max_y); Timeout.Set(sb->Timeout()); } if(sb->Count()) { WaitMs = MIN_DISPLAY_TIME; #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE painted = true; #endif } bitmaps->Del(sb, true); } else if (Delta < WaitMs) WaitMs = int((Delta > SHOW_DELTA) ? Delta - SHOW_DELTA : Delta); } else { dbgconverter("deleted because delta (%lld) > MAXDELTA (%d)\n", Delta, MAXDELTA); bitmaps->Del(sb, true); } } else { if (Timeout.TimedOut()) { dbgconverter("cDvbSubtitleConverter::Action: timeout, elapsed %lld\n", Timeout.Elapsed()); Clear(); Timeout.Set(0xFFFF*1000); } } Unlock(); if(WaitMs != WAITMS) dbgconverter("cDvbSubtitleConverter::Action: finish, WaitMs %d\n", WaitMs); return WaitMs*1000; }
void cDvbSubtitleBitmaps::Draw(int &min_x, int &min_y, int &max_x, int &max_y) { #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE #define DEFAULT_XRES 1280 // backbuffer width #define DEFAULT_YRES 720 // backbuffer height if (!Count()) return; dbgconverter("cDvbSubtitleBitmaps::%s: start\n", __func__); CFrameBuffer* fb = CFrameBuffer::getInstance(); fb_pixel_t *b = fb->getBackBufferPointer(); // HACK. When having just switched channels we may not yet have yet // received valid authoring data. This check triggers for the most // common HD subtitle format and sets our authoring display format // accordingly. Plus, me may not get the authoring data at all, e.g. for // blu-ray playback. if (max_x == 720 && max_y == 576) switch (sub.rects[0]->w) { case 1280: min_x = min_y = 0, max_x = 1280, max_y = 720; break; case 1920: min_x = min_y = 0, max_x = 1920, max_y = 1080; break; } for (int i = 0; i < Count(); i++) { uint32_t * colors = (uint32_t *) sub.rects[i]->pict.data[1]; int width = sub.rects[i]->w; int height = sub.rects[i]->h; uint8_t *origin = sub.rects[i]->pict.data[0]; int nb_colors = sub.rects[i]->nb_colors; size_t bs = width * height; for (unsigned int j = 0; j < bs; j++) if (origin[j] < nb_colors) b[j] = colors[origin[j]]; int width_new = (width * DEFAULT_XRES) / max_x; int height_new = (height * DEFAULT_YRES) / max_y; int x_new = (sub.rects[i]->x * DEFAULT_XRES) / max_x; int y_new = (sub.rects[i]->y * DEFAULT_YRES) / max_y; dbgconverter("cDvbSubtitleBitmaps::Draw: original bitmap=%d x=%d y=%d, w=%d, h=%d col=%d\n", i, sub.rects[i]->x, sub.rects[i]->y, width, height, sub.rects[i]->nb_colors); dbgconverter("cDvbSubtitleBitmaps::Draw: scaled bitmap=%d x_new=%d y_new=%d, w_new=%d, h_new=%d\n", i, x_new, y_new, width_new, height_new); fb->blitArea(width, height, x_new, y_new, width_new, height_new); } if (Count()) fb->blit(); dbgconverter("cDvbSubtitleBitmaps::%s: done\n", __func__); #else int i; int stride = CFrameBuffer::getInstance()->getScreenWidth(true); int wd = CFrameBuffer::getInstance()->getScreenWidth(); int xstart = CFrameBuffer::getInstance()->getScreenX(); int yend = CFrameBuffer::getInstance()->getScreenY() + CFrameBuffer::getInstance()->getScreenHeight(); int ystart = CFrameBuffer::getInstance()->getScreenY(); uint32_t *sublfb = CFrameBuffer::getInstance()->getFrameBufferPointer(); dbgconverter("cDvbSubtitleBitmaps::Draw: %d bitmaps, x= %d, width= %d yend=%d stride %d\n", Count(), xstart, wd, yend, stride); double xc = (double) CFrameBuffer::getInstance()->getScreenWidth(true)/(double) 720; double yc = (double) CFrameBuffer::getInstance()->getScreenHeight(true)/(double) 576; xc = yc; //FIXME should we scale also to full width ? int xf = int(xc * (double) 720); for (i = 0; i < Count(); i++) { #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 5, 0) uint32_t * colors = (uint32_t *) sub.rects[i]->pict.data[1]; #else uint32_t * colors = (uint32_t *) sub.rects[i]->data[1]; #endif int width = sub.rects[i]->w; int height = sub.rects[i]->h; int xoff, yoff; int nw = int(width == 1280 ? ((double) width / xc) : ((double) width * xc)); int nh = int((double) height * yc); int xdiff = (wd > xf) ? ((wd - xf) / 2) : 0; xoff = int(sub.rects[i]->x*xc + xstart + xdiff); if(sub.rects[i]->y < 576/2) { yoff = int(ystart + sub.rects[i]->y*yc); } else { yoff = int(yend - ((width == 1280 ? 704:576) - (double) (sub.rects[i]->y + height))*yc - nh); if(yoff < ystart) yoff = ystart; } dbgconverter("cDvbSubtitleBitmaps::Draw: #%d at %d,%d size %dx%d colors %d (x=%d y=%d w=%d h=%d) \n", i+1, sub.rects[i]->x, sub.rects[i]->y, sub.rects[i]->w, sub.rects[i]->h, sub.rects[i]->nb_colors, xoff, yoff, nw, nh); #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 5, 0) fb_pixel_t * newdata = simple_resize32 (sub.rects[i]->pict.data[0], colors, sub.rects[i]->nb_colors, width, height, nw, nh); #else fb_pixel_t * newdata = simple_resize32 (sub.rects[i]->data[0], colors, sub.rects[i]->nb_colors, width, height, nw, nh); #endif fb_pixel_t * ptr = newdata; for (int y2 = 0; y2 < nh; y2++) { int y = (yoff + y2) * stride; for (int x2 = 0; x2 < nw; x2++) *(sublfb + xoff + x2 + y) = *ptr++; } free(newdata); if(min_x > xoff) min_x = xoff; if(min_y > yoff) min_y = yoff; if(max_x < (xoff + nw)) max_x = xoff + nw; if(max_y < (yoff + nh)) max_y = yoff + nh; } if(Count()) dbgconverter("cDvbSubtitleBitmaps::Draw: finish, min/max screen: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); dbgconverter("\n"); #endif }
void cDvbSubtitleBitmaps::Draw(int &min_x, int &min_y, int &max_x, int &max_y) { int i; int stride = CFrameBuffer::getInstance()->getScreenWidth(true); int wd = CFrameBuffer::getInstance()->getScreenWidth(); int xstart = CFrameBuffer::getInstance()->getScreenX(); int yend = CFrameBuffer::getInstance()->getScreenY() + CFrameBuffer::getInstance()->getScreenHeight(); int ystart = CFrameBuffer::getInstance()->getScreenY(); uint32_t *sublfb = CFrameBuffer::getInstance()->getFrameBufferPointer(); dbgconverter("cDvbSubtitleBitmaps::Draw: %d bitmaps, x= %d, width= %d yend=%d stride %d\n", Count(), xstart, wd, yend, stride); double xc = (double) CFrameBuffer::getInstance()->getScreenWidth(true)/(double) 720; double yc = (double) CFrameBuffer::getInstance()->getScreenHeight(true)/(double) 576; xc = yc; //FIXME should we scale also to full width ? int xf = xc * (double) 720; for (i = 0; i < Count(); i++) { uint32_t * colors = (uint32_t *) sub.rects[i]->pict.data[1]; int width = sub.rects[i]->w; int height = sub.rects[i]->h; int xoff, yoff; int nw = (double) width * xc; int nh = (double) height * yc; int xdiff = (wd > xf) ? ((wd - xf) / 2) : 0; xoff = sub.rects[i]->x*xc + xstart + xdiff; if(sub.rects[i]->y < 576/2) { yoff = ystart + sub.rects[i]->y*yc; } else { yoff = yend - (576 - (double) (sub.rects[i]->y + height))*yc - nh; if(yoff < ystart) yoff = ystart; } dbgconverter("cDvbSubtitleBitmaps::Draw: #%d at %d,%d size %dx%d colors %d (x=%d y=%d w=%d h=%d) \n", i+1, sub.rects[i]->x, sub.rects[i]->y, sub.rects[i]->w, sub.rects[i]->h, sub.rects[i]->nb_colors, xoff, yoff, nw, nh); fb_pixel_t * newdata = simple_resize32 (sub.rects[i]->pict.data[0], colors, sub.rects[i]->nb_colors, width, height, nw, nh); fb_pixel_t * ptr = newdata; for (int y2 = 0; y2 < nh; y2++) { int y = (yoff + y2) * stride; for (int x2 = 0; x2 < nw; x2++) *(sublfb + xoff + x2 + y) = *ptr++; } free(newdata); if(min_x > xoff) min_x = xoff; if(min_y > yoff) min_y = yoff; if(max_x < (xoff + nw)) max_x = xoff + nw; if(max_y < (yoff + nh)) max_y = yoff + nh; } if(Count()) dbgconverter("cDvbSubtitleBitmaps::Draw: finish, min/max screen: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); dbgconverter("\n"); }
cDvbSubtitleConverter::cDvbSubtitleConverter(void) { dbgconverter("cDvbSubtitleConverter: new converter\n"); bitmaps = new cList<cDvbSubtitleBitmaps>; pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); pthread_mutex_init(&mutex, &attr); running = false; avctx = NULL; avcodec = NULL; avcodec_register_all(); avcodec = avcodec_find_decoder(CODEC_ID_DVB_SUBTITLE); if (!avcodec) { dbgconverter("cDvbSubtitleConverter: unable to get dvb subtitle codec!\n"); return; } #if LIBAVCODEC_VERSION_MAJOR < 54 avctx = avcodec_alloc_context(); #else avctx = avcodec_alloc_context3(avcodec); #endif if (!avctx) { dbgconverter("cDvbSubtitleConverter: unable to get dvb subtitle map!\n"); return; } #if LIBAVCODEC_VERSION_MAJOR < 54 if (avcodec_open(avctx, avcodec) < 0) #else if (avcodec_open2(avctx, avcodec, NULL) < 0) #endif dbgconverter("cDvbSubtitleConverter: unable to open codec !\n"); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 64, 0) av_log_set_level(AV_LOG_PANIC); #else av_log_set_level(0); #endif if(DebugConverter) #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 64, 0) av_log_set_level(AV_LOG_INFO); #else av_log_set_level(0); #endif min_x = CFrameBuffer::getInstance()->getScreenWidth(); /* screen width */ min_y = CFrameBuffer::getInstance()->getScreenHeight(); /* screenheight */ max_x = CFrameBuffer::getInstance()->getScreenX(); /* startX */ max_y = CFrameBuffer::getInstance()->getScreenY(); /* startY */ dbgconverter("cDvbSubtitleBitmaps::Draw: finish, min/max screen: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); Timeout.Set(0xFFFF*1000); }