/// <summary> /// Finds output geometry for the given preview settings and title. /// </summary> /// <param name="settings"> /// The preview settings. /// </param> /// <param name="title"> /// Information on the title to consider. /// </param> /// <returns> /// Geometry Information /// </returns> public static Geometry CreateGeometry(PreviewSettings settings, SourceVideoInfo title) { int settingMode = settings.KeepDisplayAspect ? 0x04 : 0; // Sanitize the Geometry First. AnamorphicGeometry anamorphicGeometry = new AnamorphicGeometry { SourceGeometry = new Geometry { Width = title.Resolution.Width, Height = title.Resolution.Height, PAR = new PAR { Num = title.ParVal.Width, Den = title.ParVal.Height } }, DestSettings = new DestSettings { AnamorphicMode = (int)settings.Anamorphic, Geometry = { Width = settings.Width, Height = settings.Height, PAR = new PAR { Num = settings.Anamorphic != Anamorphic.Custom ? title.ParVal.Width : settings.PixelAspectX, Den = settings.Anamorphic != Anamorphic.Custom ? title.ParVal.Height : settings.PixelAspectY, } }, Keep = settingMode, Crop = new List<int> { settings.Cropping.Top, settings.Cropping.Bottom, settings.Cropping.Left, settings.Cropping.Right }, Modulus = settings.Modulus ?? 16, MaxWidth = settings.MaxWidth, MaxHeight = settings.MaxHeight, ItuPAR = false } }; if (settings.Anamorphic == Anamorphic.Custom) { anamorphicGeometry.DestSettings.Geometry.PAR = new PAR { Num = settings.PixelAspectX, Den = settings.PixelAspectY }; } else { anamorphicGeometry.DestSettings.Geometry.PAR = new PAR { Num = title.ParVal.Width, Den = title.ParVal.Height }; } return HandBrakeUtils.GetAnamorphicSize(anamorphicGeometry); }
/// <summary> /// Get a Preview image for the current job and preview number. /// </summary> /// <param name="job"> /// The job. /// </param> /// <param name="preview"> /// The preview. /// </param> /// <param name="configuraiton"> /// The configuraiton. /// </param> /// <returns> /// The <see cref="BitmapImage"/>. /// </returns> public BitmapImage GetPreview(EncodeTask job, int preview, HBConfiguration configuraiton) { if (this.instance == null) { return null; } BitmapImage bitmapImage = null; try { PreviewSettings settings = new PreviewSettings { Cropping = new Cropping(job.Cropping), MaxWidth = job.MaxWidth ?? 0, MaxHeight = job.MaxHeight ?? 0, KeepDisplayAspect = job.KeepDisplayAspect, TitleNumber = job.Title, Anamorphic = job.Anamorphic, Modulus = job.Modulus, Width = job.Width ?? 0, Height = job.Height ?? 0, PixelAspectX = job.PixelAspectX, PixelAspectY = job.PixelAspectY }; bitmapImage = this.instance.GetPreview(settings, preview); } catch (AccessViolationException e) { Console.WriteLine(e); } return bitmapImage; }
public BitmapImage GetPreview(PreviewSettings settings, int previewNumber) { SourceTitle title = this.Titles.TitleList.FirstOrDefault(t => t.Index == settings.TitleNumber); // Create the Expected Output Geometry details for libhb. hb_geometry_settings_s uiGeometry = new hb_geometry_settings_s { crop = new[] { settings.Cropping.Top, settings.Cropping.Bottom, settings.Cropping.Left, settings.Cropping.Right }, itu_par = 0, keep = (int)AnamorphicFactory.KeepSetting.HB_KEEP_WIDTH + (settings.KeepDisplayAspect ? 0x04 : 0), // TODO Keep Width? maxWidth = settings.MaxWidth, maxHeight = settings.MaxHeight, mode = (int)(hb_anamorphic_mode_t)settings.Anamorphic, modulus = settings.Modulus ?? 16, geometry = new hb_geometry_s { height = settings.Height, width = settings.Width, par = settings.Anamorphic != Anamorphic.Custom ? new hb_rational_t { den = title.Geometry.PAR.Den, num = title.Geometry.PAR.Num } : new hb_rational_t { den = settings.PixelAspectY, num = settings.PixelAspectX } } }; // Sanitize the input. Geometry resultGeometry = AnamorphicFactory.CreateGeometry(settings, new SourceVideoInfo(new Size(title.Geometry.Width, title.Geometry.Height), new Size(title.Geometry.PAR.Num, title.Geometry.PAR.Den))); int width = resultGeometry.Width * resultGeometry.PAR.Num / resultGeometry.PAR.Den; int height = resultGeometry.Height; uiGeometry.geometry.width = width; uiGeometry.geometry.height = height; uiGeometry.geometry.par.num = settings.PixelAspectX; uiGeometry.geometry.par.den = settings.PixelAspectY; // Fetch the image data from LibHb IntPtr resultingImageStuct = HBFunctions.hb_get_preview2(this.hbHandle, settings.TitleNumber, previewNumber, ref uiGeometry, 0); hb_image_s image = InteropUtilities.ToStructureFromPtr<hb_image_s>(resultingImageStuct); // Copy the filled image buffer to a managed array. int stride_width = image.plane[0].stride; int stride_height = image.plane[0].height_stride; int imageBufferSize = stride_width * stride_height; // int imageBufferSize = outputWidth * outputHeight * 4; byte[] managedBuffer = new byte[imageBufferSize]; Marshal.Copy(image.plane[0].data, managedBuffer, 0, imageBufferSize); var bitmap = new Bitmap(width, height); BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb); IntPtr ptr = bitmapData.Scan0; // Pointer to the first pixel. for (int i = 0; i < image.height; i++) { try { Marshal.Copy(managedBuffer, i * stride_width, ptr, stride_width); ptr = IntPtr.Add(ptr, width * 4); } catch (Exception exc) { Debug.WriteLine(exc); // In theory, this will allow a partial image display if this happens. TODO add better logging of this. } } bitmap.UnlockBits(bitmapData); // Close the image so we don't leak memory. IntPtr nativeJobPtrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); Marshal.WriteIntPtr(nativeJobPtrPtr, resultingImageStuct); HBFunctions.hb_image_close(nativeJobPtrPtr); Marshal.FreeHGlobal(nativeJobPtrPtr); // Create a Bitmap Image for display. using (var memoryStream = new MemoryStream()) { try { bitmap.Save(memoryStream, ImageFormat.Bmp); } finally { bitmap.Dispose(); } var wpfBitmap = new BitmapImage(); wpfBitmap.BeginInit(); wpfBitmap.CacheOption = BitmapCacheOption.OnLoad; wpfBitmap.StreamSource = memoryStream; wpfBitmap.EndInit(); wpfBitmap.Freeze(); return wpfBitmap; } }
/// <summary> /// Get a Preview image for the current job and preview number. /// </summary> /// <param name="job"> /// The job. /// </param> /// <param name="preview"> /// The preview. /// </param> /// <param name="configuraiton"> /// The configuraiton. /// </param> /// <returns> /// The <see cref="BitmapImage"/>. /// </returns> public BitmapImage GetPreview(EncodeTask job, int preview, HBConfiguration configuraiton) { if (this.instance == null) { return null; } BitmapImage bitmapImage = null; try { PreviewSettings settings = new PreviewSettings(job); bitmapImage = this.instance.GetPreview(settings, preview); } catch (AccessViolationException e) { Console.WriteLine(e); } return bitmapImage; }