public void OnTextSubtitle(ref TEXT_SUBTITLE sub) { try { if (sub.page == _activeSubPage) { Log.Debug("Page: " + sub.page); Log.Debug("Character table: " + sub.encoding); Log.Debug("Timeout: " + sub.timeOut); Log.Debug("Timestamp: " + sub.timeStamp); Log.Debug("Language: " + sub.language); String content = sub.text; if (content == null) { Log.Error("OnTextSubtitle: sub.txt == null!"); return; } Log.Debug("Content: "); if (content.Trim().Length > 0) // debug log subtitles { StringTokenizer st = new StringTokenizer(content, new char[] { '\n' }); while (st.HasMore) { Log.Debug(st.NextToken()); } } else { Log.Debug("Page: <BLANK PAGE>"); } } } catch (Exception e) { Log.Error("Problem with TEXT_SUBTITLE"); Log.Error(e); } try { // if we dont need the subtitle if (!_renderSubtitles || _useBitmap || (_activeSubPage != sub.page)) { // //chemelli: too much logging. You can check if logs have: // Log.Debug("Page: " + sub.page); or Log.Debug("Page: <BLANK PAGE>"); // and // Log.Debug("Text subtitle (page {0}) ACCEPTED: [...] // to know the evaluation of this if block // //Log.Debug("Text subtitle (page {0}) discarded: useBitmap is {1} and activeSubPage is {2}", sub.page, useBitmap, // activeSubPage); return; } Log.Debug("Text subtitle (page {0}) ACCEPTED: useBitmap is {1} and activeSubPage is {2}", sub.page, _useBitmap, _activeSubPage); Subtitle subtitle = new Subtitle(); // TODO - RenderText should directly draw to a D3D texture subtitle.subBitmap = RenderText(sub.lc); subtitle.timeOut = sub.timeOut; subtitle.presentTime = sub.timeStamp / 90000.0f + _startPos; subtitle.height = 576; subtitle.width = 720; subtitle.screenHeight = 576; subtitle.screenWidth = 720; subtitle.firstScanLine = 0; subtitle.horizontalPosition = 0; Texture texture = null; try { // allocate new texture texture = new Texture(GUIGraphicsContext.DX9Device, subtitle.subBitmap.Width, subtitle.subBitmap.Height, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default); int pitch; using (GraphicsStream a = texture.LockRectangle(0, LockFlags.Discard, out pitch)) { BitmapData bd = subtitle.subBitmap.LockBits(new Rectangle(0, 0, subtitle.subBitmap.Width, subtitle.subBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); // Quick copy of content unsafe { byte *to = (byte *)a.InternalDataPointer; byte *from = (byte *)bd.Scan0.ToPointer(); for (int y = 0; y < bd.Height; ++y) { for (int x = 0; x < bd.Width * 4; ++x) { to[pitch * y + x] = from[y * bd.Stride + x]; } } } texture.UnlockRectangle(0); subtitle.subBitmap.UnlockBits(bd); subtitle.subBitmap.SafeDispose(); subtitle.subBitmap = null; subtitle.texture = texture; a.Close(); } } catch (Exception e) { Log.Debug("SubtitleRenderer: Failed to create subtitle surface!"); Log.Error(e); return; } AddSubtitle(subtitle); } catch (Exception e) { Log.Error("Problem processing text subtitle"); Log.Error(e); } }
public void EndPage() { if (pageNumInProgress == -1) { return; // no page in progress } else if ((pageNumInProgress < 0 || pageNumInProgress >= 966)) { Log.Debug("DANGER DANGER!, endpage with pageNumInProgress = %i", pageNumInProgress); return; } Log.Debug("Finished Page {0}", pageNumInProgress); //bool hasContent = false; for (int i = 0; i < 25; i++) { bool boxed = false; byte[] lineContent = GetLine(i); for (int j = 0; j < 40; j++) { // Remove spacing attributes ( see 12.2 of the draft) // FIXME: Some subtitles will have the attributed 'double height' // and therefore have an empty line between subs. // ís this content a space attribute? if (MSB3_NP(lineContent[j]) == 0) { if (LSB4(lineContent[j]) == SPACE_ATTRIB_BOX_START) { //LogDebug("BS - boxed is true"); boxed = true; //hasContent = true; } else if (LSB4(lineContent[j]) == SPACE_ATTRIB_BOX_END) { //LogDebug("BE - boxed is false"); boxed = false; } // remove spacing attribute lineContent[j] = TELETEXT_BLANK; } else if (!boxed) { // if we are not in boxed mode, // we dont want to keep the content lineContent[j] = TELETEXT_BLANK; assert(!boxed, "EndPage: Boxed not set as expected"); } } SetLine(i, lineContent); } /*if(!hasContent) { Log.Debug("(BLANK PAGE)"); }*/ byte[] byte_text = new byte[TELETEXT_WIDTH * TELETEXT_LINES]; Array.Copy(pageContent, byte_text, TELETEXT_LINES * TELETEXT_WIDTH); char[] text = TextConversion.Convert(language, byte_text); LineContent[] lc = new LineContent[TELETEXT_LINES]; string realLang = ""; lock (langInfo) { string langInfoInPgrs = null; if (langInfo.TryGetValue(pageNumInProgress, out langInfoInPgrs)) { realLang = langInfoInPgrs; } } for (int line = 0; line < TELETEXT_LINES; line++) { StringBuilder lineBuilder = new StringBuilder(); for (int c = 0; c < TELETEXT_WIDTH; c++) { lineBuilder.Append((char)text[line * TELETEXT_WIDTH + c]); } lc[line] = new LineContent(); if (realLang != "") { lc[line].line = TextConversion.ConvertLineLangSpecific(realLang, lineBuilder.ToString()); } else { lc[line].line = lineBuilder.ToString(); } lc[line].doubleHeight = true; } StringBuilder textBuilder = new StringBuilder(); for (int i = 0; i < text.Length; i++) { //sbuf.Append((char)text[i]); textBuilder.Append((char)text[i]); //sbuf.Append("" + ((int)pageContent[i]) + " "); if (((i + 1) % 40) == 0) { textBuilder.Append('\n'); } } // prepare subtitle TEXT_SUBTITLE sub = new TEXT_SUBTITLE(); sub.encoding = language; sub.page = pageNumInProgress; sub.language = realLang; sub.text = textBuilder.ToString(); sub.lc = lc; sub.timeOut = ulong.MaxValue; // never timeout (will be replaced by other page) sub.timeStamp = presentTime; assert(sub.text != null, "Sub.text == null!"); if (owner.SubPageInfoCallback != null) { TeletextPageEntry pageEntry = new TeletextPageEntry(); pageEntry.language = String.Copy(sub.language); pageEntry.encoding = (TeletextCharTable)sub.encoding; pageEntry.page = sub.page; owner.SubPageInfoCallback(pageEntry); } owner.SubtitleRender.OnTextSubtitle(ref sub); pageNumInProgress = -1; }
public void OnTextSubtitle(ref TEXT_SUBTITLE sub) { try { if (sub.page == _activeSubPage) { Log.Debug("Page: " + sub.page); Log.Debug("Character table: " + sub.encoding); Log.Debug("Timeout: " + sub.timeOut); Log.Debug("Timestamp: " + sub.timeStamp); Log.Debug("Language: " + sub.language); String content = sub.text; if (content == null) { Log.Error("OnTextSubtitle: sub.txt == null!"); return; } Log.Debug("Content: "); if (content.Trim().Length > 0) // debug log subtitles { StringTokenizer st = new StringTokenizer(content, new char[] {'\n'}); while (st.HasMore) { Log.Debug(st.NextToken()); } } else { Log.Debug("Page: <BLANK PAGE>"); } } } catch (Exception e) { Log.Error("Problem with TEXT_SUBTITLE"); Log.Error(e); } try { // if we dont need the subtitle if (!_renderSubtitles || _useBitmap || (_activeSubPage != sub.page)) { // //chemelli: too much logging. You can check if logs have: // Log.Debug("Page: " + sub.page); or Log.Debug("Page: <BLANK PAGE>"); // and // Log.Debug("Text subtitle (page {0}) ACCEPTED: [...] // to know the evaluation of this if block // //Log.Debug("Text subtitle (page {0}) discarded: useBitmap is {1} and activeSubPage is {2}", sub.page, useBitmap, // activeSubPage); return; } Log.Debug("Text subtitle (page {0}) ACCEPTED: useBitmap is {1} and activeSubPage is {2}", sub.page, _useBitmap, _activeSubPage); Subtitle subtitle = new Subtitle(); // TODO - RenderText should directly draw to a D3D texture subtitle.subBitmap = RenderText(sub.lc); subtitle.timeOut = sub.timeOut; subtitle.presentTime = sub.timeStamp / 90000.0f + _startPos; subtitle.height = 576; subtitle.width = 720; subtitle.screenHeight = 576; subtitle.screenWidth = 720; subtitle.firstScanLine = 0; subtitle.horizontalPosition = 0; Texture texture = null; try { // allocate new texture texture = new Texture(GUIGraphicsContext.DX9Device, subtitle.subBitmap.Width, subtitle.subBitmap.Height, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default); int pitch; using (GraphicsStream a = texture.LockRectangle(0, LockFlags.Discard, out pitch)) { BitmapData bd = subtitle.subBitmap.LockBits(new Rectangle(0, 0, subtitle.subBitmap.Width, subtitle.subBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); // Quick copy of content unsafe { byte* to = (byte*)a.InternalDataPointer; byte* from = (byte*)bd.Scan0.ToPointer(); for (int y = 0; y < bd.Height; ++y) { for (int x = 0; x < bd.Width * 4; ++x) { to[pitch * y + x] = from[y * bd.Stride + x]; } } } texture.UnlockRectangle(0); subtitle.subBitmap.UnlockBits(bd); subtitle.subBitmap.SafeDispose(); subtitle.subBitmap = null; subtitle.texture = texture; a.Close(); } } catch (Exception e) { Log.Debug("SubtitleRenderer: Failed to create subtitle surface!"); Log.Error(e); return; } AddSubtitle(subtitle); } catch (Exception e) { Log.Error("Problem processing text subtitle"); Log.Error(e); } }
public void EndPage() { if (pageNumInProgress == -1) { return; // no page in progress } else if ((pageNumInProgress < 0 || pageNumInProgress >= 966)) { Log.Debug("DANGER DANGER!, endpage with pageNumInProgress = %i", pageNumInProgress); return; } Log.Debug("Finished Page {0}", pageNumInProgress); //bool hasContent = false; for (int i = 0; i < 25; i++) { bool boxed = false; byte[] lineContent = GetLine(i); for (int j = 0; j < 40; j++) { // Remove spacing attributes ( see 12.2 of the draft) // FIXME: Some subtitles will have the attributed 'double height' // and therefore have an empty line between subs. // ís this content a space attribute? if (MSB3_NP(lineContent[j]) == 0) { if (LSB4(lineContent[j]) == SPACE_ATTRIB_BOX_START) { //LogDebug("BS - boxed is true"); boxed = true; //hasContent = true; } else if (LSB4(lineContent[j]) == SPACE_ATTRIB_BOX_END) { //LogDebug("BE - boxed is false"); boxed = false; } // remove spacing attribute lineContent[j] = TELETEXT_BLANK; } else if (!boxed) { // if we are not in boxed mode, // we dont want to keep the content lineContent[j] = TELETEXT_BLANK; assert(!boxed, "EndPage: Boxed not set as expected"); } } SetLine(i, lineContent); } /*if(!hasContent) { * Log.Debug("(BLANK PAGE)"); * }*/ byte[] byte_text = new byte[TELETEXT_WIDTH * TELETEXT_LINES]; Array.Copy(pageContent, byte_text, TELETEXT_LINES * TELETEXT_WIDTH); char[] text = TextConversion.Convert(language, byte_text); LineContent[] lc = new LineContent[TELETEXT_LINES]; string realLang = ""; lock (langInfo) { string langInfoInPgrs = null; if (langInfo.TryGetValue(pageNumInProgress, out langInfoInPgrs)) { realLang = langInfoInPgrs; } } for (int line = 0; line < TELETEXT_LINES; line++) { StringBuilder lineBuilder = new StringBuilder(); for (int c = 0; c < TELETEXT_WIDTH; c++) { lineBuilder.Append((char)text[line * TELETEXT_WIDTH + c]); } lc[line] = new LineContent(); if (realLang != "") { lc[line].line = TextConversion.ConvertLineLangSpecific(realLang, lineBuilder.ToString()); } else { lc[line].line = lineBuilder.ToString(); } lc[line].doubleHeight = true; } StringBuilder textBuilder = new StringBuilder(); for (int i = 0; i < text.Length; i++) { //sbuf.Append((char)text[i]); textBuilder.Append((char)text[i]); //sbuf.Append("" + ((int)pageContent[i]) + " "); if (((i + 1) % 40) == 0) { textBuilder.Append('\n'); } } // prepare subtitle TEXT_SUBTITLE sub = new TEXT_SUBTITLE(); sub.encoding = language; sub.page = pageNumInProgress; sub.language = realLang; sub.text = textBuilder.ToString(); sub.lc = lc; sub.timeOut = ulong.MaxValue; // never timeout (will be replaced by other page) sub.timeStamp = presentTime; assert(sub.text != null, "Sub.text == null!"); if (owner.SubPageInfoCallback != null) { TeletextPageEntry pageEntry = new TeletextPageEntry(); pageEntry.language = String.Copy(sub.language); pageEntry.encoding = (TeletextCharTable)sub.encoding; pageEntry.page = sub.page; owner.SubPageInfoCallback(pageEntry); } owner.SubtitleRender.OnTextSubtitle(ref sub); pageNumInProgress = -1; }