/// <summary> /// Callback from subtitle filter, alerting us that a new subtitle is available /// It receives the new subtitle as the argument sub, which data is only valid /// for the duration of OnSubtitle. /// </summary> /// <returns></returns> public int OnSubtitle(ref NATIVE_SUBTITLE sub) { if (!_useBitmap || !_renderSubtitles) { return(0); // TODO: Might be good to let this cache and then check in Render method because bitmap subs arrive a while before display } Log.Debug("OnSubtitle - stream position " + _player.StreamPosition); lock (_alert) { try { Log.Debug("SubtitleRenderer: Bitmap: bpp=" + sub.bmBitsPixel + " planes " + sub.bmPlanes + " dim = " + sub.bmWidth + " x " + sub.bmHeight + " stride : " + sub.bmWidthBytes); Log.Debug("SubtitleRenderer: to = " + sub.timeOut + " ts=" + sub.timeStamp + " fsl=" + sub.firstScanLine + " h pos=" + sub.horizontalPosition + " (startPos = " + _startPos + ")"); Subtitle subtitle = new Subtitle(); subtitle.subBitmap = new Bitmap(sub.bmWidth, sub.bmHeight, PixelFormat.Format32bppArgb); subtitle.timeOut = sub.timeOut; subtitle.presentTime = ((double)sub.timeStamp / 1000.0f) + _startPos; // compute present time in SECONDS subtitle.height = (uint)sub.bmHeight; subtitle.width = (uint)sub.bmWidth; subtitle.screenHeight = (uint)sub.screenHeight; subtitle.screenWidth = (uint)sub.screenWidth; subtitle.firstScanLine = sub.firstScanLine; subtitle.horizontalPosition = sub.horizontalPosition; subtitle.id = _subCounter++; //Log.Debug("Received Subtitle : " + subtitle.ToString()); Texture texture = null; try { // allocate new texture texture = new Texture(GUIGraphicsContext.DX9Device, (int)subtitle.width, (int)subtitle.height, 1, Usage.Dynamic, Format.A8R8G8B8, GUIGraphicsContext.GetTexturePoolType()); if (texture == null) { Log.Debug("OnSubtitle: Failed to create new texture!"); return(0); } int pitch; using (GraphicsStream a = texture.LockRectangle(0, LockFlags.Discard, out pitch)) { // Quick copy of content unsafe { byte *to = (byte *)a.InternalDataPointer; byte *from = (byte *)sub.bmBits; for (int y = 0; y < sub.bmHeight; ++y) { for (int x = 0; x < sub.bmWidth * 4; ++x) { to[pitch * y + x] = from[y * sub.bmWidthBytes + x]; } } } a.Close(); } texture.UnlockRectangle(0); subtitle.texture = texture; } catch (Exception) { Log.Debug("OnSubtitle: Failed to copy bitmap data!"); return(0); } AddSubtitle(subtitle); } catch (Exception e) { Log.Error(e); } } return(0); }
/// <summary> /// Callback from subtitle filter, alerting us that a new subtitle is available /// It receives the new subtitle as the argument sub, which data is only valid /// for the duration of OnSubtitle. /// </summary> /// <returns></returns> public int OnSubtitle(ref NATIVE_SUBTITLE sub) { if (!_useBitmap || !_renderSubtitles) { return 0; // TODO: Might be good to let this cache and then check in Render method because bitmap subs arrive a while before display } Log.Debug("OnSubtitle - stream position " + _player.StreamPosition); lock (_alert) { try { Log.Debug("SubtitleRenderer: Bitmap: bpp=" + sub.bmBitsPixel + " planes " + sub.bmPlanes + " dim = " + sub.bmWidth + " x " + sub.bmHeight + " stride : " + sub.bmWidthBytes); Log.Debug("SubtitleRenderer: to = " + sub.timeOut + " ts=" + sub.timeStamp + " fsl=" + sub.firstScanLine + " h pos=" + sub.horizontalPosition + " (startPos = " + _startPos + ")"); Subtitle subtitle = new Subtitle(); subtitle.subBitmap = new Bitmap(sub.bmWidth, sub.bmHeight, PixelFormat.Format32bppArgb); subtitle.timeOut = sub.timeOut; subtitle.presentTime = ((double)sub.timeStamp / 1000.0f) + _startPos; // compute present time in SECONDS subtitle.height = (uint)sub.bmHeight; subtitle.width = (uint)sub.bmWidth; subtitle.screenHeight = (uint)sub.screenHeight; subtitle.screenWidth = (uint)sub.screenWidth; subtitle.firstScanLine = sub.firstScanLine; subtitle.horizontalPosition = sub.horizontalPosition; subtitle.id = _subCounter++; //Log.Debug("Received Subtitle : " + subtitle.ToString()); Texture texture = null; try { // allocate new texture texture = new Texture(GUIGraphicsContext.DX9Device, (int)subtitle.width, (int)subtitle.height, 1, Usage.Dynamic, Format.A8R8G8B8, GUIGraphicsContext.GetTexturePoolType()); if (texture == null) { Log.Debug("OnSubtitle: Failed to create new texture!"); return 0; } int pitch; using (GraphicsStream a = texture.LockRectangle(0, LockFlags.Discard, out pitch)) { // Quick copy of content unsafe { byte* to = (byte*)a.InternalDataPointer; byte* from = (byte*)sub.bmBits; for (int y = 0; y < sub.bmHeight; ++y) { for (int x = 0; x < sub.bmWidth * 4; ++x) { to[pitch * y + x] = from[y * sub.bmWidthBytes + x]; } } } a.Close(); } texture.UnlockRectangle(0); subtitle.texture = texture; } catch (Exception) { Log.Debug("OnSubtitle: Failed to copy bitmap data!"); return 0; } AddSubtitle(subtitle); } catch (Exception e) { Log.Error(e); } } return 0; }