From 196036e8bf561e9522dee094f1b61d05aceafba8 Mon Sep 17 00:00:00 2001 From: epbk Date: Fri, 3 Nov 2023 19:43:32 +0100 Subject: [PATCH 1/7] MP1-5180: Add HEVC codec to BluRay configuration --- .../Sections/BDCodec.Designer.cs | 477 ++++++++++-------- mediaportal/Configuration/Sections/BDCodec.cs | 21 + 2 files changed, 281 insertions(+), 217 deletions(-) diff --git a/mediaportal/Configuration/Sections/BDCodec.Designer.cs b/mediaportal/Configuration/Sections/BDCodec.Designer.cs index 2e97e27b60a..cf7b2e22009 100644 --- a/mediaportal/Configuration/Sections/BDCodec.Designer.cs +++ b/mediaportal/Configuration/Sections/BDCodec.Designer.cs @@ -23,229 +23,269 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.mpGroupBox1 = new MediaPortal.UserInterface.Controls.MPGroupBox(); - this.configAudioRenderer = new MediaPortal.UserInterface.Controls.MPButton(); - this.configAUDIO = new MediaPortal.UserInterface.Controls.MPButton(); - this.configVC1 = new MediaPortal.UserInterface.Controls.MPButton(); - this.configH264 = new MediaPortal.UserInterface.Controls.MPButton(); - this.configMPEG = new MediaPortal.UserInterface.Controls.MPButton(); - this.mpLabel2 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.vc1videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.mpLabel1 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.h264videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.audioRendererComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.label3 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.label6 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.audioCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.label5 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.mpGroupBox1.SuspendLayout(); - this.SuspendLayout(); - // - // mpGroupBox1 - // - this.mpGroupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.mpGroupBox1 = new MediaPortal.UserInterface.Controls.MPGroupBox(); + this.configAudioRenderer = new MediaPortal.UserInterface.Controls.MPButton(); + this.configAUDIO = new MediaPortal.UserInterface.Controls.MPButton(); + this.configVC1 = new MediaPortal.UserInterface.Controls.MPButton(); + this.configH264 = new MediaPortal.UserInterface.Controls.MPButton(); + this.configHEVC = new MediaPortal.UserInterface.Controls.MPButton(); + this.configMPEG = new MediaPortal.UserInterface.Controls.MPButton(); + this.mpLabel2 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.vc1videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.mpLabel1 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.h264videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.mpLabel3 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.hevcvideoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.audioRendererComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.label3 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.label6 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.audioCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.label5 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.mpGroupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // mpGroupBox1 + // + this.mpGroupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.mpGroupBox1.Controls.Add(this.configAudioRenderer); - this.mpGroupBox1.Controls.Add(this.configAUDIO); - this.mpGroupBox1.Controls.Add(this.configVC1); - this.mpGroupBox1.Controls.Add(this.configH264); - this.mpGroupBox1.Controls.Add(this.configMPEG); - this.mpGroupBox1.Controls.Add(this.mpLabel2); - this.mpGroupBox1.Controls.Add(this.vc1videoCodecComboBox); - this.mpGroupBox1.Controls.Add(this.mpLabel1); - this.mpGroupBox1.Controls.Add(this.h264videoCodecComboBox); - this.mpGroupBox1.Controls.Add(this.audioRendererComboBox); - this.mpGroupBox1.Controls.Add(this.label3); - this.mpGroupBox1.Controls.Add(this.label6); - this.mpGroupBox1.Controls.Add(this.audioCodecComboBox); - this.mpGroupBox1.Controls.Add(this.videoCodecComboBox); - this.mpGroupBox1.Controls.Add(this.label5); - this.mpGroupBox1.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.mpGroupBox1.Location = new System.Drawing.Point(6, 0); - this.mpGroupBox1.Name = "mpGroupBox1"; - this.mpGroupBox1.Size = new System.Drawing.Size(462, 313); - this.mpGroupBox1.TabIndex = 1; - this.mpGroupBox1.TabStop = false; - this.mpGroupBox1.Text = "Settings Decoder"; - // - // configAudioRenderer - // - this.configAudioRenderer.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configAudioRenderer.BackColor = System.Drawing.Color.Transparent; - this.configAudioRenderer.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configAudioRenderer.Location = new System.Drawing.Point(422, 127); - this.configAudioRenderer.Name = "configAudioRenderer"; - this.configAudioRenderer.Size = new System.Drawing.Size(35, 21); - this.configAudioRenderer.TabIndex = 74; - this.configAudioRenderer.Text = "\r\n"; - this.configAudioRenderer.UseVisualStyleBackColor = false; - this.configAudioRenderer.Click += new System.EventHandler(this.configAudioRenderer_Click); - // - // configAUDIO - // - this.configAUDIO.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configAUDIO.BackColor = System.Drawing.Color.Transparent; - this.configAUDIO.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configAUDIO.Location = new System.Drawing.Point(422, 103); - this.configAUDIO.Name = "configAUDIO"; - this.configAUDIO.Size = new System.Drawing.Size(35, 21); - this.configAUDIO.TabIndex = 73; - this.configAUDIO.Text = "\r\n"; - this.configAUDIO.UseVisualStyleBackColor = false; - this.configAUDIO.Click += new System.EventHandler(this.configAUDIO_Click); - // - // configVC1 - // - this.configVC1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configVC1.BackColor = System.Drawing.Color.Transparent; - this.configVC1.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configVC1.Location = new System.Drawing.Point(422, 72); - this.configVC1.Name = "configVC1"; - this.configVC1.Size = new System.Drawing.Size(35, 21); - this.configVC1.TabIndex = 72; - this.configVC1.Text = "\r\n"; - this.configVC1.UseVisualStyleBackColor = false; - this.configVC1.Click += new System.EventHandler(this.configVC1_Click); - // - // configH264 - // - this.configH264.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configH264.BackColor = System.Drawing.Color.Transparent; - this.configH264.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configH264.Location = new System.Drawing.Point(422, 48); - this.configH264.Name = "configH264"; - this.configH264.Size = new System.Drawing.Size(35, 21); - this.configH264.TabIndex = 71; - this.configH264.Text = "\r\n"; - this.configH264.UseVisualStyleBackColor = false; - this.configH264.Click += new System.EventHandler(this.configH264_Click); - // - // configMPEG - // - this.configMPEG.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configMPEG.BackColor = System.Drawing.Color.Transparent; - this.configMPEG.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configMPEG.Location = new System.Drawing.Point(422, 24); - this.configMPEG.Name = "configMPEG"; - this.configMPEG.Size = new System.Drawing.Size(35, 21); - this.configMPEG.TabIndex = 70; - this.configMPEG.Text = "\r\n"; - this.configMPEG.UseVisualStyleBackColor = false; - this.configMPEG.Click += new System.EventHandler(this.configMPEG_Click); - // - // mpLabel2 - // - this.mpLabel2.Location = new System.Drawing.Point(16, 76); - this.mpLabel2.Name = "mpLabel2"; - this.mpLabel2.Size = new System.Drawing.Size(88, 16); - this.mpLabel2.TabIndex = 10; - this.mpLabel2.Text = "VC-1 Video :"; - // - // vc1videoCodecComboBox - // - this.vc1videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.mpGroupBox1.Controls.Add(this.configAudioRenderer); + this.mpGroupBox1.Controls.Add(this.configAUDIO); + this.mpGroupBox1.Controls.Add(this.configVC1); + this.mpGroupBox1.Controls.Add(this.configH264); + this.mpGroupBox1.Controls.Add(this.configHEVC); + this.mpGroupBox1.Controls.Add(this.configMPEG); + this.mpGroupBox1.Controls.Add(this.mpLabel2); + this.mpGroupBox1.Controls.Add(this.vc1videoCodecComboBox); + this.mpGroupBox1.Controls.Add(this.mpLabel1); + this.mpGroupBox1.Controls.Add(this.h264videoCodecComboBox); + this.mpGroupBox1.Controls.Add(this.mpLabel3); + this.mpGroupBox1.Controls.Add(this.hevcvideoCodecComboBox); + this.mpGroupBox1.Controls.Add(this.audioRendererComboBox); + this.mpGroupBox1.Controls.Add(this.label3); + this.mpGroupBox1.Controls.Add(this.label6); + this.mpGroupBox1.Controls.Add(this.audioCodecComboBox); + this.mpGroupBox1.Controls.Add(this.videoCodecComboBox); + this.mpGroupBox1.Controls.Add(this.label5); + this.mpGroupBox1.FlatStyle = System.Windows.Forms.FlatStyle.Popup; + this.mpGroupBox1.Location = new System.Drawing.Point(6, 0); + this.mpGroupBox1.Name = "mpGroupBox1"; + this.mpGroupBox1.Size = new System.Drawing.Size(462, 313); + this.mpGroupBox1.TabIndex = 1; + this.mpGroupBox1.TabStop = false; + this.mpGroupBox1.Text = "Settings Decoder"; + // + // configAudioRenderer + // + this.configAudioRenderer.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configAudioRenderer.BackColor = System.Drawing.Color.Transparent; + this.configAudioRenderer.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configAudioRenderer.Location = new System.Drawing.Point(422, 151); + this.configAudioRenderer.Name = "configAudioRenderer"; + this.configAudioRenderer.Size = new System.Drawing.Size(35, 21); + this.configAudioRenderer.TabIndex = 75; + this.configAudioRenderer.Text = "\r\n"; + this.configAudioRenderer.UseVisualStyleBackColor = false; + this.configAudioRenderer.Click += new System.EventHandler(this.configAudioRenderer_Click); + // + // configAUDIO + // + this.configAUDIO.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configAUDIO.BackColor = System.Drawing.Color.Transparent; + this.configAUDIO.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configAUDIO.Location = new System.Drawing.Point(422, 127); + this.configAUDIO.Name = "configAUDIO"; + this.configAUDIO.Size = new System.Drawing.Size(35, 21); + this.configAUDIO.TabIndex = 74; + this.configAUDIO.Text = "\r\n"; + this.configAUDIO.UseVisualStyleBackColor = false; + this.configAUDIO.Click += new System.EventHandler(this.configAUDIO_Click); + // + // configVC1 + // + this.configVC1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configVC1.BackColor = System.Drawing.Color.Transparent; + this.configVC1.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configVC1.Location = new System.Drawing.Point(422, 96); + this.configVC1.Name = "configVC1"; + this.configVC1.Size = new System.Drawing.Size(35, 21); + this.configVC1.TabIndex = 73; + this.configVC1.Text = "\r\n"; + this.configVC1.UseVisualStyleBackColor = false; + this.configVC1.Click += new System.EventHandler(this.configVC1_Click); + // + // configH264 + // + this.configH264.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configH264.BackColor = System.Drawing.Color.Transparent; + this.configH264.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configH264.Location = new System.Drawing.Point(422, 48); + this.configH264.Name = "configH264"; + this.configH264.Size = new System.Drawing.Size(35, 21); + this.configH264.TabIndex = 71; + this.configH264.Text = "\r\n"; + this.configH264.UseVisualStyleBackColor = false; + this.configH264.Click += new System.EventHandler(this.configH264_Click); + // + // configHEVC + // + this.configHEVC.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configHEVC.BackColor = System.Drawing.Color.Transparent; + this.configHEVC.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configHEVC.Location = new System.Drawing.Point(422, 72); + this.configHEVC.Name = "configHEVC"; + this.configHEVC.Size = new System.Drawing.Size(35, 21); + this.configHEVC.TabIndex = 72; + this.configHEVC.Text = "\r\n"; + this.configHEVC.UseVisualStyleBackColor = false; + this.configHEVC.Click += new System.EventHandler(this.configHEVC_Click); + // + // configMPEG + // + this.configMPEG.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configMPEG.BackColor = System.Drawing.Color.Transparent; + this.configMPEG.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configMPEG.Location = new System.Drawing.Point(422, 24); + this.configMPEG.Name = "configMPEG"; + this.configMPEG.Size = new System.Drawing.Size(35, 21); + this.configMPEG.TabIndex = 70; + this.configMPEG.Text = "\r\n"; + this.configMPEG.UseVisualStyleBackColor = false; + this.configMPEG.Click += new System.EventHandler(this.configMPEG_Click); + // + // mpLabel2 + // + this.mpLabel2.Location = new System.Drawing.Point(16, 100); + this.mpLabel2.Name = "mpLabel2"; + this.mpLabel2.Size = new System.Drawing.Size(88, 16); + this.mpLabel2.TabIndex = 93; + this.mpLabel2.Text = "VC-1 Video :"; + // + // vc1videoCodecComboBox + // + this.vc1videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.vc1videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; - this.vc1videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.vc1videoCodecComboBox.Location = new System.Drawing.Point(122, 72); - this.vc1videoCodecComboBox.Name = "vc1videoCodecComboBox"; - this.vc1videoCodecComboBox.Size = new System.Drawing.Size(295, 21); - this.vc1videoCodecComboBox.Sorted = true; - this.vc1videoCodecComboBox.TabIndex = 5; - // - // mpLabel1 - // - this.mpLabel1.Location = new System.Drawing.Point(16, 52); - this.mpLabel1.Name = "mpLabel1"; - this.mpLabel1.Size = new System.Drawing.Size(88, 16); - this.mpLabel1.TabIndex = 8; - this.mpLabel1.Text = "H.264 Video :"; - // - // h264videoCodecComboBox - // - this.h264videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.vc1videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.vc1videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.vc1videoCodecComboBox.Location = new System.Drawing.Point(122, 96); + this.vc1videoCodecComboBox.Name = "vc1videoCodecComboBox"; + this.vc1videoCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.vc1videoCodecComboBox.Sorted = true; + this.vc1videoCodecComboBox.TabIndex = 4; + // + // mpLabel1 + // + this.mpLabel1.Location = new System.Drawing.Point(16, 52); + this.mpLabel1.Name = "mpLabel1"; + this.mpLabel1.Size = new System.Drawing.Size(88, 16); + this.mpLabel1.TabIndex = 91; + this.mpLabel1.Text = "H.264 Video :"; + // + // h264videoCodecComboBox + // + this.h264videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.h264videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; - this.h264videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.h264videoCodecComboBox.Location = new System.Drawing.Point(122, 48); - this.h264videoCodecComboBox.Name = "h264videoCodecComboBox"; - this.h264videoCodecComboBox.Size = new System.Drawing.Size(295, 21); - this.h264videoCodecComboBox.Sorted = true; - this.h264videoCodecComboBox.TabIndex = 3; - this.h264videoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.h264videoCodecComboBox_SelectedIndexChanged); - // - // audioRendererComboBox - // - this.audioRendererComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.h264videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.h264videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.h264videoCodecComboBox.Location = new System.Drawing.Point(122, 48); + this.h264videoCodecComboBox.Name = "h264videoCodecComboBox"; + this.h264videoCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.h264videoCodecComboBox.Sorted = true; + this.h264videoCodecComboBox.TabIndex = 2; + this.h264videoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.h264videoCodecComboBox_SelectedIndexChanged); + // + // mpLabel3 + // + this.mpLabel3.Location = new System.Drawing.Point(16, 76); + this.mpLabel3.Name = "mpLabel3"; + this.mpLabel3.Size = new System.Drawing.Size(88, 16); + this.mpLabel3.TabIndex = 92; + this.mpLabel3.Text = "HEVC Video :"; + // + // hevcvideoCodecComboBox + // + this.hevcvideoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.audioRendererComboBox.BorderColor = System.Drawing.Color.Empty; - this.audioRendererComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.audioRendererComboBox.Location = new System.Drawing.Point(122, 128); - this.audioRendererComboBox.Name = "audioRendererComboBox"; - this.audioRendererComboBox.Size = new System.Drawing.Size(295, 21); - this.audioRendererComboBox.Sorted = true; - this.audioRendererComboBox.TabIndex = 9; - // - // label3 - // - this.label3.Location = new System.Drawing.Point(16, 132); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(88, 17); - this.label3.TabIndex = 6; - this.label3.Text = "Audio renderer:"; - // - // label6 - // - this.label6.Location = new System.Drawing.Point(16, 28); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(88, 16); - this.label6.TabIndex = 0; - this.label6.Text = "MPEG-2 Video :"; - // - // audioCodecComboBox - // - this.audioCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.hevcvideoCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.hevcvideoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.hevcvideoCodecComboBox.Location = new System.Drawing.Point(122, 72); + this.hevcvideoCodecComboBox.Name = "hevcvideoCodecComboBox"; + this.hevcvideoCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.hevcvideoCodecComboBox.Sorted = true; + this.hevcvideoCodecComboBox.TabIndex = 3; + this.hevcvideoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.hevcvideoCodecComboBox_SelectedIndexChanged); + // + // audioRendererComboBox + // + this.audioRendererComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.audioCodecComboBox.BorderColor = System.Drawing.Color.Empty; - this.audioCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.audioCodecComboBox.Location = new System.Drawing.Point(122, 104); - this.audioCodecComboBox.Name = "audioCodecComboBox"; - this.audioCodecComboBox.Size = new System.Drawing.Size(295, 21); - this.audioCodecComboBox.Sorted = true; - this.audioCodecComboBox.TabIndex = 7; - // - // videoCodecComboBox - // - this.videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.audioRendererComboBox.BorderColor = System.Drawing.Color.Empty; + this.audioRendererComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.audioRendererComboBox.Location = new System.Drawing.Point(122, 152); + this.audioRendererComboBox.Name = "audioRendererComboBox"; + this.audioRendererComboBox.Size = new System.Drawing.Size(295, 21); + this.audioRendererComboBox.Sorted = true; + this.audioRendererComboBox.TabIndex = 6; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 156); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(88, 17); + this.label3.TabIndex = 95; + this.label3.Text = "Audio renderer:"; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(16, 28); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(88, 16); + this.label6.TabIndex = 90; + this.label6.Text = "MPEG-2 Video :"; + // + // audioCodecComboBox + // + this.audioCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; - this.videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.videoCodecComboBox.Location = new System.Drawing.Point(122, 24); - this.videoCodecComboBox.Name = "videoCodecComboBox"; - this.videoCodecComboBox.Size = new System.Drawing.Size(295, 21); - this.videoCodecComboBox.Sorted = true; - this.videoCodecComboBox.TabIndex = 1; - this.videoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.videoCodecComboBox_SelectedIndexChanged); - // - // label5 - // - this.label5.Location = new System.Drawing.Point(16, 108); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(125, 21); - this.label5.TabIndex = 2; - this.label5.Text = "LPCM/AC3/DTS :"; - // - // BDCodec - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackColor = System.Drawing.SystemColors.Window; - this.Controls.Add(this.mpGroupBox1); - this.Name = "BDCodec"; - this.Size = new System.Drawing.Size(472, 391); - this.mpGroupBox1.ResumeLayout(false); - this.ResumeLayout(false); + this.audioCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.audioCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.audioCodecComboBox.Location = new System.Drawing.Point(122, 128); + this.audioCodecComboBox.Name = "audioCodecComboBox"; + this.audioCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.audioCodecComboBox.Sorted = true; + this.audioCodecComboBox.TabIndex = 5; + // + // videoCodecComboBox + // + this.videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.videoCodecComboBox.Location = new System.Drawing.Point(122, 21); + this.videoCodecComboBox.Name = "videoCodecComboBox"; + this.videoCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.videoCodecComboBox.Sorted = true; + this.videoCodecComboBox.TabIndex = 1; + this.videoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.videoCodecComboBox_SelectedIndexChanged); + // + // label5 + // + this.label5.Location = new System.Drawing.Point(16, 132); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(125, 21); + this.label5.TabIndex = 94; + this.label5.Text = "LPCM/AC3/DTS :"; + // + // BDCodec + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Window; + this.Controls.Add(this.mpGroupBox1); + this.Name = "BDCodec"; + this.Size = new System.Drawing.Size(472, 391); + this.mpGroupBox1.ResumeLayout(false); + this.ResumeLayout(false); } @@ -254,6 +294,8 @@ private void InitializeComponent() private MediaPortal.UserInterface.Controls.MPGroupBox mpGroupBox1; private MediaPortal.UserInterface.Controls.MPLabel mpLabel1; private MediaPortal.UserInterface.Controls.MPComboBox h264videoCodecComboBox; + private MediaPortal.UserInterface.Controls.MPLabel mpLabel3; + private MediaPortal.UserInterface.Controls.MPComboBox hevcvideoCodecComboBox; private MediaPortal.UserInterface.Controls.MPComboBox audioRendererComboBox; private MediaPortal.UserInterface.Controls.MPLabel label3; private MediaPortal.UserInterface.Controls.MPLabel label6; @@ -267,5 +309,6 @@ private void InitializeComponent() private UserInterface.Controls.MPButton configAUDIO; private UserInterface.Controls.MPButton configVC1; private UserInterface.Controls.MPButton configH264; + private UserInterface.Controls.MPButton configHEVC; } } diff --git a/mediaportal/Configuration/Sections/BDCodec.cs b/mediaportal/Configuration/Sections/BDCodec.cs index ece5b551ff0..c27f507640a 100644 --- a/mediaportal/Configuration/Sections/BDCodec.cs +++ b/mediaportal/Configuration/Sections/BDCodec.cs @@ -62,6 +62,7 @@ public override sealed void OnSectionActivated() ArrayList availableVideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubTypeEx.MPEG2); ArrayList availableAudioFilters = FilterHelper.GetFilters(MediaType.Audio, MediaSubType.Mpeg2Audio); ArrayList availableH264VideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.H264); + ArrayList availableHEVCVideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.HEVC); ArrayList availableVC1VideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.VC1); ArrayList availableVC1CyberlinkVideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.CyberlinkVC1); ArrayList availableFileSyncFilters = FilterHelper.GetFilters(MediaType.Stream, MediaSubType.Null); @@ -113,6 +114,7 @@ public override sealed void OnSectionActivated() audioCodecComboBox.Items.AddRange(availableAudioFilters.ToArray()); availableFileSyncFilters.Sort(); h264videoCodecComboBox.Items.AddRange(availableH264VideoFilters.ToArray()); + hevcvideoCodecComboBox.Items.AddRange(availableHEVCVideoFilters.ToArray()); vc1videoCodecComboBox.Items.AddRange(availableVC1VideoFilters.ToArray()); vc1videoCodecComboBox.Items.AddRange(availableVC1CyberlinkVideoFilters.ToArray()); audioRendererComboBox.Items.AddRange(availableAudioRenderers.ToArray()); @@ -137,6 +139,7 @@ public override void LoadSettings() // Set codecs string videoCodec = xmlreader.GetValueAsString("bdplayer", "mpeg2videocodec", ""); string h264videoCodec = xmlreader.GetValueAsString("bdplayer", "h264videocodec", ""); + string hevcvideoCodec = xmlreader.GetValueAsString("bdplayer", "hevcvideocodec", ""); string vc1videoCodec = xmlreader.GetValueAsString("bdplayer", "vc1videocodec", ""); string audioCodec = xmlreader.GetValueAsString("bdplayer", "mpeg2audiocodec", ""); //string aacaudioCodec = xmlreader.GetValueAsString("bdplayer", "aacaudiocodec", ""); @@ -151,6 +154,11 @@ public override void LoadSettings() ArrayList availableH264VideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.H264); h264videoCodec = SetCodecBox(availableH264VideoFilters, "LAV Video Decoder", "CoreAVC Video Decoder", ""); } + if (hevcvideoCodec == string.Empty) + { + ArrayList availableHEVCVideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.HEVC); + hevcvideoCodec = SetCodecBox(availableHEVCVideoFilters, "LAV Video Decoder", "CoreAVC Video Decoder", ""); + } if (vc1videoCodec == string.Empty) { ArrayList availableVC1VideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.VC1); @@ -165,10 +173,12 @@ public override void LoadSettings() audioCodecComboBox.Text = audioCodec; videoCodecComboBox.Text = videoCodec; h264videoCodecComboBox.Text = h264videoCodec; + hevcvideoCodecComboBox.Text = hevcvideoCodec; vc1videoCodecComboBox.Text = vc1videoCodec; CheckBoxValid(audioCodecComboBox); CheckBoxValid(videoCodecComboBox); CheckBoxValid(h264videoCodecComboBox); + CheckBoxValid(hevcvideoCodecComboBox); CheckBoxValid(vc1videoCodecComboBox); CheckBoxValid(audioRendererComboBox); } @@ -242,6 +252,7 @@ public override void SaveSettings() xmlwriter.SetValue("bdplayer", "mpeg2audiocodec", audioCodecComboBox.Text); xmlwriter.SetValue("bdplayer", "mpeg2videocodec", videoCodecComboBox.Text); xmlwriter.SetValue("bdplayer", "h264videocodec", h264videoCodecComboBox.Text); + xmlwriter.SetValue("bdplayer", "hevcvideocodec", hevcvideoCodecComboBox.Text); xmlwriter.SetValue("bdplayer", "vc1videocodec", vc1videoCodecComboBox.Text); } } @@ -296,6 +307,11 @@ private void h264videoCodecComboBox_SelectedIndexChanged(object sender, System.E */ } + private void hevcvideoCodecComboBox_SelectedIndexChanged(object sender, System.EventArgs e) + { + + } + private void RegMPtoConfig(string subkeysource) { using (RegistryKey subkey = Registry.CurrentUser.CreateSubKey(subkeysource)) @@ -397,6 +413,11 @@ private void configH264_Click(object sender, EventArgs e) ConfigCodecSection(sender, e, h264videoCodecComboBox.Text); } + private void configHEVC_Click(object sender, EventArgs e) + { + ConfigCodecSection(sender, e, hevcvideoCodecComboBox.Text); + } + private void configVC1_Click(object sender, EventArgs e) { ConfigCodecSection(sender, e, vc1videoCodecComboBox.Text); From 7b41ed1ea2c6c29cee81fd7eeec341bbcc2464c3 Mon Sep 17 00:00:00 2001 From: epbk Date: Fri, 3 Nov 2023 19:50:39 +0100 Subject: [PATCH 2/7] MP1-5180: Add HEVC support to BDPlayer --- mediaportal/Core/Player/BDPlayer.cs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/mediaportal/Core/Player/BDPlayer.cs b/mediaportal/Core/Player/BDPlayer.cs index 516148fdb93..d617cebd413 100644 --- a/mediaportal/Core/Player/BDPlayer.cs +++ b/mediaportal/Core/Player/BDPlayer.cs @@ -244,6 +244,7 @@ public BDFilterConfig() public string VideoMPEG { get; set; } public string VideoH264 { get; set; } public string VideoVC1 { get; set; } + public string VideoHEVC { get; set; } public string Audio { get; set; } //public string AudioAAC { get; set; } //public string AudioDDPlus { get; set; } @@ -1988,6 +1989,7 @@ protected virtual BDFilterConfig GetFilterConfiguration() //filterConfig.AudioDDPlus = xmlreader.GetValueAsString("bdplayer", "ddplusaudiocodec", ""); filterConfig.VideoH264 = xmlreader.GetValueAsString("bdplayer", "h264videocodec", ""); filterConfig.VideoVC1 = xmlreader.GetValueAsString("bdplayer", "vc1videocodec", ""); + filterConfig.VideoHEVC = xmlreader.GetValueAsString("bdplayer", "hevcvideocodec", ""); filterConfig.AudioRenderer = xmlreader.GetValueAsString("bdplayer", "audiorenderer", "Default DirectSound Device"); // get AR setting @@ -2714,6 +2716,10 @@ protected string MatchFilters(string format) { return filterConfig.VideoVC1; } + else if (_currentVideoFormat == BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_HEVC) + { + return filterConfig.VideoHEVC; + } else { return filterConfig.VideoH264; @@ -3234,7 +3240,16 @@ private void SetVideoDecoder() { ExportGuidFilterAndRelease(filterConfig.VideoH264, BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_H264); - if (filterConfig.VideoMPEG != filterConfig.VideoH264) + if (filterConfig.VideoHEVC != filterConfig.VideoH264) + { + ExportGuidFilterAndRelease(filterConfig.VideoHEVC, BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_HEVC); + } + else + { + _ireader.SetVideoDecoder((int)BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_HEVC, ref GuidFilter); + } + + if (filterConfig.VideoMPEG != filterConfig.VideoH264 || filterConfig.VideoMPEG != filterConfig.VideoHEVC) { ExportGuidFilterAndRelease(filterConfig.VideoMPEG, BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_MPEG2); } @@ -3243,7 +3258,7 @@ private void SetVideoDecoder() _ireader.SetVideoDecoder((int)BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_MPEG2, ref GuidFilter); } - if (filterConfig.VideoVC1 != filterConfig.VideoH264 || filterConfig.VideoVC1 != filterConfig.VideoMPEG) + if (filterConfig.VideoVC1 != filterConfig.VideoH264 || filterConfig.VideoVC1 != filterConfig.VideoHEVC || filterConfig.VideoVC1 != filterConfig.VideoMPEG) { ExportGuidFilterAndRelease(filterConfig.VideoVC1, BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_VC1); } @@ -3495,6 +3510,8 @@ protected string VideoFormattoString(VideoFormat videoFormat) return "1080p"; case VideoFormat.BLURAY_VIDEO_FORMAT_576P: return "576p"; + case VideoFormat.BLURAY_VIDEO_FORMAT_2160P: + return "2160p"; default: return Strings.Unknown; } @@ -3528,6 +3545,8 @@ protected string StreamTypetoString(BluRayStreamFormats stream) return "H264"; case BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_VC1: return "VC1"; + case BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_HEVC: + return "HEVC"; } return Strings.Unknown; } From e7a656ed9a3f56f742744fe284a7a43c48fb7db3 Mon Sep 17 00:00:00 2001 From: epbk Date: Fri, 3 Nov 2023 19:56:20 +0100 Subject: [PATCH 3/7] MP1-5180: BDReader: Fix video/audio synchronization upon start of the playback --- DirectShowFilters/BDReader/source/Clip.cpp | 89 +++++++++++----------- DirectShowFilters/BDReader/source/Clip.h | 16 ++-- 2 files changed, 51 insertions(+), 54 deletions(-) diff --git a/DirectShowFilters/BDReader/source/Clip.cpp b/DirectShowFilters/BDReader/source/Clip.cpp index ef4c7f80bf6..06c57605177 100644 --- a/DirectShowFilters/BDReader/source/Clip.cpp +++ b/DirectShowFilters/BDReader/source/Clip.cpp @@ -43,23 +43,21 @@ CClip::CClip(int clipNumber, int playlistNumber, REFERENCE_TIME firstPacketTime, audioPlaybackPosition = playlistFirstPacketTime; videoPlaybackPosition = playlistFirstPacketTime; - earliestPacketAccepted = _I64_MAX; + m_rtEarliestPacketAccepted = _I64_MAX; firstVideoPosition = _I64_MAX; firstAudioPosition = _I64_MAX; clipDuration = duration; - clipPlaylistOffset = totalStreamOffset; + m_rtClipPlaylistOffset = totalStreamOffset; m_rtStreamStartOffset = streamStartOffset; m_playlistOffset = clipOffset; m_rtPlayedDuration = 0; m_rtPrevAudioStart = 0; - m_rtClipVideoStartingOffset = 0LL; - m_rtClipAudioStartingOffset = 0LL; - - m_bCalculateAudioOffset = true; - m_bCalculateVideoOffset = true; - + m_rtClipStartingOffset = 0LL; + + m_bCalculateOffset = true; + noAudio =! audioPresent; clipInterrupted = interrupted; @@ -70,8 +68,8 @@ CClip::CClip(int clipNumber, int playlistNumber, REFERENCE_TIME firstPacketTime, firstAudio = true; firstVideo = true; - firstPacketAccepted = false; - firstPacketReturned = false; + m_bFirstPacketAccepted = false; + m_bFirstPacketReturned = false; clipReset = false; //LogDebug("CClip:: New Clip (%d,%d) stream Offset %I64d", nPlaylist, nClip, totalStreamOffset); @@ -94,8 +92,8 @@ Packet* CClip::ReturnNextAudioPacket(REFERENCE_TIME playlistOffset) if (noAudio) { ret = GenerateFakeAudio(audioPlaybackPosition); - if (earliestPacketAccepted == INT64_MAX) - earliestPacketAccepted = audioPlaybackPosition; + if (m_rtEarliestPacketAccepted == INT64_MAX) + m_rtEarliestPacketAccepted = audioPlaybackPosition; } else { @@ -122,20 +120,20 @@ Packet* CClip::ReturnNextAudioPacket(REFERENCE_TIME playlistOffset) if (clipInterrupted) ret->nNewSegment |= NS_INTERRUPTED; - if (m_bCalculateAudioOffset && (abs(earliestPacketAccepted - ret->rtStart) > 0)) - m_rtClipAudioStartingOffset = earliestPacketAccepted - ret->rtStart; + if (m_bCalculateOffset && (abs(m_rtEarliestPacketAccepted - ret->rtStart) > 0)) + m_rtClipStartingOffset = m_rtEarliestPacketAccepted - ret->rtStart; - m_bCalculateAudioOffset = false; + m_bCalculateOffset = false; } - if (!firstPacketReturned) - firstPacketReturned = true; + if (!m_bFirstPacketReturned) + m_bFirstPacketReturned = true; ret->rtPlaylistTime = ret->rtStart - m_playlistOffset; - ret->rtClipStartTime = ret->rtStart - earliestPacketAccepted + m_rtClipAudioStartingOffset; - ret->rtStart += clipPlaylistOffset - earliestPacketAccepted + m_rtClipAudioStartingOffset; - ret->rtStop += clipPlaylistOffset - earliestPacketAccepted + m_rtClipAudioStartingOffset; + ret->rtClipStartTime = ret->rtStart - m_rtEarliestPacketAccepted + m_rtClipStartingOffset; + ret->rtStart += m_rtClipPlaylistOffset - m_rtEarliestPacketAccepted + m_rtClipStartingOffset; + ret->rtStop += m_rtClipPlaylistOffset - m_rtEarliestPacketAccepted + m_rtClipStartingOffset; if (m_rtPrevAudioStart == 0) m_rtPrevAudioStart = ret->rtStart; @@ -178,10 +176,10 @@ Packet* CClip::ReturnNextVideoPacket(REFERENCE_TIME playlistOffset) firstVideo = false; ret->pmt = CreateMediaType(m_videoPmt); - if (m_bCalculateVideoOffset && (abs(earliestPacketAccepted - ret->rtStart) > 0)) - m_rtClipVideoStartingOffset = earliestPacketAccepted - ret->rtStart; + if (m_bCalculateOffset && (abs(m_rtEarliestPacketAccepted - ret->rtStart) > 0)) + m_rtClipStartingOffset = m_rtEarliestPacketAccepted - ret->rtStart; - m_bCalculateVideoOffset = false; + m_bCalculateOffset = false; } if (ret->rtStart > videoPlaybackPosition) @@ -190,14 +188,14 @@ Packet* CClip::ReturnNextVideoPacket(REFERENCE_TIME playlistOffset) //LogDebug("Videoplayback position (%d,%d) %I64d", nPlaylist, nClip, videoPlaybackPosition); } - if (!firstPacketReturned) - firstPacketReturned = true; + if (!m_bFirstPacketReturned) + m_bFirstPacketReturned = true; ret->rtPlaylistTime = ret->rtStart - m_playlistOffset; - ret->rtClipStartTime = ret->rtStart - earliestPacketAccepted + m_rtClipVideoStartingOffset; - ret->rtStart += clipPlaylistOffset - earliestPacketAccepted + m_rtClipVideoStartingOffset; - ret->rtStop += clipPlaylistOffset - earliestPacketAccepted + m_rtClipVideoStartingOffset; + ret->rtClipStartTime = ret->rtStart - m_rtEarliestPacketAccepted + m_rtClipStartingOffset; + ret->rtStart += m_rtClipPlaylistOffset - m_rtEarliestPacketAccepted + m_rtClipStartingOffset; + ret->rtStop += m_rtClipPlaylistOffset - m_rtEarliestPacketAccepted + m_rtClipStartingOffset; } } // LogDebug("Clip: vid: return Packet rtStart: %I64d offset: %I64d seekRequired %d",ret->rtStart, ret->rtOffset,ret->bSeekRequired); @@ -245,10 +243,10 @@ Packet* CClip::GenerateFakeAudio(REFERENCE_TIME rtStart) packet->pmt = CreateMediaType(&pmt); } - if (earliestPacketAccepted == INT64_MAX) - earliestPacketAccepted = audioPlaybackPosition; + if (m_rtEarliestPacketAccepted == INT64_MAX) + m_rtEarliestPacketAccepted = audioPlaybackPosition; - firstPacketAccepted = true; + m_bFirstPacketAccepted = true; lastAudioPosition += FAKE_AUDIO_DURATION; audioPlaybackPosition += FAKE_AUDIO_DURATION; @@ -274,10 +272,12 @@ bool CClip::AcceptAudioPacket(Packet* packet) else { //CAutoLock lock(m_sectionRead); - if (!firstPacketReturned) + if (!m_bFirstPacketReturned) { - if (earliestPacketAccepted > packet->rtStart) earliestPacketAccepted = packet->rtStart; - firstPacketAccepted = true; + if (m_rtEarliestPacketAccepted > packet->rtStart) + m_rtEarliestPacketAccepted = packet->rtStart; + + m_bFirstPacketAccepted = true; } packet->nClipNumber = nClip; @@ -304,12 +304,12 @@ bool CClip::AcceptVideoPacket(Packet* packet) } else { - if (!firstPacketReturned && packet->rtStart != Packet::INVALID_TIME && earliestPacketAccepted > packet->rtStart) - earliestPacketAccepted = packet->rtStart; + if (!m_bFirstPacketReturned && packet->rtStart != Packet::INVALID_TIME && m_rtEarliestPacketAccepted > packet->rtStart) + m_rtEarliestPacketAccepted = packet->rtStart; - if (!firstPacketAccepted && packet->rtStart != Packet::INVALID_TIME) + if (!m_bFirstPacketAccepted && packet->rtStart != Packet::INVALID_TIME) { - firstPacketAccepted = true; + m_bFirstPacketAccepted = true; lastVideoPosition = packet->rtStart; } @@ -392,23 +392,22 @@ void CClip::Reset(REFERENCE_TIME totalStreamOffset) lastVideoPosition = playlistFirstPacketTime; lastAudioPosition = playlistFirstPacketTime; - firstPacketAccepted ? clipReset = true : clipReset = false; + m_bFirstPacketAccepted ? clipReset = true : clipReset = false; - clipPlaylistOffset = totalStreamOffset; + m_rtClipPlaylistOffset = totalStreamOffset; audioPlaybackPosition = playlistFirstPacketTime; videoPlaybackPosition = playlistFirstPacketTime; - m_rtClipAudioStartingOffset = 0LL; - m_rtClipVideoStartingOffset = 0LL; + m_rtClipStartingOffset = 0LL; - earliestPacketAccepted = INT64_MAX; + m_rtEarliestPacketAccepted = INT64_MAX; superseded = NO_SUPERSEDE; firstAudio = true; firstVideo = true; - firstPacketAccepted = false; - firstPacketReturned = false; + m_bFirstPacketAccepted = false; + m_bFirstPacketReturned = false; } bool CClip::HasAudio() diff --git a/DirectShowFilters/BDReader/source/Clip.h b/DirectShowFilters/BDReader/source/Clip.h index 79aeb09569f..cb9cbd5bdd6 100644 --- a/DirectShowFilters/BDReader/source/Clip.h +++ b/DirectShowFilters/BDReader/source/Clip.h @@ -63,7 +63,7 @@ class CClip void Supersede(int supersedeType); bool IsSuperseded(int supersedeType); REFERENCE_TIME playlistFirstPacketTime; - REFERENCE_TIME clipPlaylistOffset; + REFERENCE_TIME m_rtClipPlaylistOffset; void Reset(REFERENCE_TIME totalStreamOffset); bool HasAudio(); bool HasVideo(); @@ -85,7 +85,7 @@ class CClip // starttime of the last video packet returned from the clip to the pin REFERENCE_TIME videoPlaybackPosition; - REFERENCE_TIME earliestPacketAccepted; + REFERENCE_TIME m_rtEarliestPacketAccepted; // Clip duration as provided by libbluray REFERENCE_TIME clipDuration; @@ -98,9 +98,8 @@ class CClip // Accurate clip starting time (when known). // Not set when selecting chapter from the menu - REFERENCE_TIME m_rtClipAudioStartingOffset; - REFERENCE_TIME m_rtClipVideoStartingOffset; - + REFERENCE_TIME m_rtClipStartingOffset; + // true would indicate that this is the first audio packet bool firstAudio; // true would indicate that this is the first video packet @@ -120,13 +119,12 @@ class CClip CCritSec m_sectionVectorAudio; CCritSec m_sectionVectorVideo; - bool m_bCalculateAudioOffset; - bool m_bCalculateVideoOffset; + bool m_bCalculateOffset; // indicates if this is the first packet to be buffered in clip - bool firstPacketAccepted; + bool m_bFirstPacketAccepted; // indicates if this is the first packet to be returned from the clip - bool firstPacketReturned; + bool m_bFirstPacketReturned; REFERENCE_TIME m_rtPrevAudioStart; REFERENCE_TIME m_rtPlayedDuration; // Do not zero on reset as this should be cumulative From 4b16bdc267402744f3716020102fab27627fbc4d Mon Sep 17 00:00:00 2001 From: epbk Date: Fri, 3 Nov 2023 20:13:51 +0100 Subject: [PATCH 4/7] MP1-5180: BDReader: Add HEVC support --- .../BDReader/source/BDReader.cpp | 1 + .../BDReader/source/DeMultiplexer.cpp | 26 +- .../BDReader/source/FrameHeaderParser.cpp | 357 ++++++++++++++++++ .../BDReader/source/FrameHeaderParser.h | 27 ++ .../BDReader/source/H264Nalu.cpp | 11 +- DirectShowFilters/BDReader/source/H264Nalu.h | 86 ++++- .../BDReader/source/StreamParser.cpp | 14 + .../BDReader/source/VideoPin.cpp | 25 ++ DirectShowFilters/BDReader/source/VideoPin.h | 1 + .../BDReader/source/mediaformats.h | 1 + 10 files changed, 531 insertions(+), 18 deletions(-) diff --git a/DirectShowFilters/BDReader/source/BDReader.cpp b/DirectShowFilters/BDReader/source/BDReader.cpp index 7ed561c2b9f..37017dc6cf1 100644 --- a/DirectShowFilters/BDReader/source/BDReader.cpp +++ b/DirectShowFilters/BDReader/source/BDReader.cpp @@ -319,6 +319,7 @@ STDMETHODIMP CBDReaderFilter::SetVideoDecoder(int format, GUID* decoder) { if (format != BLURAY_STREAM_TYPE_VIDEO_H264 && format != BLURAY_STREAM_TYPE_VIDEO_VC1 && + format != BLURAY_STREAM_TYPE_VIDEO_HEVC && format != BLURAY_STREAM_TYPE_VIDEO_MPEG2) return E_INVALIDARG; diff --git a/DirectShowFilters/BDReader/source/DeMultiplexer.cpp b/DirectShowFilters/BDReader/source/DeMultiplexer.cpp index 957a7fb9c22..5b94182ed20 100644 --- a/DirectShowFilters/BDReader/source/DeMultiplexer.cpp +++ b/DirectShowFilters/BDReader/source/DeMultiplexer.cpp @@ -812,7 +812,7 @@ void CDeMultiplexer::FlushPESBuffers(bool bDiscardData, bool bSetCurrentClipFill if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_MPEG1 || m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_MPEG2) FillVideoMPEG2(NULL, NULL, true); - else if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_H264) + else if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_H264 || m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_HEVC) FillVideoH264PESPacket(NULL, m_pBuild, true); else if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_VC1) FillVideoVC1PESPacket(NULL, m_pBuild, true); @@ -996,10 +996,22 @@ void CDeMultiplexer::FillVideoH264PESPacket(CTsHeader* header, CAutoPtr if (!pData) continue; - if ((pData[4]&0x1f) == 0x09) - m_fHasAccessUnitDelimiters = true; + bool bFlag = false; + if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_HEVC) + { + if (((pData[4] >> 1) & 0x3f) == HEVC_NAL_AUD) + { + m_fHasAccessUnitDelimiters = true; + bFlag = true; + } + } + else if ((pData[4] & 0x1f) == NALU_TYPE_AUD) + { + m_fHasAccessUnitDelimiters = true; + bFlag = true; + } - if ((pData[4]&0x1f) == 0x09 || !m_fHasAccessUnitDelimiters && pPacket->rtStart != Packet::INVALID_TIME) + if (bFlag || !m_fHasAccessUnitDelimiters && pPacket->rtStart != Packet::INVALID_TIME) { p = m_pl.RemoveHead(); @@ -1263,8 +1275,8 @@ void CDeMultiplexer::FillVideoH264(CTsHeader* header, byte* tsPacket) if (m_pBuild->GetCount() && m_videoServiceType != BLURAY_STREAM_TYPE_VIDEO_VC1) { - FillVideoH264PESPacket(header, m_pBuild); - m_pBuild.Free(); + FillVideoH264PESPacket(header, m_pBuild); + m_pBuild.Free(); } } @@ -1716,6 +1728,8 @@ char* CDeMultiplexer::StreamFormatAsString(int pStreamType) return "H264"; case BLURAY_STREAM_TYPE_VIDEO_VC1: return "VC1"; + case BLURAY_STREAM_TYPE_VIDEO_HEVC: + return "HEVC"; case BLURAY_STREAM_TYPE_AUDIO_LPCM: return "LPCM"; case BLURAY_STREAM_TYPE_AUDIO_AC3: diff --git a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp index fa2ade00410..7afe5e82e56 100644 --- a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp +++ b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp @@ -35,6 +35,7 @@ #include #include #include +#include "h264nalu.h" // For more details for memory leak detection see the alloctracing.h header #include "..\..\alloctracing.h" @@ -1665,6 +1666,217 @@ bool CFrameHeaderParser::Read(avchdr& h, int len, CMediaType* pmt) return true; } +bool CFrameHeaderParser::Read(hevchdr& h, int len, CMediaType* pmt) +{ + memset(&h, 0, sizeof(h)); + + while (GetRemaining() > 4 && (h.spslen == 0 || h.ppslen == 0)) + { + const int nal_len = BitRead(32); + const INT64 next_nal = GetPos() + nal_len; + + //nalu header + const bool bForbiden = BitRead(1); //forbidden_zero_bit + const HEVC_NALU_TYPE nal_type = (HEVC_NALU_TYPE)BitRead(6); //nal_unit_type + const int idLayer = BitRead(6); //nuh_layer_id + const int iTempId = BitRead(3); //nuh_temporal_id_plus1 + + if (bForbiden || idLayer > 0 || (nal_type != HEVC_NAL_SPS && nal_type != HEVC_NAL_PPS && nal_type != HEVC_NAL_VPS)) + { + Seek(next_nal); + continue; + } + if (nal_type == HEVC_NAL_SPS) + { + h.spspos = GetPos() - 6; + h.spslen = next_nal - h.spspos; + + BYTE buff[MAX_SPS]; + BYTE buffTmp[MAX_SPS]; + CGolombBuffer gb(buff, MAX_SPS); + ByteRead((BYTE*)buffTmp, min(MAX_SPS, GetRemaining())); + RemoveMpegEscapeCode(buff, buffTmp, MAX_SPS); + + int tmp = gb.BitRead(4); //sps_video_parameter_set_id + int sps_max_sub_layers_minus1 = gb.BitRead(3); //sps_max_sub_layers_minus1 + tmp = gb.BitRead(1); //sps_temporal_id_nesting_flag + + profile_tier_level(1, sps_max_sub_layers_minus1, &gb); + + tmp = gb.UExpGolombRead(); //sps_seq_parameter_set_id + tmp = gb.UExpGolombRead(); //chroma_format_idc + + if (tmp == 3) + gb.BitRead(1); //separate_colour_plane_flag + + h.width = gb.UExpGolombRead(); //width + h.height = gb.UExpGolombRead(); //height + + //if (gb.BitRead(1)) // pic_conformance_flag + //{ + // tmp = gb.UExpGolombRead(); //conf_win_left_offset + // tmp = gb.UExpGolombRead(); //conf_win_right_offset + // tmp = gb.UExpGolombRead(); //conf_win_top_offset + // tmp = gb.UExpGolombRead(); //conf_win_bottom_offset + //} + + //tmp = gb.UExpGolombRead(); //bit_depth_luma_minus8 + //tmp = gb.UExpGolombRead(); //bit_depth_chroma_minus8 + //tmp = gb.UExpGolombRead(); //log2_max_pic_order_cnt_lsb_minus4 + } + else if (nal_type == HEVC_NAL_PPS) + { + h.ppspos = GetPos() - 6; + h.ppslen = next_nal - h.ppspos; + } + else if (nal_type == HEVC_NAL_VPS) + { + BYTE buff[MAX_SPS]; + BYTE buffTmp[MAX_SPS]; + CGolombBuffer gb(buff, MAX_SPS); + ByteRead((BYTE*)buffTmp, min(MAX_SPS, GetRemaining())); + RemoveMpegEscapeCode(buff, buffTmp, MAX_SPS); + + int tmp = gb.BitRead(4); //vps_video_parameter_set_id + tmp = gb.BitRead(1); //vps_base_layer_internal_flag + tmp = gb.BitRead(1); //vps_base_layer_available_flag + tmp = gb.BitRead(6); //vps_max_layers_minus1 + int iSubLayers = gb.BitRead(3); //vps_max_sub_layers_minus1 + tmp = gb.BitRead(1); //vps_temporal_id_nesting_flag + tmp = gb.BitRead(16); //vps_reserved_0xffff_16bits + + + profile_tier_level(true, iSubLayers, &gb); + + bool bFlag = gb.BitRead(1); //vps_sub_layer_ordering_info_present_flag + + for (int i = bFlag ? 0 : iSubLayers; i <= iSubLayers; i++) + { + tmp = gb.UExpGolombRead(); //vps_max_dec_pic_buffering_minus1 + tmp = gb.UExpGolombRead(); //vps_max_num_reorder_pics + tmp = gb.UExpGolombRead(); //vps_max_latency_increase_plus1 + } + + int iMaxLayer = gb.BitRead(6); //vps_max_layer_id + int iLayersSet = gb.UExpGolombRead(); //vps_num_layer_sets_minus1 + + for (int i = 1; i <= iLayersSet; i++) + for (int j = 0; j <= iMaxLayer; j++) + tmp = gb.BitRead(1); //layer_id_included_flag + + bFlag = gb.BitRead(1); //vps_timing_info_present_flag + if (bFlag) + { + int vps_num_units_in_tick = gb.BitRead(32); //vps_num_units_in_tick + int vps_time_scale = gb.BitRead(32); //vps_time_scale + + h.AvgTimePerFrame = (10000000I64 * vps_num_units_in_tick) / vps_time_scale; + + bFlag = gb.BitRead(1); //vps_poc_proportional_to_timing_flag + if (bFlag) + tmp = gb.UExpGolombRead(); //vps_num_ticks_poc_diff_one_minus1 + + tmp = gb.UExpGolombRead(); //vps_num_hrd_parameters + } + } + + Seek(next_nal); + } + + if (!h.spspos || !h.spslen || !h.ppspos || !h.ppslen || h.height < 300 || h.width < 300 || h.AvgTimePerFrame < 1000) + return(false); + + if (!pmt) + return(true); + + h.ar = 255; //ex + h.arx = 1; //ex + h.ary = 1; //ex + + //h.profile = 2; //ex + //h.level = 153; //ex + + { + + int extra = 2 + h.spslen - 4 + 2 + h.ppslen - 4; + pmt->SetType(&MEDIATYPE_Video); + //pmt->SetSubtype(&MEDIASUBTYPE_H264); + pmt->SetSubtype(&HEVC_SubType); + pmt->formattype = FORMAT_MPEG2_VIDEO; + //pmt->bTemporalCompression = true; //ex + + int len = FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + extra; + MPEG2VIDEOINFO* vi = (MPEG2VIDEOINFO*)pmt->AllocFormatBuffer(len); + memset(vi, 0, len); + vi->hdr.AvgTimePerFrame = h.AvgTimePerFrame; + + /* + h.ar=h.width/h.height; + struct {DWORD x, y;} ar[] = {{h.width,h.height},{4,3},{16,9},{221,100},{h.width,h.height}}; + int i = min(max(h.ar, 1), 5)-1; + */ + struct { DWORD x, y; } ar[] = { {1,1},{1,1},{12,11},{10,11},{16,11},{40,33},{24,11},{20,11},{32,11},{80,33},{18,11},{15,11},{64,33},{160,99},{1,1},{1,1} }; + if (h.ar == 255) + { + // make sure that both are 0 or none + if (h.arx == 0 || h.ary == 0) + h.arx = h.ary = 0; + // h.arx and h.ary now contain sample aspect ratio + } + else if (h.ar < 1 || h.ar > 13) + { + // aspect ratio unspecified or reserved + h.ar = 0; + h.arx = h.ary = 0; + } + else + { + // use preset aspect ratio + h.arx = ar[h.ar].x; + h.ary = ar[h.ar].y; + } + + h.arx *= h.width; + h.ary *= h.height; + + DWORD a = h.arx, b = h.ary; + while (a) { DWORD tmp = a; a = b % tmp; b = tmp; } + if (b) h.arx /= b, h.ary /= b; + vi->hdr.dwPictAspectRatioX = h.arx; + vi->hdr.dwPictAspectRatioY = h.ary; + vi->hdr.bmiHeader.biSize = sizeof(vi->hdr.bmiHeader); + vi->hdr.bmiHeader.biWidth = h.width; + vi->hdr.bmiHeader.biHeight = h.height; + //vi->hdr.bmiHeader.biCompression = '462h'; + vi->hdr.bmiHeader.biCompression = 'CVEH'; + vi->hdr.bmiHeader.biPlanes = 1; + vi->hdr.bmiHeader.biBitCount = 24; + vi->hdr.bmiHeader.biClrUsed = 0; + vi->dwProfile = h.profile; + vi->dwFlags = 4; // ? + vi->dwLevel = h.level; + vi->cbSequenceHeader = extra; + vi->dwStartTimeCode = 0; + //vi->hdr.rcSource.right = h.width; //ex + //vi->hdr.rcSource.bottom = h.height; //ex + //vi->hdr.rcTarget.right = h.width; //ex + //vi->hdr.rcTarget.bottom = h.height; //ex + BYTE* p = (BYTE*)&vi->dwSequenceHeader[0]; + *p++ = (h.spslen - 4) >> 8; + *p++ = (h.spslen - 4) & 0xff; + Seek(h.spspos + 4); + ByteRead(p, h.spslen - 4); + p += h.spslen - 4; + *p++ = (h.ppslen - 4) >> 8; + *p++ = (h.ppslen - 4) & 0xff; + Seek(h.ppspos + 4); + ByteRead(p, h.ppslen - 4); + p += h.ppslen - 4; + pmt->SetFormat((BYTE*)vi, len); + } + + return true; +} bool CFrameHeaderParser::Read(vc1hdr& h, int len, CMediaType* pmt) { @@ -2043,3 +2255,148 @@ void CFrameHeaderParser::DumpAvcHeader(avchdr h) LogDebug("================================="); } +void CFrameHeaderParser::profile_tier_level(bool profilePresentFlag, int maxNumSubLayersMinus1, CGolombBuffer* gb) +{ + if (profilePresentFlag) + { + byte general_profile_compatibility_flag[32]; + + gb->BitRead(2); //general_profile_space u(2) + gb->BitRead(1); //general_tier_flag u(1) + int general_profile_idc = gb->BitRead(5); //general_profile_idc u(5) + for (int j = 0; j < 32; j++) + general_profile_compatibility_flag[j] = gb->BitRead(1);//u(1) + + gb->BitRead(1); //general_progressive_source_flag u(1) + gb->BitRead(1); //general_interlaced_source_flag u(1) + gb->BitRead(1); //general_non_packed_constraint_flag u(1) + gb->BitRead(1); //general_frame_only_constraint_flag u(1) + if (general_profile_idc == 4 || general_profile_compatibility_flag[4] + || general_profile_idc == 5 || general_profile_compatibility_flag[5] + || general_profile_idc == 6 || general_profile_compatibility_flag[6] + || general_profile_idc == 7 || general_profile_compatibility_flag[7] + || general_profile_idc == 8 || general_profile_compatibility_flag[8] + || general_profile_idc == 9 || general_profile_compatibility_flag[9] + || general_profile_idc == 10 || general_profile_compatibility_flag[10]) + { + /* The number of bits in this syntax structure is not affected by this condition */ + gb->BitRead(1); //general_max_12bit_constraint_flag u(1) + gb->BitRead(1); //general_max_10bit_constraint_flag u(1) + gb->BitRead(1); //general_max_8bit_constraint_flag u(1) + gb->BitRead(1); //general_max_422chroma_constraint_flag u(1) + gb->BitRead(1); //general_max_420chroma_constraint_flag u(1) + gb->BitRead(1); //general_max_monochrome_constraint_flag u(1) + gb->BitRead(1); //general_intra_constraint_flag u(1) + gb->BitRead(1); //general_one_picture_only_constraint_flag u(1) + gb->BitRead(1); //general_lower_bit_rate_constraint_flag u(1) + if (general_profile_idc == 5 || general_profile_compatibility_flag[5] + || general_profile_idc == 9 || general_profile_compatibility_flag[9] || + general_profile_idc == 10 || general_profile_compatibility_flag[10]) { + gb->BitRead(1); //general_max_14bit_constraint_flag u(1) + gb->BitRead(33); //general_reserved_zero_33bits u(33) + } + else + gb->BitRead(34); //general_reserved_zero_34bits u(34) + } + else if (general_profile_idc == 2 || general_profile_compatibility_flag[2]) + { + gb->BitRead(7); //general_reserved_zero_7bits u(7) + gb->BitRead(1); //general_one_picture_only_constraint_flag u(1) + gb->BitRead(35); //general_reserved_zero_35bits u(35) + } + else + + gb->BitRead(43); //general_reserved_zero_43bits u(43) + if ((general_profile_idc >= 1 && general_profile_idc <= 5) + || general_profile_idc == 9 + || general_profile_compatibility_flag[1] || general_profile_compatibility_flag[2] + || general_profile_compatibility_flag[3] || general_profile_compatibility_flag[4] + || general_profile_compatibility_flag[5] || general_profile_compatibility_flag[9]) + /* The number of bits in this syntax structure is not affected by this condition */ + gb->BitRead(1); //general_inbld_flag u(1) + else + gb->BitRead(1); //general_reserved_zero_bit u(1) + } + gb->BitRead(8); //general_level_idc u(8) + + byte sub_layer_profile_present_flag[8]; + byte sub_layer_profile_idc[8]; + byte sub_layer_profile_compatibility_flag[8][32]; + byte sub_layer_level_present_flag[8]; + + for (int i = 0; i < maxNumSubLayersMinus1; i++) + { + sub_layer_profile_present_flag[i] = (byte)gb->BitRead(1); //sub_layer_profile_present_flag[i] u(1) + sub_layer_level_present_flag[i] = (byte)gb->BitRead(1); //sub_layer_level_present_flag[i] u(1) + } + if (maxNumSubLayersMinus1 > 0) + for (int i = maxNumSubLayersMinus1; i < 8; i++) + gb->BitRead(2); //reserved_zero_2bits[i] u(2) + + for (int i = 0; i < maxNumSubLayersMinus1; i++) + { + if (sub_layer_profile_present_flag[i]) + { + gb->BitRead(2); //sub_layer_profile_space[i] u(2) + gb->BitRead(1); //sub_layer_tier_flag[i] u(1) + sub_layer_profile_idc[i] = (byte)gb->BitRead(5); //sub_layer_profile_idc[i] u(5) + + for (int j = 0; j < 32; j++) + sub_layer_profile_compatibility_flag[i][j] = (byte)gb->BitRead(1); //sub_layer_profile_compatibility_flag[i][j] u(1) + + gb->BitRead(1); //sub_layer_progressive_source_flag[i] u(1) + gb->BitRead(1); //sub_layer_interlaced_source_flag[i] u(1) + gb->BitRead(1); //sub_layer_non_packed_constraint_flag[i] u(1) + gb->BitRead(1); //sub_layer_frame_only_constraint_flag[i] u(1) + if (sub_layer_profile_idc[i] == 4 || sub_layer_profile_compatibility_flag[i][4] + || sub_layer_profile_idc[i] == 5 || sub_layer_profile_compatibility_flag[i][5] + || sub_layer_profile_idc[i] == 6 || sub_layer_profile_compatibility_flag[i][6] + || sub_layer_profile_idc[i] == 7 || sub_layer_profile_compatibility_flag[i][7] + || sub_layer_profile_idc[i] == 8 || sub_layer_profile_compatibility_flag[i][8] + || sub_layer_profile_idc[i] == 9 || sub_layer_profile_compatibility_flag[i][9] + || sub_layer_profile_idc[i] == 10 || sub_layer_profile_compatibility_flag[i][10] + ) + { + /* The number of bits in this syntax structure is not affected by this condition */ + gb->BitRead(1); //sub_layer_max_12bit_constraint_flag[i] u(1) + gb->BitRead(1); //sub_layer_max_10bit_constraint_flag[i] u(1) + gb->BitRead(1); //sub_layer_max_8bit_constraint_flag[i] u(1) + gb->BitRead(1); //sub_layer_max_422chroma_constraint_flag[i] u(1) + gb->BitRead(1); //sub_layer_max_420chroma_constraint_flag[i] u(1) + gb->BitRead(1); //sub_layer_max_monochrome_constraint_flag[i] u(1) + gb->BitRead(1); //sub_layer_intra_constraint_flag[i] u(1) + gb->BitRead(1); //sub_layer_one_picture_only_constraint_flag[i] u(1) + gb->BitRead(1); //sub_layer_lower_bit_rate_constraint_flag[i] u(1) + + if (sub_layer_profile_idc[i] == 5 || sub_layer_profile_compatibility_flag[i][5]) + { + gb->BitRead(1); //sub_layer_max_14bit_constraint_flag[i] u(1) + gb->BitRead(33); //sub_layer_reserved_zero_33bits[i] u(33) + } + else + gb->BitRead(34); //sub_layer_reserved_zero_34bits[i] u(34) + } + else if (sub_layer_profile_idc[i] == 2 || sub_layer_profile_compatibility_flag[i][2]) + { + gb->BitRead(7); //sub_layer_reserved_zero_7bits[i] u(7) + gb->BitRead(1); //sub_layer_one_picture_only_constraint_flag[i] u(1) + gb->BitRead(35); //sub_layer_reserved_zero_35bits[i] u(35) + } + else + gb->BitRead(43); //sub_layer_reserved_zero_43bits[i] u(43) + if ((sub_layer_profile_idc[i] >= 1 && sub_layer_profile_idc[i] <= 5) + || sub_layer_profile_idc[i] == 9 || sub_layer_profile_compatibility_flag[1] + || sub_layer_profile_compatibility_flag[2] || sub_layer_profile_compatibility_flag[3] + || sub_layer_profile_compatibility_flag[4] || sub_layer_profile_compatibility_flag[5] + || sub_layer_profile_compatibility_flag[9] + ) + /* The number of bits in this syntax structure is not affected by this condition */ + gb->BitRead(1); //sub_layer_inbld_flag[i] u(1) + else + gb->BitRead(1); // sub_layer_reserved_zero_bit[i] u(1) + } + + if (sub_layer_level_present_flag[i]) + gb->BitRead(8); //sub_layer_level_idc[i] u(8) + } +} \ No newline at end of file diff --git a/DirectShowFilters/BDReader/source/FrameHeaderParser.h b/DirectShowFilters/BDReader/source/FrameHeaderParser.h index f539e750fa7..b1a5414d6b7 100644 --- a/DirectShowFilters/BDReader/source/FrameHeaderParser.h +++ b/DirectShowFilters/BDReader/source/FrameHeaderParser.h @@ -387,6 +387,30 @@ enum mpeg_t {mpegunk, mpeg1, mpeg2}; }sar; }; + struct hevchdr + { + BYTE profile, level; + unsigned int width, height; + bool progressive; + __int64 spspos, spslen; + __int64 ppspos, ppslen; + __int64 AvgTimePerFrame; + int arx, ary; + BYTE ar; + hevchdr() + { + progressive = true; + spspos = 0; + spslen = 0; + ppspos = 0; + ppslen = 0; + AvgTimePerFrame = 0; + ar = 0; + arx = 0; + ary = 0; + } + }; + struct thdhdr { int stream_type; // 0xBB for MLP, 0xBA for TrueHD @@ -457,6 +481,7 @@ class CFrameHeaderParser:public CGolombBuffer bool Read(trsechdr& h); bool Read(pvahdr& h, bool fSync = true); bool Read(avchdr& h, int len, CMediaType* pmt = NULL); + bool Read(hevchdr& h, int len, CMediaType* pmt); bool Read(vc1hdr& h, int len, CMediaType* pmt = NULL); bool Read(bdlpcmhdr& h, int len, CMediaType* pmt = NULL); bool Read(thdhdr& h, int len, CMediaType* pmt = NULL); @@ -466,6 +491,8 @@ class CFrameHeaderParser:public CGolombBuffer void DumpSequenceHeader(seqhdr h); void DumpAvcHeader(avchdr h); + void profile_tier_level(bool profilePresentFlag, int maxNumSubLayersMinus1, CGolombBuffer* gb); + private: REFERENCE_TIME m_rtPTSOffset; }; diff --git a/DirectShowFilters/BDReader/source/H264Nalu.cpp b/DirectShowFilters/BDReader/source/H264Nalu.cpp index cbf4811ad76..3269b06fcd6 100644 --- a/DirectShowFilters/BDReader/source/H264Nalu.cpp +++ b/DirectShowFilters/BDReader/source/H264Nalu.cpp @@ -99,9 +99,14 @@ bool CH264Nalu::ReadNext() MoveToNextAnnexBStartcode(); } - forbidden_bit = (m_pBuffer[m_nNALDataPos]>>7) & 1; - nal_reference_idc = (m_pBuffer[m_nNALDataPos]>>5) & 3; - nal_unit_type = (NALU_TYPE) (m_pBuffer[m_nNALDataPos] & 0x1f); + //H264 + //forbidden_bit = (m_pBuffer[m_nNALDataPos]>>7) & 1; + //nal_reference_idc = (m_pBuffer[m_nNALDataPos]>>5) & 3; + //nal_unit_type = (NALU_TYPE) (m_pBuffer[m_nNALDataPos] & 0x1f); + + //H265 + //forbidden_bit = (m_pBuffer[m_nNALDataPos] >> 7) & 1; + //nal_unit_type = (HEVC_NALU_TYPE)((m_pBuffer[m_nNALDataPos] >> 1) & 0x3F); return true; } diff --git a/DirectShowFilters/BDReader/source/H264Nalu.h b/DirectShowFilters/BDReader/source/H264Nalu.h index 429a45af307..f261495660a 100644 --- a/DirectShowFilters/BDReader/source/H264Nalu.h +++ b/DirectShowFilters/BDReader/source/H264Nalu.h @@ -38,12 +38,80 @@ typedef enum { NALU_TYPE_FILL = 12 } NALU_TYPE; +typedef enum { + HEVC_NAL_TRAIL_N = 0, + HEVC_NAL_TRAIL_R = 1, + HEVC_NAL_TSA_N = 2, + HEVC_NAL_TSA_R = 3, + HEVC_NAL_STSA_N = 4, + HEVC_NAL_STSA_R = 5, + HEVC_NAL_RADL_N = 6, + HEVC_NAL_RADL_R = 7, + HEVC_NAL_RASL_N = 8, + HEVC_NAL_RASL_R = 9, + HEVC_NAL_VCL_N10 = 10, + HEVC_NAL_VCL_R11 = 11, + HEVC_NAL_VCL_N12 = 12, + HEVC_NAL_VCL_R13 = 13, + HEVC_NAL_VCL_N14 = 14, + HEVC_NAL_VCL_R15 = 15, + HEVC_NAL_BLA_W_LP = 16, + HEVC_NAL_BLA_W_RADL = 17, + HEVC_NAL_BLA_N_LP = 18, + HEVC_NAL_IDR_W_RADL = 19, + HEVC_NAL_IDR_N_LP = 20, + HEVC_NAL_CRA_NUT = 21, + HEVC_NAL_RSV_IRAP_VCL22 = 22, + HEVC_NAL_RSV_IRAP_VCL23 = 23, + HEVC_NAL_RSV_VCL24 = 24, + HEVC_NAL_RSV_VCL25 = 25, + HEVC_NAL_RSV_VCL26 = 26, + HEVC_NAL_RSV_VCL27 = 27, + HEVC_NAL_RSV_VCL28 = 28, + HEVC_NAL_RSV_VCL29 = 29, + HEVC_NAL_RSV_VCL30 = 30, + HEVC_NAL_RSV_VCL31 = 31, + HEVC_NAL_VPS = 32, + HEVC_NAL_SPS = 33, + HEVC_NAL_PPS = 34, + HEVC_NAL_AUD = 35, + HEVC_NAL_EOS_NUT = 36, + HEVC_NAL_EOB_NUT = 37, + HEVC_NAL_FD_NUT = 38, + HEVC_NAL_SEI_PREFIX = 39, + HEVC_NAL_SEI_SUFFIX = 40, + HEVC_NAL_RSV_NVCL41 = 41, + HEVC_NAL_RSV_NVCL42 = 42, + HEVC_NAL_RSV_NVCL43 = 43, + HEVC_NAL_RSV_NVCL44 = 44, + HEVC_NAL_RSV_NVCL45 = 45, + HEVC_NAL_RSV_NVCL46 = 46, + HEVC_NAL_RSV_NVCL47 = 47, + HEVC_NAL_UNSPEC48 = 48, + HEVC_NAL_UNSPEC49 = 49, + HEVC_NAL_UNSPEC50 = 50, + HEVC_NAL_UNSPEC51 = 51, + HEVC_NAL_UNSPEC52 = 52, + HEVC_NAL_UNSPEC53 = 53, + HEVC_NAL_UNSPEC54 = 54, + HEVC_NAL_UNSPEC55 = 55, + HEVC_NAL_UNSPEC56 = 56, + HEVC_NAL_UNSPEC57 = 57, + HEVC_NAL_UNSPEC58 = 58, + HEVC_NAL_UNSPEC59 = 59, + HEVC_NAL_UNSPEC60 = 60, + HEVC_NAL_UNSPEC61 = 61, + HEVC_NAL_UNSPEC62 = 62, + HEVC_NAL_UNSPEC63 = 63, +} HEVC_NALU_TYPE; + + class CH264Nalu { private : - int forbidden_bit; //! should be always FALSE - int nal_reference_idc; //! NALU_PRIORITY_xxxx - NALU_TYPE nal_unit_type; //! NALU_TYPE_xxxx + //int forbidden_bit; //! should be always FALSE + //int nal_reference_idc; //! NALU_PRIORITY_xxxx + //NALU_TYPE nal_unit_type; //! NALU_TYPE_xxxx int m_nNALStartPos; //! NALU start (including startcode / size) int m_nNALDataPos; //! Useful part @@ -61,12 +129,12 @@ private : public : CH264Nalu(); - NALU_TYPE GetType() const { - return nal_unit_type; - }; - bool IsRefFrame() const { - return (nal_reference_idc != 0); - }; + //NALU_TYPE GetType() const { + // return nal_unit_type; + //}; + //bool IsRefFrame() const { + // return (nal_reference_idc != 0); + //}; int GetDataLength() const { return m_nCurPos - m_nNALDataPos; diff --git a/DirectShowFilters/BDReader/source/StreamParser.cpp b/DirectShowFilters/BDReader/source/StreamParser.cpp index 0d554b41338..12c0e555b8f 100644 --- a/DirectShowFilters/BDReader/source/StreamParser.cpp +++ b/DirectShowFilters/BDReader/source/StreamParser.cpp @@ -68,6 +68,20 @@ bool StreamParser::Parse(byte* tsPacket, int serviceType) parsed=true; } } + else if (serviceType == BLURAY_STREAM_TYPE_VIDEO_HEVC) + { + hevchdr hevc; + if (hdrParser.Read(hevc, framesize, &pmt)) + { + basicVideoInfo.width = hevc.width; + basicVideoInfo.height = hevc.height; + basicVideoInfo.fps = 1000 / (hevc.AvgTimePerFrame / 10000); + basicVideoInfo.isInterlaced = 0; + basicVideoInfo.streamType = 4; // HEVC + basicVideoInfo.isValid = true; + parsed = true; + } + } else if (serviceType == BLURAY_STREAM_TYPE_VIDEO_H264) { avchdr avc; diff --git a/DirectShowFilters/BDReader/source/VideoPin.cpp b/DirectShowFilters/BDReader/source/VideoPin.cpp index 8f9117f6568..e71b04604eb 100644 --- a/DirectShowFilters/BDReader/source/VideoPin.cpp +++ b/DirectShowFilters/BDReader/source/VideoPin.cpp @@ -105,6 +105,7 @@ CVideoPin::CVideoPin(LPUNKNOWN pUnk, CBDReaderFilter* pFilter, HRESULT* phr, CCr m_bDoFakeSeek(false), m_bResetToLibSeek(false), m_H264decoder(GUID_NULL), + m_HEVCdecoder(GUID_NULL), m_VC1decoder(GUID_NULL), m_MPEG2decoder(GUID_NULL), m_VC1Override(GUID_NULL), @@ -212,6 +213,12 @@ void CVideoPin::SetVideoDecoder(int format, GUID* decoder) LogDebug("vid: SetVideoDecoder for MPEG2"); LogMediaType(&tmp); } + else if (format == BLURAY_STREAM_TYPE_VIDEO_HEVC) + { + m_HEVCdecoder = tmp.subtype = *decoder; + LogDebug("vid: SetVideoDecoder for HEVC"); + LogMediaType(&tmp); + } else { LogDebug("vid: SetVideoDecoder - trying to set a decoder for invalid format %d", format); @@ -237,6 +244,8 @@ bool CVideoPin::CheckVideoFormat(GUID* pFormat, CLSID* pDecoder) decoder = &m_H264decoder; else if (IsEqualGUID(*pFormat, VC1_SubType)) decoder = &m_VC1decoder; + else if (IsEqualGUID(*pFormat, HEVC_SubType)) + decoder = &m_HEVCdecoder; else if (IsEqualGUID(*pFormat, MEDIASUBTYPE_MPEG2_VIDEO)) decoder = &m_MPEG2decoder; else @@ -741,6 +750,22 @@ HRESULT CVideoPin::FillBuffer(IMediaSample* pSample) pSample->GetPointer(&pSampleBuffer); memcpy(pSampleBuffer, buffer->GetData(), buffer->GetDataSize()); + //Switch to AnnexB for HEVC + if (m_demux.GetVideoServiceType() == BLURAY_STREAM_TYPE_VIDEO_HEVC) + { + int i = buffer->GetDataSize(); + while (i > 0) + { + //size of nalu + int iSize = (*pSampleBuffer << 24) | (*(pSampleBuffer + 1) << 16) | (*(pSampleBuffer + 2) << 8) | (*(pSampleBuffer + 3)); + + *(DWORD*)pSampleBuffer = 0x01000000; //four byte start code + + i -= iSize + 4; + pSampleBuffer += iSize + 4; + } + } + m_nSampleCounter++; #ifdef LOG_VIDEO_PIN_SAMPLES diff --git a/DirectShowFilters/BDReader/source/VideoPin.h b/DirectShowFilters/BDReader/source/VideoPin.h index 1bf5672a56b..534c53f410f 100644 --- a/DirectShowFilters/BDReader/source/VideoPin.h +++ b/DirectShowFilters/BDReader/source/VideoPin.h @@ -96,6 +96,7 @@ class CVideoPin : public CSourceStream, public CSourceSeeking CLSID m_VC1decoder; CLSID m_H264decoder; CLSID m_MPEG2decoder; + CLSID m_HEVCdecoder; CLSID m_currentDecoder; diff --git a/DirectShowFilters/BDReader/source/mediaformats.h b/DirectShowFilters/BDReader/source/mediaformats.h index 66116dae771..3589fd6b8bd 100644 --- a/DirectShowFilters/BDReader/source/mediaformats.h +++ b/DirectShowFilters/BDReader/source/mediaformats.h @@ -90,6 +90,7 @@ static GUID MEDIASUBTYPE_CVD_SUBPICTURE = {0x7b57308f, 0x5154, 0x4c36, 0xb9, 0x3 static GUID MEDIATYPE_Subtitle = {0xe487eb08, 0x6b26, 0x4be9, 0x9d, 0xd3, 0x99, 0x34, 0x34, 0xd3, 0x13, 0xfd}; static GUID MEDIASUBTYPE_PS2_SUB = {0x4f3d3d21, 0x6d7c, 0x4f73, 0xaa, 0x5, 0xe3, 0x97, 0xb5, 0xea, 0xe0, 0xaa}; static GUID H264_SubType = {0x8D2D71CB, 0x243F, 0x45E3, {0xB2, 0xD8, 0x5F, 0xD7, 0x96, 0x7E, 0xC0, 0x9B}}; +static GUID HEVC_SubType = { 0x43564548, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }; static GUID MPG4_SubType = FOURCCMap(MAKEFOURCC('A','V','C','1')); static GUID VC1_SubType = FOURCCMap('1CVW'); static GUID AVC1_SubType = {0x31435641, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}; From 1339dd3e2aecf11f0c63b92f249720a40a7847e7 Mon Sep 17 00:00:00 2001 From: epbk Date: Fri, 3 Nov 2023 20:28:54 +0100 Subject: [PATCH 5/7] MP1-5180: BDReader: Use LPCM media type for PCM BluRay format --- DirectShowFilters/BDReader/source/FrameHeaderParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp index 7afe5e82e56..5747fb31407 100644 --- a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp +++ b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp @@ -2206,10 +2206,10 @@ bool CFrameHeaderParser::Read(bdlpcmhdr& h, int len, CMediaType* pmt) wfe.Samples.wSamplesPerBlock = 0; wfe.Samples.wValidBitsPerSample = bitspersample[h.bitpersample]; - wfe.SubFormat = MEDIASUBTYPE_PCM; + wfe.SubFormat = MEDIASUBTYPE_BD_LPCM_AUDIO; //MEDIASUBTYPE_PCM; pmt->majortype = MEDIATYPE_Audio; - pmt->subtype = MEDIASUBTYPE_PCM; + pmt->subtype = MEDIASUBTYPE_BD_LPCM_AUDIO; //MEDIASUBTYPE_PCM; pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)&wfe, sizeof(wfe)); From 5c5e480c32503f29db83c38fc06695fdcaa6c08c Mon Sep 17 00:00:00 2001 From: epbk Date: Mon, 6 Nov 2023 16:45:02 +0100 Subject: [PATCH 6/7] MP1-5180: BDReader: Use HEVC parser from TsReader project --- .../BDReader/source/DeMultiplexer.cpp | 2 +- .../BDReader/source/FrameHeaderParser.cpp | 375 +++------ .../BDReader/source/FrameHeaderParser.h | 35 +- .../BDReader/source/H264Nalu.cpp | 11 +- DirectShowFilters/BDReader/source/H264Nalu.h | 86 +- .../BDReader/source/HEVC/BitstreamReader.cpp | 189 +++++ .../BDReader/source/HEVC/BitstreamReader.h | 54 ++ .../BDReader/source/HEVC/Hevc.cpp | 339 ++++++++ DirectShowFilters/BDReader/source/HEVC/Hevc.h | 476 +++++++++++ .../BDReader/source/HEVC/HevcNalDecode.cpp | 749 ++++++++++++++++++ .../BDReader/source/HEVC/HevcNalDecode.h | 57 ++ .../BDReader/source/StreamParser.cpp | 3 + 12 files changed, 1993 insertions(+), 383 deletions(-) create mode 100644 DirectShowFilters/BDReader/source/HEVC/BitstreamReader.cpp create mode 100644 DirectShowFilters/BDReader/source/HEVC/BitstreamReader.h create mode 100644 DirectShowFilters/BDReader/source/HEVC/Hevc.cpp create mode 100644 DirectShowFilters/BDReader/source/HEVC/Hevc.h create mode 100644 DirectShowFilters/BDReader/source/HEVC/HevcNalDecode.cpp create mode 100644 DirectShowFilters/BDReader/source/HEVC/HevcNalDecode.h diff --git a/DirectShowFilters/BDReader/source/DeMultiplexer.cpp b/DirectShowFilters/BDReader/source/DeMultiplexer.cpp index 5b94182ed20..771f1df06a0 100644 --- a/DirectShowFilters/BDReader/source/DeMultiplexer.cpp +++ b/DirectShowFilters/BDReader/source/DeMultiplexer.cpp @@ -999,7 +999,7 @@ void CDeMultiplexer::FillVideoH264PESPacket(CTsHeader* header, CAutoPtr bool bFlag = false; if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_HEVC) { - if (((pData[4] >> 1) & 0x3f) == HEVC_NAL_AUD) + if (((pData[4] >> 1) & 0x3f) == HEVC::NAL_AUD) { m_fHasAccessUnitDelimiters = true; bFlag = true; diff --git a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp index 5747fb31407..5206e138151 100644 --- a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp +++ b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp @@ -35,13 +35,16 @@ #include #include #include -#include "h264nalu.h" +#include "HEVC\Hevc.h" +#include "HEVC\HevcNalDecode.h" // For more details for memory leak detection see the alloctracing.h header #include "..\..\alloctracing.h" extern void LogDebug(const char *fmt, ...) ; +#define LOG_HEVC_FHP //LogDebug + #define countof(array) (sizeof(array)/sizeof(array[0])) #define DNew new @@ -49,6 +52,14 @@ extern void LogDebug(const char *fmt, ...) ; #define TRUEHD_SYNC_WORD 0xf8726f +//AVC Chroma format IDC definitions +#define YUV400 0 +#define YUV420 1 +#define YUV422 2 +#define YUV444 3 + +using namespace HEVC; + // LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2 static const UINT8 thd_chancount[13] = {2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1}; static const UINT8 mlp_quants[16] = {16, 20, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; @@ -1668,142 +1679,87 @@ bool CFrameHeaderParser::Read(avchdr& h, int len, CMediaType* pmt) bool CFrameHeaderParser::Read(hevchdr& h, int len, CMediaType* pmt) { + if ((len <= 6) || (len > 65534)) + return(false); //Sanity check + memset(&h, 0, sizeof(h)); + h.progressive = true; + h.AvgTimePerFrame = 370000; //27 Hz + + BYTE* pBuff = GetBufferPos(); - while (GetRemaining() > 4 && (h.spslen == 0 || h.ppslen == 0)) + while (GetRemaining() > 4 && (h.spslen == 0 || h.ppslen == 0 || h.vpslen == 0)) { const int nal_len = BitRead(32); - const INT64 next_nal = GetPos() + nal_len; + const INT64 nal_pos = GetPos(); + const INT64 next_nal = nal_pos + nal_len; - //nalu header - const bool bForbiden = BitRead(1); //forbidden_zero_bit - const HEVC_NALU_TYPE nal_type = (HEVC_NALU_TYPE)BitRead(6); //nal_unit_type - const int idLayer = BitRead(6); //nuh_layer_id - const int iTempId = BitRead(3); //nuh_temporal_id_plus1 + NALUnitType nal_type = HevcNalDecode::processNALUnit(GetBufferPos(), nal_len, h); - if (bForbiden || idLayer > 0 || (nal_type != HEVC_NAL_SPS && nal_type != HEVC_NAL_PPS && nal_type != HEVC_NAL_VPS)) + if (nal_type == NAL_FAIL) //NAL decoding error { - Seek(next_nal); - continue; + return(false); } - if (nal_type == HEVC_NAL_SPS) + else if (nal_type == NAL_SPS) { - h.spspos = GetPos() - 6; - h.spslen = next_nal - h.spspos; - - BYTE buff[MAX_SPS]; - BYTE buffTmp[MAX_SPS]; - CGolombBuffer gb(buff, MAX_SPS); - ByteRead((BYTE*)buffTmp, min(MAX_SPS, GetRemaining())); - RemoveMpegEscapeCode(buff, buffTmp, MAX_SPS); - - int tmp = gb.BitRead(4); //sps_video_parameter_set_id - int sps_max_sub_layers_minus1 = gb.BitRead(3); //sps_max_sub_layers_minus1 - tmp = gb.BitRead(1); //sps_temporal_id_nesting_flag - - profile_tier_level(1, sps_max_sub_layers_minus1, &gb); - - tmp = gb.UExpGolombRead(); //sps_seq_parameter_set_id - tmp = gb.UExpGolombRead(); //chroma_format_idc - - if (tmp == 3) - gb.BitRead(1); //separate_colour_plane_flag - - h.width = gb.UExpGolombRead(); //width - h.height = gb.UExpGolombRead(); //height - - //if (gb.BitRead(1)) // pic_conformance_flag - //{ - // tmp = gb.UExpGolombRead(); //conf_win_left_offset - // tmp = gb.UExpGolombRead(); //conf_win_right_offset - // tmp = gb.UExpGolombRead(); //conf_win_top_offset - // tmp = gb.UExpGolombRead(); //conf_win_bottom_offset - //} - - //tmp = gb.UExpGolombRead(); //bit_depth_luma_minus8 - //tmp = gb.UExpGolombRead(); //bit_depth_chroma_minus8 - //tmp = gb.UExpGolombRead(); //log2_max_pic_order_cnt_lsb_minus4 + LOG_HEVC_FHP("SPS found"); + //Copy SPS to buffer + h.sps = (BYTE*)malloc(nal_len); + if (h.sps == NULL) + { + //malloc error... + h.spslen = 0; + return(false); + } + ByteRead(h.sps, nal_len); + h.spslen = nal_len; } - else if (nal_type == HEVC_NAL_PPS) + else if (nal_type == NAL_PPS) { - h.ppspos = GetPos() - 6; - h.ppslen = next_nal - h.ppspos; + LOG_HEVC_FHP("PPS found"); + //Copy PPS to new buffer + h.pps = (BYTE*)malloc(nal_len); + if (h.pps == NULL) + { + //malloc error... + h.ppslen = 0; + return(false); + } + ByteRead(h.pps, nal_len); + h.ppslen = nal_len; } - else if (nal_type == HEVC_NAL_VPS) + else if (nal_type == NAL_VPS) { - BYTE buff[MAX_SPS]; - BYTE buffTmp[MAX_SPS]; - CGolombBuffer gb(buff, MAX_SPS); - ByteRead((BYTE*)buffTmp, min(MAX_SPS, GetRemaining())); - RemoveMpegEscapeCode(buff, buffTmp, MAX_SPS); - - int tmp = gb.BitRead(4); //vps_video_parameter_set_id - tmp = gb.BitRead(1); //vps_base_layer_internal_flag - tmp = gb.BitRead(1); //vps_base_layer_available_flag - tmp = gb.BitRead(6); //vps_max_layers_minus1 - int iSubLayers = gb.BitRead(3); //vps_max_sub_layers_minus1 - tmp = gb.BitRead(1); //vps_temporal_id_nesting_flag - tmp = gb.BitRead(16); //vps_reserved_0xffff_16bits - - - profile_tier_level(true, iSubLayers, &gb); - - bool bFlag = gb.BitRead(1); //vps_sub_layer_ordering_info_present_flag - - for (int i = bFlag ? 0 : iSubLayers; i <= iSubLayers; i++) - { - tmp = gb.UExpGolombRead(); //vps_max_dec_pic_buffering_minus1 - tmp = gb.UExpGolombRead(); //vps_max_num_reorder_pics - tmp = gb.UExpGolombRead(); //vps_max_latency_increase_plus1 - } - - int iMaxLayer = gb.BitRead(6); //vps_max_layer_id - int iLayersSet = gb.UExpGolombRead(); //vps_num_layer_sets_minus1 - - for (int i = 1; i <= iLayersSet; i++) - for (int j = 0; j <= iMaxLayer; j++) - tmp = gb.BitRead(1); //layer_id_included_flag - - bFlag = gb.BitRead(1); //vps_timing_info_present_flag - if (bFlag) + LOG_HEVC_FHP("VPS found"); + //Copy VPS to new buffer + h.vps = (BYTE*)malloc(nal_len); + if (h.vps == NULL) { - int vps_num_units_in_tick = gb.BitRead(32); //vps_num_units_in_tick - int vps_time_scale = gb.BitRead(32); //vps_time_scale - - h.AvgTimePerFrame = (10000000I64 * vps_num_units_in_tick) / vps_time_scale; - - bFlag = gb.BitRead(1); //vps_poc_proportional_to_timing_flag - if (bFlag) - tmp = gb.UExpGolombRead(); //vps_num_ticks_poc_diff_one_minus1 - - tmp = gb.UExpGolombRead(); //vps_num_hrd_parameters + //malloc error... + h.vpslen = 0; + return(false); } + ByteRead(h.vps, nal_len); + h.vpslen = nal_len; } Seek(next_nal); } - if (!h.spspos || !h.spslen || !h.ppspos || !h.ppslen || h.height < 300 || h.width < 300 || h.AvgTimePerFrame < 1000) + if (!h.spslen || !h.ppslen || !h.vpslen || h.height < 100 || h.width < 100 || h.AvgTimePerFrame < 1000) return(false); if (!pmt) return(true); - h.ar = 255; //ex - h.arx = 1; //ex - h.ary = 1; //ex - - //h.profile = 2; //ex - //h.level = 153; //ex - { - int extra = 2 + h.spslen - 4 + 2 + h.ppslen - 4; + int extra = h.spslen + 4 + h.ppslen + 4 + h.vpslen + 4; pmt->SetType(&MEDIATYPE_Video); //pmt->SetSubtype(&MEDIASUBTYPE_H264); pmt->SetSubtype(&HEVC_SubType); pmt->formattype = FORMAT_MPEG2_VIDEO; - //pmt->bTemporalCompression = true; //ex + pmt->bTemporalCompression = true; int len = FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + extra; MPEG2VIDEOINFO* vi = (MPEG2VIDEOINFO*)pmt->AllocFormatBuffer(len); @@ -1847,31 +1803,58 @@ bool CFrameHeaderParser::Read(hevchdr& h, int len, CMediaType* pmt) vi->hdr.bmiHeader.biSize = sizeof(vi->hdr.bmiHeader); vi->hdr.bmiHeader.biWidth = h.width; vi->hdr.bmiHeader.biHeight = h.height; - //vi->hdr.bmiHeader.biCompression = '462h'; + vi->hdr.rcSource.right = h.width; + vi->hdr.rcSource.bottom = h.height; + vi->hdr.rcTarget.right = h.width; + vi->hdr.rcTarget.bottom = h.height; vi->hdr.bmiHeader.biCompression = 'CVEH'; vi->hdr.bmiHeader.biPlanes = 1; - vi->hdr.bmiHeader.biBitCount = 24; + + + switch (h.chromaFormat) + { + case YUV420: + vi->hdr.bmiHeader.biBitCount = h.lumaDepth + (h.chromaDepth / 2); + break; + case YUV422: + vi->hdr.bmiHeader.biBitCount = h.lumaDepth + h.chromaDepth; + break; + case YUV444: + vi->hdr.bmiHeader.biBitCount = h.lumaDepth + (2 * h.chromaDepth); + break; + case YUV400: //Monochrome + vi->hdr.bmiHeader.biBitCount = h.lumaDepth; + break; + default: + vi->hdr.bmiHeader.biBitCount = h.lumaDepth + (h.chromaDepth / 2); + } + vi->hdr.bmiHeader.biClrUsed = 0; + vi->hdr.bmiHeader.biSizeImage = DIBSIZE(vi->hdr.bmiHeader); vi->dwProfile = h.profile; - vi->dwFlags = 4; // ? + vi->dwFlags = 0; vi->dwLevel = h.level; vi->cbSequenceHeader = extra; vi->dwStartTimeCode = 0; - //vi->hdr.rcSource.right = h.width; //ex - //vi->hdr.rcSource.bottom = h.height; //ex - //vi->hdr.rcTarget.right = h.width; //ex - //vi->hdr.rcTarget.bottom = h.height; //ex BYTE* p = (BYTE*)&vi->dwSequenceHeader[0]; - *p++ = (h.spslen - 4) >> 8; - *p++ = (h.spslen - 4) & 0xff; - Seek(h.spspos + 4); - ByteRead(p, h.spslen - 4); - p += h.spslen - 4; - *p++ = (h.ppslen - 4) >> 8; - *p++ = (h.ppslen - 4) & 0xff; - Seek(h.ppspos + 4); - ByteRead(p, h.ppslen - 4); - p += h.ppslen - 4; + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 1; + memcpy(p, h.sps, (size_t)h.spslen); + p += h.spslen; + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 1; + memcpy(p, h.pps, (size_t)h.ppslen); + p += h.ppslen; + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 1; + memcpy(p, h.vps, (size_t)h.vpslen); + pmt->SetFormat((BYTE*)vi, len); } @@ -2254,149 +2237,3 @@ void CFrameHeaderParser::DumpAvcHeader(avchdr h) */ LogDebug("================================="); } - -void CFrameHeaderParser::profile_tier_level(bool profilePresentFlag, int maxNumSubLayersMinus1, CGolombBuffer* gb) -{ - if (profilePresentFlag) - { - byte general_profile_compatibility_flag[32]; - - gb->BitRead(2); //general_profile_space u(2) - gb->BitRead(1); //general_tier_flag u(1) - int general_profile_idc = gb->BitRead(5); //general_profile_idc u(5) - for (int j = 0; j < 32; j++) - general_profile_compatibility_flag[j] = gb->BitRead(1);//u(1) - - gb->BitRead(1); //general_progressive_source_flag u(1) - gb->BitRead(1); //general_interlaced_source_flag u(1) - gb->BitRead(1); //general_non_packed_constraint_flag u(1) - gb->BitRead(1); //general_frame_only_constraint_flag u(1) - if (general_profile_idc == 4 || general_profile_compatibility_flag[4] - || general_profile_idc == 5 || general_profile_compatibility_flag[5] - || general_profile_idc == 6 || general_profile_compatibility_flag[6] - || general_profile_idc == 7 || general_profile_compatibility_flag[7] - || general_profile_idc == 8 || general_profile_compatibility_flag[8] - || general_profile_idc == 9 || general_profile_compatibility_flag[9] - || general_profile_idc == 10 || general_profile_compatibility_flag[10]) - { - /* The number of bits in this syntax structure is not affected by this condition */ - gb->BitRead(1); //general_max_12bit_constraint_flag u(1) - gb->BitRead(1); //general_max_10bit_constraint_flag u(1) - gb->BitRead(1); //general_max_8bit_constraint_flag u(1) - gb->BitRead(1); //general_max_422chroma_constraint_flag u(1) - gb->BitRead(1); //general_max_420chroma_constraint_flag u(1) - gb->BitRead(1); //general_max_monochrome_constraint_flag u(1) - gb->BitRead(1); //general_intra_constraint_flag u(1) - gb->BitRead(1); //general_one_picture_only_constraint_flag u(1) - gb->BitRead(1); //general_lower_bit_rate_constraint_flag u(1) - if (general_profile_idc == 5 || general_profile_compatibility_flag[5] - || general_profile_idc == 9 || general_profile_compatibility_flag[9] || - general_profile_idc == 10 || general_profile_compatibility_flag[10]) { - gb->BitRead(1); //general_max_14bit_constraint_flag u(1) - gb->BitRead(33); //general_reserved_zero_33bits u(33) - } - else - gb->BitRead(34); //general_reserved_zero_34bits u(34) - } - else if (general_profile_idc == 2 || general_profile_compatibility_flag[2]) - { - gb->BitRead(7); //general_reserved_zero_7bits u(7) - gb->BitRead(1); //general_one_picture_only_constraint_flag u(1) - gb->BitRead(35); //general_reserved_zero_35bits u(35) - } - else - - gb->BitRead(43); //general_reserved_zero_43bits u(43) - if ((general_profile_idc >= 1 && general_profile_idc <= 5) - || general_profile_idc == 9 - || general_profile_compatibility_flag[1] || general_profile_compatibility_flag[2] - || general_profile_compatibility_flag[3] || general_profile_compatibility_flag[4] - || general_profile_compatibility_flag[5] || general_profile_compatibility_flag[9]) - /* The number of bits in this syntax structure is not affected by this condition */ - gb->BitRead(1); //general_inbld_flag u(1) - else - gb->BitRead(1); //general_reserved_zero_bit u(1) - } - gb->BitRead(8); //general_level_idc u(8) - - byte sub_layer_profile_present_flag[8]; - byte sub_layer_profile_idc[8]; - byte sub_layer_profile_compatibility_flag[8][32]; - byte sub_layer_level_present_flag[8]; - - for (int i = 0; i < maxNumSubLayersMinus1; i++) - { - sub_layer_profile_present_flag[i] = (byte)gb->BitRead(1); //sub_layer_profile_present_flag[i] u(1) - sub_layer_level_present_flag[i] = (byte)gb->BitRead(1); //sub_layer_level_present_flag[i] u(1) - } - if (maxNumSubLayersMinus1 > 0) - for (int i = maxNumSubLayersMinus1; i < 8; i++) - gb->BitRead(2); //reserved_zero_2bits[i] u(2) - - for (int i = 0; i < maxNumSubLayersMinus1; i++) - { - if (sub_layer_profile_present_flag[i]) - { - gb->BitRead(2); //sub_layer_profile_space[i] u(2) - gb->BitRead(1); //sub_layer_tier_flag[i] u(1) - sub_layer_profile_idc[i] = (byte)gb->BitRead(5); //sub_layer_profile_idc[i] u(5) - - for (int j = 0; j < 32; j++) - sub_layer_profile_compatibility_flag[i][j] = (byte)gb->BitRead(1); //sub_layer_profile_compatibility_flag[i][j] u(1) - - gb->BitRead(1); //sub_layer_progressive_source_flag[i] u(1) - gb->BitRead(1); //sub_layer_interlaced_source_flag[i] u(1) - gb->BitRead(1); //sub_layer_non_packed_constraint_flag[i] u(1) - gb->BitRead(1); //sub_layer_frame_only_constraint_flag[i] u(1) - if (sub_layer_profile_idc[i] == 4 || sub_layer_profile_compatibility_flag[i][4] - || sub_layer_profile_idc[i] == 5 || sub_layer_profile_compatibility_flag[i][5] - || sub_layer_profile_idc[i] == 6 || sub_layer_profile_compatibility_flag[i][6] - || sub_layer_profile_idc[i] == 7 || sub_layer_profile_compatibility_flag[i][7] - || sub_layer_profile_idc[i] == 8 || sub_layer_profile_compatibility_flag[i][8] - || sub_layer_profile_idc[i] == 9 || sub_layer_profile_compatibility_flag[i][9] - || sub_layer_profile_idc[i] == 10 || sub_layer_profile_compatibility_flag[i][10] - ) - { - /* The number of bits in this syntax structure is not affected by this condition */ - gb->BitRead(1); //sub_layer_max_12bit_constraint_flag[i] u(1) - gb->BitRead(1); //sub_layer_max_10bit_constraint_flag[i] u(1) - gb->BitRead(1); //sub_layer_max_8bit_constraint_flag[i] u(1) - gb->BitRead(1); //sub_layer_max_422chroma_constraint_flag[i] u(1) - gb->BitRead(1); //sub_layer_max_420chroma_constraint_flag[i] u(1) - gb->BitRead(1); //sub_layer_max_monochrome_constraint_flag[i] u(1) - gb->BitRead(1); //sub_layer_intra_constraint_flag[i] u(1) - gb->BitRead(1); //sub_layer_one_picture_only_constraint_flag[i] u(1) - gb->BitRead(1); //sub_layer_lower_bit_rate_constraint_flag[i] u(1) - - if (sub_layer_profile_idc[i] == 5 || sub_layer_profile_compatibility_flag[i][5]) - { - gb->BitRead(1); //sub_layer_max_14bit_constraint_flag[i] u(1) - gb->BitRead(33); //sub_layer_reserved_zero_33bits[i] u(33) - } - else - gb->BitRead(34); //sub_layer_reserved_zero_34bits[i] u(34) - } - else if (sub_layer_profile_idc[i] == 2 || sub_layer_profile_compatibility_flag[i][2]) - { - gb->BitRead(7); //sub_layer_reserved_zero_7bits[i] u(7) - gb->BitRead(1); //sub_layer_one_picture_only_constraint_flag[i] u(1) - gb->BitRead(35); //sub_layer_reserved_zero_35bits[i] u(35) - } - else - gb->BitRead(43); //sub_layer_reserved_zero_43bits[i] u(43) - if ((sub_layer_profile_idc[i] >= 1 && sub_layer_profile_idc[i] <= 5) - || sub_layer_profile_idc[i] == 9 || sub_layer_profile_compatibility_flag[1] - || sub_layer_profile_compatibility_flag[2] || sub_layer_profile_compatibility_flag[3] - || sub_layer_profile_compatibility_flag[4] || sub_layer_profile_compatibility_flag[5] - || sub_layer_profile_compatibility_flag[9] - ) - /* The number of bits in this syntax structure is not affected by this condition */ - gb->BitRead(1); //sub_layer_inbld_flag[i] u(1) - else - gb->BitRead(1); // sub_layer_reserved_zero_bit[i] u(1) - } - - if (sub_layer_level_present_flag[i]) - gb->BitRead(8); //sub_layer_level_idc[i] u(8) - } -} \ No newline at end of file diff --git a/DirectShowFilters/BDReader/source/FrameHeaderParser.h b/DirectShowFilters/BDReader/source/FrameHeaderParser.h index b1a5414d6b7..9247ce42845 100644 --- a/DirectShowFilters/BDReader/source/FrameHeaderParser.h +++ b/DirectShowFilters/BDReader/source/FrameHeaderParser.h @@ -29,6 +29,11 @@ #include #include "GolombBuffer.h" +#include "HEVC\Hevc.h" +#include "HEVC\HevcNalDecode.h" + +using namespace HEVC; + static const byte pixel_aspect[17][2]={ {0, 1}, {1, 1}, @@ -387,30 +392,6 @@ enum mpeg_t {mpegunk, mpeg1, mpeg2}; }sar; }; - struct hevchdr - { - BYTE profile, level; - unsigned int width, height; - bool progressive; - __int64 spspos, spslen; - __int64 ppspos, ppslen; - __int64 AvgTimePerFrame; - int arx, ary; - BYTE ar; - hevchdr() - { - progressive = true; - spspos = 0; - spslen = 0; - ppspos = 0; - ppslen = 0; - AvgTimePerFrame = 0; - ar = 0; - arx = 0; - ary = 0; - } - }; - struct thdhdr { int stream_type; // 0xBB for MLP, 0xBA for TrueHD @@ -453,7 +434,7 @@ struct BasicVideoInfo } }; -class CFrameHeaderParser:public CGolombBuffer +class CFrameHeaderParser:public CGolombBuffer, public HEVC::HevcNalDecode { int m_tslen; // transport stream packet length (188 or 192 bytes, auto-detected) @@ -481,18 +462,16 @@ class CFrameHeaderParser:public CGolombBuffer bool Read(trsechdr& h); bool Read(pvahdr& h, bool fSync = true); bool Read(avchdr& h, int len, CMediaType* pmt = NULL); - bool Read(hevchdr& h, int len, CMediaType* pmt); bool Read(vc1hdr& h, int len, CMediaType* pmt = NULL); bool Read(bdlpcmhdr& h, int len, CMediaType* pmt = NULL); bool Read(thdhdr& h, int len, CMediaType* pmt = NULL); + bool Read(hevchdr& h, int len, CMediaType* pmt); void RemoveMpegEscapeCode(BYTE* dst, BYTE* src, int length); void DumpSequenceHeader(seqhdr h); void DumpAvcHeader(avchdr h); - void profile_tier_level(bool profilePresentFlag, int maxNumSubLayersMinus1, CGolombBuffer* gb); - private: REFERENCE_TIME m_rtPTSOffset; }; diff --git a/DirectShowFilters/BDReader/source/H264Nalu.cpp b/DirectShowFilters/BDReader/source/H264Nalu.cpp index 3269b06fcd6..cbf4811ad76 100644 --- a/DirectShowFilters/BDReader/source/H264Nalu.cpp +++ b/DirectShowFilters/BDReader/source/H264Nalu.cpp @@ -99,14 +99,9 @@ bool CH264Nalu::ReadNext() MoveToNextAnnexBStartcode(); } - //H264 - //forbidden_bit = (m_pBuffer[m_nNALDataPos]>>7) & 1; - //nal_reference_idc = (m_pBuffer[m_nNALDataPos]>>5) & 3; - //nal_unit_type = (NALU_TYPE) (m_pBuffer[m_nNALDataPos] & 0x1f); - - //H265 - //forbidden_bit = (m_pBuffer[m_nNALDataPos] >> 7) & 1; - //nal_unit_type = (HEVC_NALU_TYPE)((m_pBuffer[m_nNALDataPos] >> 1) & 0x3F); + forbidden_bit = (m_pBuffer[m_nNALDataPos]>>7) & 1; + nal_reference_idc = (m_pBuffer[m_nNALDataPos]>>5) & 3; + nal_unit_type = (NALU_TYPE) (m_pBuffer[m_nNALDataPos] & 0x1f); return true; } diff --git a/DirectShowFilters/BDReader/source/H264Nalu.h b/DirectShowFilters/BDReader/source/H264Nalu.h index f261495660a..429a45af307 100644 --- a/DirectShowFilters/BDReader/source/H264Nalu.h +++ b/DirectShowFilters/BDReader/source/H264Nalu.h @@ -38,80 +38,12 @@ typedef enum { NALU_TYPE_FILL = 12 } NALU_TYPE; -typedef enum { - HEVC_NAL_TRAIL_N = 0, - HEVC_NAL_TRAIL_R = 1, - HEVC_NAL_TSA_N = 2, - HEVC_NAL_TSA_R = 3, - HEVC_NAL_STSA_N = 4, - HEVC_NAL_STSA_R = 5, - HEVC_NAL_RADL_N = 6, - HEVC_NAL_RADL_R = 7, - HEVC_NAL_RASL_N = 8, - HEVC_NAL_RASL_R = 9, - HEVC_NAL_VCL_N10 = 10, - HEVC_NAL_VCL_R11 = 11, - HEVC_NAL_VCL_N12 = 12, - HEVC_NAL_VCL_R13 = 13, - HEVC_NAL_VCL_N14 = 14, - HEVC_NAL_VCL_R15 = 15, - HEVC_NAL_BLA_W_LP = 16, - HEVC_NAL_BLA_W_RADL = 17, - HEVC_NAL_BLA_N_LP = 18, - HEVC_NAL_IDR_W_RADL = 19, - HEVC_NAL_IDR_N_LP = 20, - HEVC_NAL_CRA_NUT = 21, - HEVC_NAL_RSV_IRAP_VCL22 = 22, - HEVC_NAL_RSV_IRAP_VCL23 = 23, - HEVC_NAL_RSV_VCL24 = 24, - HEVC_NAL_RSV_VCL25 = 25, - HEVC_NAL_RSV_VCL26 = 26, - HEVC_NAL_RSV_VCL27 = 27, - HEVC_NAL_RSV_VCL28 = 28, - HEVC_NAL_RSV_VCL29 = 29, - HEVC_NAL_RSV_VCL30 = 30, - HEVC_NAL_RSV_VCL31 = 31, - HEVC_NAL_VPS = 32, - HEVC_NAL_SPS = 33, - HEVC_NAL_PPS = 34, - HEVC_NAL_AUD = 35, - HEVC_NAL_EOS_NUT = 36, - HEVC_NAL_EOB_NUT = 37, - HEVC_NAL_FD_NUT = 38, - HEVC_NAL_SEI_PREFIX = 39, - HEVC_NAL_SEI_SUFFIX = 40, - HEVC_NAL_RSV_NVCL41 = 41, - HEVC_NAL_RSV_NVCL42 = 42, - HEVC_NAL_RSV_NVCL43 = 43, - HEVC_NAL_RSV_NVCL44 = 44, - HEVC_NAL_RSV_NVCL45 = 45, - HEVC_NAL_RSV_NVCL46 = 46, - HEVC_NAL_RSV_NVCL47 = 47, - HEVC_NAL_UNSPEC48 = 48, - HEVC_NAL_UNSPEC49 = 49, - HEVC_NAL_UNSPEC50 = 50, - HEVC_NAL_UNSPEC51 = 51, - HEVC_NAL_UNSPEC52 = 52, - HEVC_NAL_UNSPEC53 = 53, - HEVC_NAL_UNSPEC54 = 54, - HEVC_NAL_UNSPEC55 = 55, - HEVC_NAL_UNSPEC56 = 56, - HEVC_NAL_UNSPEC57 = 57, - HEVC_NAL_UNSPEC58 = 58, - HEVC_NAL_UNSPEC59 = 59, - HEVC_NAL_UNSPEC60 = 60, - HEVC_NAL_UNSPEC61 = 61, - HEVC_NAL_UNSPEC62 = 62, - HEVC_NAL_UNSPEC63 = 63, -} HEVC_NALU_TYPE; - - class CH264Nalu { private : - //int forbidden_bit; //! should be always FALSE - //int nal_reference_idc; //! NALU_PRIORITY_xxxx - //NALU_TYPE nal_unit_type; //! NALU_TYPE_xxxx + int forbidden_bit; //! should be always FALSE + int nal_reference_idc; //! NALU_PRIORITY_xxxx + NALU_TYPE nal_unit_type; //! NALU_TYPE_xxxx int m_nNALStartPos; //! NALU start (including startcode / size) int m_nNALDataPos; //! Useful part @@ -129,12 +61,12 @@ private : public : CH264Nalu(); - //NALU_TYPE GetType() const { - // return nal_unit_type; - //}; - //bool IsRefFrame() const { - // return (nal_reference_idc != 0); - //}; + NALU_TYPE GetType() const { + return nal_unit_type; + }; + bool IsRefFrame() const { + return (nal_reference_idc != 0); + }; int GetDataLength() const { return m_nCurPos - m_nNALDataPos; diff --git a/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.cpp b/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.cpp new file mode 100644 index 00000000000..838dbf147a8 --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.cpp @@ -0,0 +1,189 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + + +#include "BitstreamReader.h" + +#include +#include +#include + + +BitstreamReader::BitstreamReader(const uint8_t *ptr, std::size_t size): + m_ptr(ptr) + ,m_size(size) + ,m_posBase(0) + ,m_posInBase(CHAR_BIT - 1) +{ +} + +std::size_t BitstreamReader::available() +{ + return (m_size - m_posBase -1) * CHAR_BIT + m_posInBase + 1; +} + +std::size_t BitstreamReader::availableInNalU() +{ + std::size_t pos = m_posBase; + if(m_posInBase) + pos++; + for(; pos<(m_size - 3); pos++) + { + bool naluFinded = m_ptr[pos] == 0 && m_ptr[pos+1] == 0 && m_ptr[pos+2] == 1; + + if(!naluFinded) + { + if(m_size - pos >= 4 && m_ptr[pos] == 0 && m_ptr[pos+1] == 0 && m_ptr[pos+2] == 0 && m_ptr[pos+3] == 1) + naluFinded = true; + } + + if(naluFinded) + { + return (pos - m_posBase - 1) * CHAR_BIT + m_posInBase + 1; + } + + } + + return m_size; +} + + +bool BitstreamReader::getBit() +{ + if(m_posBase >= m_size) + throw std::runtime_error("BitstreamReader: not enough data"); + + bool res = (m_ptr[m_posBase] & (1 << m_posInBase)) != 0; + + m_posInBase--; + + if(m_posInBase > CHAR_BIT) + { + m_posInBase = CHAR_BIT-1; + m_posBase++; + + if(m_posBase >= 2) + { + if(m_ptr[m_posBase - 2] == 0 && m_ptr[m_posBase - 1] == 0 && m_ptr[m_posBase] == 3) + m_posBase++; + } + } + + return res; +} + + +uint32_t BitstreamReader::getBits(std::size_t num) +{ + assert(num <= 32); + + uint32_t result = 0; + for(std::size_t i=0; i= 2) + { + if(m_ptr[m_posBase - 2] == 0 && m_ptr[m_posBase - 1] == 0 && m_ptr[m_posBase] == 3) + m_posBase++; + } + + uint32_t scipBytes = (uint32_t)(num / 8); + + + while(scipBytes) + { + scipBytes--; + m_posBase++; + if(m_posBase >= 2) + { + if(m_ptr[m_posBase - 2] == 0 && m_ptr[m_posBase - 1] == 0 && m_ptr[m_posBase] == 3) + m_posBase++; + } + } + + if(m_posInBase > num % 8) + m_posInBase -= num % 8; + else + { + m_posBase++; + m_posInBase = m_posInBase - num % 8 + 8; + } + +} + +uint32_t BitstreamReader::showBits(std::size_t num) +{ + assert(num <= 32); + + std::size_t posBasePrev = m_posBase; + std::size_t posInBasePrev = m_posInBase; + + uint32_t result = 0; + for(std::size_t i=0; i= 32) + return 0; +// throw std::range_error("Golomb: size of value more then 32 bits"); + + return (1 << numZeroBits) - 1 + getBits(numZeroBits); +} + + + +int32_t BitstreamReader::getGolombS() +{ + int32_t buf = getGolombU(); + + if (buf & 1) + buf = (buf + 1) >> 1; + else + buf = -(buf >> 1); + + return buf; +} + diff --git a/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.h b/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.h new file mode 100644 index 00000000000..556ba2ebcf8 --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.h @@ -0,0 +1,54 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#ifndef BITSTREAM_READER_H_ +#define BITSTREAM_READER_H_ + +#include +#include + +class BitstreamReader +{ +public: + BitstreamReader(const uint8_t *ptr, std::size_t size); + bool getBit(); + uint32_t getBits(std::size_t num); + void skipBits(std::size_t num); + uint32_t showBits(std::size_t num); + uint32_t getGolombU(); + int32_t getGolombS(); + + std::size_t available(); + std::size_t availableInNalU(); + +private: + const uint8_t *m_ptr; + std::size_t m_size; + std::size_t m_posBase; + std::size_t m_posInBase; +}; + + +#endif \ No newline at end of file diff --git a/DirectShowFilters/BDReader/source/HEVC/Hevc.cpp b/DirectShowFilters/BDReader/source/HEVC/Hevc.cpp new file mode 100644 index 00000000000..25cffabeb02 --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/Hevc.cpp @@ -0,0 +1,339 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#include "Hevc.h" + +#include + +using namespace HEVC; + +NALUnit::NALUnit(NALUnitType type): + m_nalUnitType(type) + ,m_processFailed(false) +{ +} + + +NALUnit::~NALUnit() +{ +} + + +NALUnitType NALUnit::getType() const +{ + return m_nalUnitType; +} + + + +HEVC::VPS::VPS(): NALUnit(HEVC::NAL_VPS) +{ + toDefault(); +} + + +HEVC::SPS::SPS(): NALUnit(NAL_SPS) +{ + toDefault(); +} + + +HEVC::PPS::PPS(): NALUnit(NAL_PPS) +{ + toDefault(); +}; + + +HEVC::AUD::AUD(): NALUnit(NAL_AUD) +{ + toDefault(); +}; + + +void ProfileTierLevel::toDefault() +{ + general_profile_space = 0; + general_tier_flag = 0; + general_profile_idc = 0; + general_profile_compatibility_flag[32]; + general_progressive_source_flag = 0; + general_interlaced_source_flag = 0; + general_non_packed_constraint_flag = 0; + general_frame_only_constraint_flag = 0; + general_level_idc = 0; + sub_layer_profile_present_flag.clear(); + sub_layer_level_present_flag.clear(); + sub_layer_profile_space.clear(); + sub_layer_tier_flag.clear(); + sub_layer_profile_idc.clear(); + sub_layer_profile_compatibility_flag.clear(); + sub_layer_progressive_source_flag.clear(); + sub_layer_interlaced_source_flag.clear(); + sub_layer_non_packed_constraint_flag.clear(); + sub_layer_frame_only_constraint_flag.clear(); + sub_layer_level_idc.clear(); +} + + +void SubLayerHrdParameters::toDefault() +{ + bit_rate_value_minus1.clear(); + cpb_size_value_minus1.clear(); + cpb_size_du_value_minus1.clear(); + bit_rate_du_value_minus1.clear(); + cbr_flag.clear(); +} + + +void HrdParameters::toDefault() +{ + nal_hrd_parameters_present_flag = 0; + vcl_hrd_parameters_present_flag = 0; + sub_pic_hrd_params_present_flag = 0; + tick_divisor_minus2 = 0; + du_cpb_removal_delay_increment_length_minus1 = 0; + sub_pic_cpb_params_in_pic_timing_sei_flag = 0; + dpb_output_delay_du_length_minus1 = 0; + bit_rate_scale = 0; + cpb_size_scale = 0; + cpb_size_du_scale = 0; + initial_cpb_removal_delay_length_minus1 = 23; + au_cpb_removal_delay_length_minus1 = 23; + dpb_output_delay_length_minus1 = 23; + fixed_pic_rate_general_flag.clear(); + fixed_pic_rate_within_cvs_flag.clear(); + elemental_duration_in_tc_minus1.clear(); + low_delay_hrd_flag.clear(); + cpb_cnt_minus1.clear(); + nal_sub_layer_hrd_parameters.clear(); + vcl_sub_layer_hrd_parameters.clear(); +} + + +void ShortTermRefPicSet::toDefault() +{ + inter_ref_pic_set_prediction_flag = 0; + delta_idx_minus1 = 0; + delta_rps_sign = 0; + abs_delta_rps_minus1 = 0; + used_by_curr_pic_flag.clear(); + use_delta_flag.clear(); + num_negative_pics = 0; + num_positive_pics = 0; + delta_poc_s0_minus1.clear(); + used_by_curr_pic_s0_flag.clear(); + delta_poc_s1_minus1.clear(); + used_by_curr_pic_s1_flag.clear(); +} + + + +void VuiParameters::toDefault() +{ + aspect_ratio_info_present_flag = 0; + aspect_ratio_idc = 0; + sar_width = 0; + sar_height = 0; + overscan_info_present_flag = 0; + overscan_appropriate_flag = 0; + video_signal_type_present_flag = 0; + video_format = 5; + video_full_range_flag = 0; + colour_description_present_flag = 0; + colour_primaries = 2; + transfer_characteristics = 2; + matrix_coeffs = 2; + chroma_loc_info_present_flag = 0; + chroma_sample_loc_type_top_field = 0; + chroma_sample_loc_type_bottom_field = 0; + neutral_chroma_indication_flag = 0; + field_seq_flag = 0; + frame_field_info_present_flag = 0; + default_display_window_flag = 0; + def_disp_win_left_offset = 0; + def_disp_win_right_offset = 0; + def_disp_win_top_offset = 0; + def_disp_win_bottom_offset = 0; + vui_timing_info_present_flag = 0; + vui_num_units_in_tick = 0; + vui_time_scale = 0; + vui_poc_proportional_to_timing_flag = 0; + vui_num_ticks_poc_diff_one_minus1 = 0; + vui_hrd_parameters_present_flag = 0; + hrd_parameters.toDefault(); + bitstream_restriction_flag = 0; + tiles_fixed_structure_flag = 0; + motion_vectors_over_pic_boundaries_flag = 0; + restricted_ref_pic_lists_flag = 0; + min_spatial_segmentation_idc = 0; + max_bytes_per_pic_denom = 2; + max_bits_per_min_cu_denom = 1; + log2_max_mv_length_horizontal = 15; + log2_max_mv_length_vertical = 15; +} + + + +void VPS::toDefault() +{ + vps_video_parameter_set_id = 0; + vps_max_layers_minus1 = 0; + vps_max_sub_layers_minus1 = 0; + vps_temporal_id_nesting_flag = 0; + profile_tier_level.toDefault(); + vps_sub_layer_ordering_info_present_flag = 0; + vps_max_dec_pic_buffering_minus1.clear(); + vps_max_num_reorder_pics.clear(); + vps_max_latency_increase_plus1.clear(); + vps_max_layer_id = 0; + vps_num_layer_sets_minus1 = 0; + layer_id_included_flag.clear(); + vps_timing_info_present_flag = 0; + vps_num_units_in_tick = 0; + vps_time_scale = 0; + vps_poc_proportional_to_timing_flag = 0; + vps_num_ticks_poc_diff_one_minus1 = 0; + vps_num_hrd_parameters = 0; + hrd_layer_set_idx.clear(); + cprms_present_flag.clear(); + hrd_parameters.clear(); + vps_extension_flag = 0; +} + + +void SPS::toDefault() +{ + sps_video_parameter_set_id = 0; + sps_max_sub_layers_minus1 = 0; + sps_temporal_id_nesting_flag = 0; + profile_tier_level.toDefault(); + sps_seq_parameter_set_id = 0; + chroma_format_idc = 0; + separate_colour_plane_flag = 0; + pic_width_in_luma_samples = 0; + pic_height_in_luma_samples = 0; + conformance_window_flag = 0; + conf_win_left_offset = 0; + conf_win_right_offset = 0; + conf_win_top_offset = 0; + conf_win_bottom_offset = 0; + bit_depth_luma_minus8 = 0; + bit_depth_chroma_minus8 = 0; + log2_max_pic_order_cnt_lsb_minus4 = 0; + sps_sub_layer_ordering_info_present_flag = 0; + sps_max_dec_pic_buffering_minus1.clear(); + sps_max_num_reorder_pics.clear(); + sps_max_latency_increase_plus1.clear(); + log2_min_luma_coding_block_size_minus3 = 0; + log2_diff_max_min_luma_coding_block_size = 0; + log2_min_transform_block_size_minus2 = 0; + log2_diff_max_min_transform_block_size = 0; + max_transform_hierarchy_depth_inter = 0; + max_transform_hierarchy_depth_intra = 0; + scaling_list_enabled_flag = 0; + scaling_list_data.toDefault(); + sps_scaling_list_data_present_flag = 0; + amp_enabled_flag = 0; + sample_adaptive_offset_enabled_flag = 0; + pcm_enabled_flag = 0; + pcm_sample_bit_depth_luma_minus1 = 0; + pcm_sample_bit_depth_chroma_minus1 = 0; + log2_min_pcm_luma_coding_block_size_minus3 = 0; + log2_diff_max_min_pcm_luma_coding_block_size = 0; + pcm_loop_filter_disabled_flag = 0; + num_short_term_ref_pic_sets = 0; + short_term_ref_pic_set.clear(); + long_term_ref_pics_present_flag = 0; + num_long_term_ref_pics_sps = 0; + lt_ref_pic_poc_lsb_sps.clear(); + used_by_curr_pic_lt_sps_flag.clear(); + sps_temporal_mvp_enabled_flag = 0; + strong_intra_smoothing_enabled_flag = 0; + vui_parameters_present_flag = 0; + vui_parameters.toDefault(); + sps_extension_flag = 0; +} + + + +void PPS::toDefault() +{ + pps_pic_parameter_set_id = 0; + pps_seq_parameter_set_id = 0; + dependent_slice_segments_enabled_flag = 0; + output_flag_present_flag = 0; + num_extra_slice_header_bits = 0; + sign_data_hiding_flag = 0; + cabac_init_present_flag = 0; + num_ref_idx_l0_default_active_minus1 = 0; + num_ref_idx_l1_default_active_minus1 = 0; + init_qp_minus26 = 0; + constrained_intra_pred_flag = 0; + transform_skip_enabled_flag = 0; + cu_qp_delta_enabled_flag = 0; + diff_cu_qp_delta_depth = 0; + pps_cb_qp_offset = 0; + pps_cr_qp_offset = 0; + pps_slice_chroma_qp_offsets_present_flag = 0; + weighted_pred_flag = 0; + weighted_bipred_flag = 0; + transquant_bypass_enabled_flag = 0; + tiles_enabled_flag = 0; + entropy_coding_sync_enabled_flag = 0; + num_tile_columns_minus1 = 0; + num_tile_rows_minus1 = 0; + uniform_spacing_flag = 1; + column_width_minus1.clear(); + row_height_minus1.clear(); + loop_filter_across_tiles_enabled_flag = 0; + pps_loop_filter_across_slices_enabled_flag = 0; + deblocking_filter_control_present_flag = 0; + deblocking_filter_override_enabled_flag = 0; + pps_deblocking_filter_disabled_flag = 0; + pps_beta_offset_div2 = 0; + pps_tc_offset_div2 = 0; + pps_scaling_list_data_present_flag = 0; + lists_modification_present_flag = 0; + log2_parallel_merge_level_minus2 = 0; + slice_segment_header_extension_present_flag = 0; + pps_extension_flag = 0; +} + + +void ScalingListData::toDefault() +{ + scaling_list_delta_coef.clear(); + scaling_list_pred_mode_flag.clear(); + scaling_list_pred_matrix_id_delta.clear(); + scaling_list_dc_coef_minus8.clear(); +} + + +void AUD::toDefault() +{ + pic_type = 0; +} + + diff --git a/DirectShowFilters/BDReader/source/HEVC/Hevc.h b/DirectShowFilters/BDReader/source/HEVC/Hevc.h new file mode 100644 index 00000000000..e9d48ecdc7e --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/Hevc.h @@ -0,0 +1,476 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#ifndef HEVC_H_ +#define HEVC_H_ + +//#include +#include +#include +#include +#include +#include + +namespace HEVC +{ + + struct hevchdr + { + uint8_t profile, level; + uint64_t chromaFormat; + uint16_t lumaDepth, chromaDepth; + unsigned int width, height; + bool progressive; + uint8_t * sps; + uint8_t * pps; + uint8_t * vps; + __int64 spslen; + __int64 ppslen; + __int64 vpslen; + __int64 AvgTimePerFrame; + int arx, ary; + uint8_t ar; + hevchdr() + { + profile = 0; + level = 0; + chromaFormat = 0; + lumaDepth = 0; + chromaDepth = 0; + progressive = true; + sps = NULL; + pps = NULL; + vps = NULL; + spslen = 0; + ppslen = 0; + vpslen = 0; + AvgTimePerFrame = 370000; //27 Hz + ar = 0; + arx = 0; + ary = 0; + width = 0; + height = 0; + } + + ~hevchdr() + { + if (sps != NULL) free(sps); + if (pps != NULL) free(pps); + if (vps != NULL) free(vps); + sps = NULL; + pps = NULL; + vps = NULL; + } + }; + + enum NALUnitType + { + NAL_FAIL = -1, + NAL_TRAIL_N = 0, + NAL_TRAIL_R = 1, + NAL_TSA_N = 2, + NAL_TSA_R = 3, + NAL_STSA_N = 4, + NAL_STSA_R = 5, + NAL_RADL_N = 6, + NAL_RADL_R = 7, + NAL_RASL_N = 8, + NAL_RASL_R = 9, + NAL_BLA_W_LP = 16, + NAL_BLA_W_RADL = 17, + NAL_BLA_N_LP = 18, + NAL_IDR_W_RADL = 19, + NAL_IDR_N_LP = 20, + NAL_CRA_NUT = 21, + NAL_IRAP_VCL23 = 23, + NAL_VPS = 32, + NAL_SPS = 33, + NAL_PPS = 34, + NAL_AUD = 35, + NAL_EOS_NUT = 36, + NAL_EOB_NUT = 37, + NAL_FD_NUT = 38, + NAL_SEI_PREFIX = 39, + NAL_SEI_SUFFIX = 40, + NAL_RESERVED = 255 + }; + + class ProfileTierLevel + { + public: + uint8_t general_profile_space; + uint8_t general_tier_flag; + uint8_t general_profile_idc; + uint8_t general_profile_compatibility_flag[32]; + uint8_t general_progressive_source_flag; + uint8_t general_interlaced_source_flag; + uint8_t general_non_packed_constraint_flag; + uint8_t general_frame_only_constraint_flag; + uint8_t general_level_idc; + std::vector sub_layer_profile_present_flag; + std::vector sub_layer_level_present_flag; + std::vector sub_layer_profile_space; + std::vector sub_layer_tier_flag; + std::vector sub_layer_profile_idc; + std::vector< std::vector< uint8_t> > + sub_layer_profile_compatibility_flag; + std::vector sub_layer_progressive_source_flag; + std::vector sub_layer_interlaced_source_flag; + std::vector sub_layer_non_packed_constraint_flag; + std::vector sub_layer_frame_only_constraint_flag; + std::vector sub_layer_level_idc; + + void toDefault(); + + //bool operator == (const ProfileTierLevel &) const; + }; + + class SubLayerHrdParameters + { + public: + std::vector bit_rate_value_minus1; + std::vector cpb_size_value_minus1; + std::vector cpb_size_du_value_minus1; + std::vector bit_rate_du_value_minus1; + std::vector cbr_flag; + + void toDefault(); + + //bool operator == (const SubLayerHrdParameters &) const; + }; + + + class ScalingListData + { + public: + std::vector< std::vector< uint8_t> > scaling_list_pred_mode_flag; + std::vector< std::vector< uint32_t> > scaling_list_pred_matrix_id_delta; + std::vector< std::vector< uint32_t> > scaling_list_dc_coef_minus8; + std::vector > > + scaling_list_delta_coef; + + void toDefault(); + + //bool operator == (const ScalingListData &) const; + }; + + class HrdParameters + { + public: + uint8_t nal_hrd_parameters_present_flag; + uint8_t vcl_hrd_parameters_present_flag; + uint8_t sub_pic_hrd_params_present_flag; + uint8_t tick_divisor_minus2; + uint8_t du_cpb_removal_delay_increment_length_minus1; + uint8_t sub_pic_cpb_params_in_pic_timing_sei_flag; + uint8_t dpb_output_delay_du_length_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t cpb_size_du_scale; + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t au_cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + std::vector fixed_pic_rate_general_flag; + std::vector fixed_pic_rate_within_cvs_flag; + std::vector elemental_duration_in_tc_minus1; + std::vector low_delay_hrd_flag; + std::vector cpb_cnt_minus1; + std::vector + nal_sub_layer_hrd_parameters; + std::vector + vcl_sub_layer_hrd_parameters; + + void toDefault(); + + //bool operator == (const HrdParameters &) const; + }; + + class ShortTermRefPicSet + { + public: + uint8_t inter_ref_pic_set_prediction_flag; + uint32_t delta_idx_minus1; + uint8_t delta_rps_sign; + uint32_t abs_delta_rps_minus1; + std::vector used_by_curr_pic_flag; + std::vector use_delta_flag; + uint32_t num_negative_pics; + uint32_t num_positive_pics; + std::vector delta_poc_s0_minus1; + std::vector used_by_curr_pic_s0_flag; + std::vector delta_poc_s1_minus1; + std::vector used_by_curr_pic_s1_flag; + + void toDefault(); + + //bool operator == (const ShortTermRefPicSet &) const; + }; + + class RefPicListModification + { + public: + uint8_t ref_pic_list_modification_flag_l0; + std::vector list_entry_l0; + uint8_t ref_pic_list_modification_flag_l1; + std::vector list_entry_l1; + + void toDefault(); + + //bool operator == (const RefPicListModification &) const; + }; + + class VuiParameters + { + public: + uint8_t aspect_ratio_info_present_flag; + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + uint8_t overscan_info_present_flag; + uint8_t overscan_appropriate_flag; + uint8_t video_signal_type_present_flag; + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present_flag; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coeffs; + uint8_t chroma_loc_info_present_flag; + uint32_t chroma_sample_loc_type_top_field; + uint32_t chroma_sample_loc_type_bottom_field; + uint8_t neutral_chroma_indication_flag; + uint8_t field_seq_flag; + uint8_t frame_field_info_present_flag; + uint8_t default_display_window_flag; + uint32_t def_disp_win_left_offset; + uint32_t def_disp_win_right_offset; + uint32_t def_disp_win_top_offset; + uint32_t def_disp_win_bottom_offset; + uint8_t vui_timing_info_present_flag; + uint32_t vui_num_units_in_tick; + uint32_t vui_time_scale; + uint8_t vui_poc_proportional_to_timing_flag; + uint32_t vui_num_ticks_poc_diff_one_minus1; + uint8_t vui_hrd_parameters_present_flag; + HrdParameters hrd_parameters; + uint8_t bitstream_restriction_flag; + uint8_t tiles_fixed_structure_flag; + uint8_t motion_vectors_over_pic_boundaries_flag; + uint8_t restricted_ref_pic_lists_flag; + uint32_t min_spatial_segmentation_idc; + uint32_t max_bytes_per_pic_denom; + uint32_t max_bits_per_min_cu_denom; + uint32_t log2_max_mv_length_horizontal; + uint32_t log2_max_mv_length_vertical; + + void toDefault(); + + //bool operator == (const VuiParameters &) const; + + }; + + + + class NALUnit + { + public: + NALUnit(NALUnitType type); + virtual ~NALUnit(); + virtual NALUnitType getType() const; + + std::shared_ptr copy() const; + + bool m_processFailed; + + NALUnitType m_nalUnitType; + }; + + + + class VPS: public NALUnit + { + public: + VPS(); + uint8_t vps_video_parameter_set_id; + uint8_t vps_max_layers_minus1; + uint8_t vps_max_sub_layers_minus1; + uint8_t vps_temporal_id_nesting_flag; + ProfileTierLevel profile_tier_level; + uint8_t vps_sub_layer_ordering_info_present_flag; + std::vector vps_max_dec_pic_buffering_minus1; + std::vector vps_max_num_reorder_pics; + std::vector vps_max_latency_increase_plus1; + uint8_t vps_max_layer_id; + uint32_t vps_num_layer_sets_minus1; + std::vector > + layer_id_included_flag; + uint8_t vps_timing_info_present_flag; + uint32_t vps_num_units_in_tick; + uint32_t vps_time_scale; + uint8_t vps_poc_proportional_to_timing_flag; + uint32_t vps_num_ticks_poc_diff_one_minus1; + uint32_t vps_num_hrd_parameters; + std::vector hrd_layer_set_idx; + std::vector cprms_present_flag; + std::vector + hrd_parameters; + uint8_t vps_extension_flag; + + void toDefault(); + //bool operator == (const VPS &) const; + }; + + + class SPS: public NALUnit + { + public: + SPS(); + uint8_t sps_video_parameter_set_id; + uint8_t sps_max_sub_layers_minus1; + uint8_t sps_temporal_id_nesting_flag; + ProfileTierLevel profile_tier_level; + uint32_t sps_seq_parameter_set_id; + uint32_t chroma_format_idc; + uint8_t separate_colour_plane_flag; + uint32_t pic_width_in_luma_samples; + uint32_t pic_height_in_luma_samples; + uint8_t conformance_window_flag; + uint32_t conf_win_left_offset; + uint32_t conf_win_right_offset; + uint32_t conf_win_top_offset; + uint32_t conf_win_bottom_offset; + uint32_t bit_depth_luma_minus8; + uint32_t bit_depth_chroma_minus8; + uint32_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t sps_sub_layer_ordering_info_present_flag; + std::vector sps_max_dec_pic_buffering_minus1; + std::vector sps_max_num_reorder_pics; + std::vector sps_max_latency_increase_plus1; + uint32_t log2_min_luma_coding_block_size_minus3; + uint32_t log2_diff_max_min_luma_coding_block_size; + uint32_t log2_min_transform_block_size_minus2; + uint32_t log2_diff_max_min_transform_block_size; + uint32_t max_transform_hierarchy_depth_inter; + uint32_t max_transform_hierarchy_depth_intra; + uint8_t scaling_list_enabled_flag; + uint8_t sps_scaling_list_data_present_flag; + ScalingListData scaling_list_data; + uint8_t amp_enabled_flag; + uint8_t sample_adaptive_offset_enabled_flag; + uint8_t pcm_enabled_flag; + uint8_t pcm_sample_bit_depth_luma_minus1; + uint8_t pcm_sample_bit_depth_chroma_minus1; + uint32_t log2_min_pcm_luma_coding_block_size_minus3; + uint32_t log2_diff_max_min_pcm_luma_coding_block_size; + uint8_t pcm_loop_filter_disabled_flag; + uint32_t num_short_term_ref_pic_sets; + std::vector + short_term_ref_pic_set; + uint8_t long_term_ref_pics_present_flag; + uint32_t num_long_term_ref_pics_sps; + std::vector lt_ref_pic_poc_lsb_sps; + std::vector used_by_curr_pic_lt_sps_flag; + uint8_t sps_temporal_mvp_enabled_flag; + uint8_t strong_intra_smoothing_enabled_flag; + uint8_t vui_parameters_present_flag; + VuiParameters vui_parameters; + uint8_t sps_extension_flag; + + void toDefault(); + + //bool operator == (const SPS &) const; + }; + + + class PPS: public NALUnit + { + public: + PPS(); + + uint32_t pps_pic_parameter_set_id; + uint32_t pps_seq_parameter_set_id; + uint8_t dependent_slice_segments_enabled_flag; + uint8_t output_flag_present_flag; + uint8_t num_extra_slice_header_bits; + uint8_t sign_data_hiding_flag; + uint8_t cabac_init_present_flag; + uint32_t num_ref_idx_l0_default_active_minus1; + uint32_t num_ref_idx_l1_default_active_minus1; + int32_t init_qp_minus26; + uint8_t constrained_intra_pred_flag; + uint8_t transform_skip_enabled_flag; + uint8_t cu_qp_delta_enabled_flag; + uint32_t diff_cu_qp_delta_depth; + int32_t pps_cb_qp_offset; + int32_t pps_cr_qp_offset; + uint8_t pps_slice_chroma_qp_offsets_present_flag; + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_flag; + uint8_t transquant_bypass_enabled_flag; + uint8_t tiles_enabled_flag; + uint8_t entropy_coding_sync_enabled_flag; + uint32_t num_tile_columns_minus1; + uint32_t num_tile_rows_minus1; + uint8_t uniform_spacing_flag; + std::vector + column_width_minus1; + std::vector + row_height_minus1; + uint8_t loop_filter_across_tiles_enabled_flag; + uint8_t pps_loop_filter_across_slices_enabled_flag; + uint8_t deblocking_filter_control_present_flag; + uint8_t deblocking_filter_override_enabled_flag; + uint8_t pps_deblocking_filter_disabled_flag; + uint32_t pps_beta_offset_div2; + uint32_t pps_tc_offset_div2; + uint8_t pps_scaling_list_data_present_flag; + ScalingListData + scaling_list_data; + uint8_t lists_modification_present_flag; + int32_t log2_parallel_merge_level_minus2; + uint8_t slice_segment_header_extension_present_flag; + uint8_t pps_extension_flag; + + void toDefault(); + + //bool operator == (const PPS &) const; + }; + + + + + class AUD: public NALUnit + { + public: + AUD(); + + uint8_t pic_type; + void toDefault(); + }; + + +} + +#endif diff --git a/DirectShowFilters/BDReader/source/HEVC/HevcNalDecode.cpp b/DirectShowFilters/BDReader/source/HEVC/HevcNalDecode.cpp new file mode 100644 index 00000000000..d051178003e --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/HevcNalDecode.cpp @@ -0,0 +1,749 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#include "HevcNalDecode.h" + +#include +#include +#include + +#include + +#include + +extern void LogDebug(const char *fmt, ...) ; + +using namespace HEVC; + +NALUnitType HevcNalDecode::processNALUnit(const uint8_t *pdata, std::size_t size, hevchdr& h) +{ + //Note: 'emulation_prevention_three_byte' removal is dealt with inside the BitstreamReader + BitstreamReader bs(pdata, size); + + NALUnitType type = NAL_FAIL; + + try + { + type = processNALUnitHeader(bs); + } + catch(...) + { + LogDebug("HevcNalDecode:processNALUnit exception ..."); + return NAL_FAIL; + } + + switch(type) + { + case NAL_SPS: + { + std::shared_ptr psps(new SPS); + try + { + processSPS(psps, bs); + } + catch(...) + { + LogDebug("HevcNalDecode:processSPS exception ..."); + return NAL_FAIL; + } + + //Assign values to hevchdr elements + h.chromaFormat = psps -> chroma_format_idc; + + h.width = psps -> pic_width_in_luma_samples; + h.height = psps -> pic_height_in_luma_samples; + if (h.height == 1088) h.height = 1080; // Prevent blur lines + + h.lumaDepth = psps -> bit_depth_luma_minus8 + 8; // bit_depth_luma_minus8 + h.chromaDepth = psps -> bit_depth_chroma_minus8 + 8; // bit_depth_chroma_minus8 + + h.progressive = (psps->profile_tier_level.general_progressive_source_flag > 0); + + h.profile = psps->profile_tier_level.general_profile_idc; + h.level = psps->profile_tier_level.general_level_idc; + + if(psps -> vui_parameters_present_flag) + { + if (psps->vui_parameters.aspect_ratio_info_present_flag) + { + h.ar = psps->vui_parameters.aspect_ratio_idc; + if(h.ar == 255) //EXTENDED_SAR + { + h.arx = psps->vui_parameters.sar_width; + h.ary = psps->vui_parameters.sar_height; + // make sure that both are 0 if one is 0 + if(h.arx == 0 || h.ary == 0) + { + h.arx = 0; + h.ary = 0; + } + } + else //Look up the aspect ratio from a table + { + struct {int x, y;} ar[] = {{0,0},{1,1},{12,11},{10,11},{16,11},{40,33},{24,11},{20,11},{32,11},{80,33},{18,11},{15,11},{64,33},{160,99},{4,3},{3,2},{2,1}}; + if(h.ar > 16) + { + // aspect ratio reserved + h.arx = 0; + h.ary = 0; + } + else + { + // use preset aspect ratio + h.arx = ar[h.ar].x; + h.ary = ar[h.ar].y; + } + } + + h.arx *= h.width; + h.ary *= h.height; + + uint32_t a = h.arx, b = h.ary; + while(a) {uint32_t tmp = a; a = b % tmp; b = tmp;} + if(b) h.arx /= b, h.ary /= b; + } + + if (psps->vui_parameters.vui_timing_info_present_flag) + { + if ((psps->vui_parameters.vui_time_scale > 0) && (psps->vui_parameters.vui_num_units_in_tick > 0)) + { + h.AvgTimePerFrame = (__int64)((10000000.0 * (double)psps->vui_parameters.vui_num_units_in_tick)/(double)psps->vui_parameters.vui_time_scale); + } + } + } + + if (h.arx == 0 && h.ary == 0) //Do something sensible if aspect ratio info not present + { + if (h.width > 0 && h.width > 0) + { + h.arx = h.width; + h.ary = h.height; + + uint32_t a = h.arx, b = h.ary; + while(a) {uint32_t tmp = a; a = b % tmp; b = tmp;} + if(b) h.arx /= b, h.ary /= b; + } + } + + break; + } + + default: {} //Do not decode any other NALs + }; + + return type; +} + +//Remove 'emulation_prevention_three_byte' characters and copy to new buffer +void HevcNalDecode::Remove3Byte(uint8_t* dst, const uint8_t* src, int length) +{ + int si=0; + int di=0; + while(si+23){ + dst[di++]= src[si++]; + dst[di++]= src[si++]; + } + else if(src[si]==0 && src[si+1]==0){ + if(src[si+2]==3){ //escape + dst[di++]= 0; + dst[di++]= 0; + si+=3; + continue; + } + else //next start code + return; + } + + dst[di++]= src[si++]; + } +} + + +NALUnitType HevcNalDecode::processNALUnitHeader(BitstreamReader &bs) +{ + //forbidden_zero_bit + bs.getBit(); + + NALUnitType type = (NALUnitType)bs.getBits(6); + + //nuh_layer_id + bs.getBits(6); + + //nuh_temporal_id_plus1 + bs.getBits(3); + return type; +} + +void HevcNalDecode::processSPS(std::shared_ptr psps, BitstreamReader &bs) +{ + psps -> sps_video_parameter_set_id = bs.getBits(4); + psps -> sps_max_sub_layers_minus1 = bs.getBits(3); + psps -> sps_temporal_id_nesting_flag = bs.getBits(1); + psps -> profile_tier_level = processProfileTierLevel(psps -> sps_max_sub_layers_minus1, bs); + + psps -> sps_seq_parameter_set_id = bs.getGolombU(); + psps -> chroma_format_idc = bs.getGolombU(); + + if(psps -> chroma_format_idc == 3) + psps -> separate_colour_plane_flag = bs.getBits(1); + else + psps -> separate_colour_plane_flag = 0; + + psps -> pic_width_in_luma_samples = bs.getGolombU(); + psps -> pic_height_in_luma_samples = bs.getGolombU(); + psps -> conformance_window_flag = bs.getBits(1); + + if(psps -> conformance_window_flag) + { + psps -> conf_win_left_offset = bs.getGolombU(); + psps -> conf_win_right_offset = bs.getGolombU(); + psps -> conf_win_top_offset = bs.getGolombU(); + psps -> conf_win_bottom_offset = bs.getGolombU(); + } + + psps -> bit_depth_luma_minus8 = bs.getGolombU(); + psps -> bit_depth_chroma_minus8 = bs.getGolombU(); + psps -> log2_max_pic_order_cnt_lsb_minus4 = bs.getGolombU(); + psps -> sps_sub_layer_ordering_info_present_flag = bs.getBits(1); + + psps -> sps_max_dec_pic_buffering_minus1.resize(psps -> sps_max_sub_layers_minus1 + 1, 0); + psps -> sps_max_num_reorder_pics.resize(psps -> sps_max_sub_layers_minus1 + 1, 0); + psps -> sps_max_latency_increase_plus1.resize(psps -> sps_max_sub_layers_minus1 + 1, 0); + + for(std::size_t i=(psps -> sps_sub_layer_ordering_info_present_flag ? 0 : psps -> sps_max_sub_layers_minus1); + i<=psps -> sps_max_sub_layers_minus1; + i++) + { + psps -> sps_max_dec_pic_buffering_minus1[i] = bs.getGolombU(); + psps -> sps_max_num_reorder_pics[i] = bs.getGolombU(); + psps -> sps_max_latency_increase_plus1[i] = bs.getGolombU(); + } + + psps -> log2_min_luma_coding_block_size_minus3 = bs.getGolombU(); + psps -> log2_diff_max_min_luma_coding_block_size = bs.getGolombU(); + psps -> log2_min_transform_block_size_minus2 = bs.getGolombU(); + psps -> log2_diff_max_min_transform_block_size = bs.getGolombU(); + psps -> max_transform_hierarchy_depth_inter = bs.getGolombU(); + psps -> max_transform_hierarchy_depth_intra = bs.getGolombU(); + + psps -> scaling_list_enabled_flag = bs.getBits(1); + if(psps -> scaling_list_enabled_flag) + { + psps -> sps_scaling_list_data_present_flag = bs.getBits(1); + if(psps -> sps_scaling_list_data_present_flag) + { + psps -> scaling_list_data = processScalingListData(bs); + } + } + + psps -> amp_enabled_flag = bs.getBits(1); + psps -> sample_adaptive_offset_enabled_flag = bs.getBits(1); + psps -> pcm_enabled_flag = bs.getBits(1); + + if(psps -> pcm_enabled_flag) + { + psps -> pcm_sample_bit_depth_luma_minus1 = bs.getBits(4); + psps -> pcm_sample_bit_depth_chroma_minus1 = bs.getBits(4); + psps -> log2_min_pcm_luma_coding_block_size_minus3 = bs.getGolombU(); + psps -> log2_diff_max_min_pcm_luma_coding_block_size = bs.getGolombU(); + psps -> pcm_loop_filter_disabled_flag = bs.getBits(1); + } + + psps -> num_short_term_ref_pic_sets = bs.getGolombU(); + + psps -> short_term_ref_pic_set.resize(psps -> num_short_term_ref_pic_sets); + for(std::size_t i=0; i num_short_term_ref_pic_sets; i++) + psps -> short_term_ref_pic_set[i] = processShortTermRefPicSet(i, psps -> num_short_term_ref_pic_sets, psps -> short_term_ref_pic_set, psps, bs); + + psps -> long_term_ref_pics_present_flag = bs.getBits(1); + if(psps -> long_term_ref_pics_present_flag) + { + psps -> num_long_term_ref_pics_sps = bs.getGolombU(); + psps -> lt_ref_pic_poc_lsb_sps.resize(psps -> num_long_term_ref_pics_sps); + psps -> used_by_curr_pic_lt_sps_flag.resize(psps -> num_long_term_ref_pics_sps); + + for(std::size_t i = 0; i num_long_term_ref_pics_sps; i++) + { + psps -> lt_ref_pic_poc_lsb_sps[i] = bs.getBits(psps -> log2_max_pic_order_cnt_lsb_minus4 + 4); + psps -> used_by_curr_pic_lt_sps_flag[i] = bs.getBits(1); + } + } + + psps -> sps_temporal_mvp_enabled_flag = bs.getBits(1); + psps -> strong_intra_smoothing_enabled_flag = bs.getBits(1); + psps -> vui_parameters_present_flag = bs.getBits(1); + + if(psps -> vui_parameters_present_flag) + { + psps -> vui_parameters = processVuiParameters(psps -> sps_max_sub_layers_minus1, bs); + } + + psps -> sps_extension_flag = bs.getBits(1); +} + + +//======================================================================= + +VuiParameters HevcNalDecode::processVuiParameters(std::size_t sps_max_sub_layers_minus1, BitstreamReader &bs) +{ + VuiParameters vui; + + vui.toDefault(); + + vui.aspect_ratio_idc = 0; + vui.sar_width = 0; + vui.sar_height = 0; + + + vui.aspect_ratio_info_present_flag = bs.getBits(1); + + if(vui.aspect_ratio_info_present_flag) + { + vui.aspect_ratio_idc = bs.getBits(8); + + if(vui.aspect_ratio_idc == 255) //EXTENDED_SAR + { + vui.sar_width = bs.getBits(16); + vui.sar_height = bs.getBits(16); + } + } + + + vui.overscan_info_present_flag = bs.getBits(1); + if(vui.overscan_info_present_flag) + vui.overscan_appropriate_flag = bs.getBits(1); + + vui.video_format = 5; + vui.video_full_range_flag = 0; + vui.colour_primaries = 2; + vui.transfer_characteristics = 2; + vui.matrix_coeffs = 2; + + vui.video_signal_type_present_flag = bs.getBits(1); + + if(vui.video_signal_type_present_flag) + { + vui.video_format = bs.getBits(3); + vui.video_full_range_flag = bs.getBits(1); + vui.colour_description_present_flag = bs.getBits(1); + + if(vui.colour_description_present_flag) + { + vui.colour_primaries = bs.getBits(8); + vui.transfer_characteristics = bs.getBits(8); + vui.matrix_coeffs = bs.getBits(8); + } + + } + + vui.chroma_sample_loc_type_top_field = 0; + vui.chroma_sample_loc_type_bottom_field = 0; + + vui.chroma_loc_info_present_flag = bs.getBits(1); + if(vui.chroma_loc_info_present_flag) + { + vui.chroma_sample_loc_type_top_field = bs.getGolombU(); + vui.chroma_sample_loc_type_bottom_field = bs.getGolombU(); + } + + + vui.neutral_chroma_indication_flag = bs.getBits(1); + vui.field_seq_flag = bs.getBits(1); + vui.frame_field_info_present_flag = bs.getBits(1); + vui.default_display_window_flag = bs.getBits(1); + + vui.def_disp_win_left_offset = 0; + vui.def_disp_win_right_offset = 0; + vui.def_disp_win_right_offset = 0; + vui.def_disp_win_bottom_offset = 0; + + if(vui.default_display_window_flag) + { + vui.def_disp_win_left_offset = bs.getGolombU(); + vui.def_disp_win_right_offset = bs.getGolombU(); + vui.def_disp_win_top_offset = bs.getGolombU(); + vui.def_disp_win_bottom_offset = bs.getGolombU(); + } + + vui.vui_timing_info_present_flag = bs.getBits(1); + + if(vui.vui_timing_info_present_flag) + { + vui.vui_num_units_in_tick = bs.getBits(32); + vui.vui_time_scale = bs.getBits(32); + vui.vui_poc_proportional_to_timing_flag = bs.getBits(1); + + if(vui.vui_poc_proportional_to_timing_flag) + vui.vui_num_ticks_poc_diff_one_minus1 = bs.getGolombU(); + + vui.vui_hrd_parameters_present_flag = bs.getBits(1); + + if(vui.vui_hrd_parameters_present_flag) + vui.hrd_parameters = processHrdParameters(1, sps_max_sub_layers_minus1, bs); + } + + vui.bitstream_restriction_flag = bs.getBits(1); + + if(vui.bitstream_restriction_flag) + { + vui.tiles_fixed_structure_flag = bs.getBits(1); + vui.motion_vectors_over_pic_boundaries_flag = bs.getBits(1); + vui.restricted_ref_pic_lists_flag = bs.getBits(1); + + vui.min_spatial_segmentation_idc = bs.getGolombU(); + vui.max_bytes_per_pic_denom = bs.getGolombU(); + vui.max_bits_per_min_cu_denom = bs.getGolombU(); + vui.log2_max_mv_length_horizontal = bs.getGolombU(); + vui.log2_max_mv_length_vertical = bs.getGolombU(); + } + + return vui; +} + +//======================================================================= + +ProfileTierLevel HevcNalDecode::processProfileTierLevel(std::size_t max_sub_layers_minus1, BitstreamReader &bs) +{ + ProfileTierLevel ptl; + + ptl.toDefault(); + + ptl.general_profile_space = bs.getBits(2); + ptl.general_tier_flag = bs.getBits(1); + ptl.general_profile_idc = bs.getBits(5); + + for(std::size_t i=0; i<32; i++) + ptl.general_profile_compatibility_flag[i] = bs.getBits(1); + + ptl.general_progressive_source_flag = bs.getBits(1); + ptl.general_interlaced_source_flag = bs.getBits(1); + ptl.general_non_packed_constraint_flag = bs.getBits(1); + ptl.general_frame_only_constraint_flag = bs.getBits(1); + bs.getBits(32); + bs.getBits(12); + ptl.general_level_idc = bs.getBits(8); + + ptl.sub_layer_profile_present_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_level_present_flag.resize(max_sub_layers_minus1); + + for(std::size_t i=0; i 0) + { + for(std::size_t i=max_sub_layers_minus1; i<8; i++) + bs.getBits(2); + } + + ptl.sub_layer_profile_space.resize(max_sub_layers_minus1); + ptl.sub_layer_tier_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_profile_idc.resize(max_sub_layers_minus1); + ptl.sub_layer_profile_compatibility_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_progressive_source_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_interlaced_source_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_non_packed_constraint_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_frame_only_constraint_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_level_idc.resize(max_sub_layers_minus1); + + for(std::size_t i=0; i= 2) + sc.scaling_list_dc_coef_minus8[sizeId-2].resize(6); + } + + for(std::size_t matrixId = 0; matrixId<(size_t)((sizeId == 3)?2:6); matrixId++) + { + sc.scaling_list_pred_mode_flag[sizeId][matrixId] = bs.getBits(1); + if(!sc.scaling_list_pred_mode_flag[sizeId][matrixId]) + sc.scaling_list_pred_matrix_id_delta[sizeId][matrixId] = bs.getGolombU(); + else + { + std::size_t nextCoef = 8; + std::size_t coefNum = std::min(64, (1 << (4 + (sizeId << 1)))); + if(sizeId > 1) + sc.scaling_list_dc_coef_minus8[sizeId-2][matrixId] = bs.getGolombS(); + + sc.scaling_list_delta_coef[sizeId][matrixId].resize(coefNum); + for(std::size_t i = 0; i < coefNum; i++) + sc.scaling_list_delta_coef[sizeId][matrixId][i] = bs.getGolombS(); + } + } + } + + return sc; +} + +//======================================================================= + +ShortTermRefPicSet HevcNalDecode::processShortTermRefPicSet(std::size_t stRpsIdx, std::size_t num_short_term_ref_pic_sets, const std::vector &refPicSets, std::shared_ptr psps, BitstreamReader &bs) +{ + ShortTermRefPicSet rpset; + + rpset.toDefault(); + + rpset.inter_ref_pic_set_prediction_flag = 0; + rpset.delta_idx_minus1 = 0; + if(stRpsIdx) + { + rpset.inter_ref_pic_set_prediction_flag = bs.getBits(1); + } + + if(rpset.inter_ref_pic_set_prediction_flag) + { + if(stRpsIdx == num_short_term_ref_pic_sets) + rpset.delta_idx_minus1 = bs.getGolombU(); + + rpset.delta_rps_sign = bs.getBits(1); + rpset.abs_delta_rps_minus1 = bs.getGolombU(); + + std::size_t RefRpsIdx = stRpsIdx - (rpset.delta_idx_minus1 + 1); + std::size_t NumDeltaPocs = 0; + + if(refPicSets[RefRpsIdx].inter_ref_pic_set_prediction_flag) + { + for(std::size_t i=0; i psps -> sps_max_dec_pic_buffering_minus1[psps -> sps_max_sub_layers_minus1]) + { + LogDebug("HevcNalDecode:ShortTermRefPicSet: num_negative_pics > sps_max_dec_pic_buffering_minus1"); + return rpset; + } + + if(rpset.num_positive_pics > psps -> sps_max_dec_pic_buffering_minus1[psps -> sps_max_sub_layers_minus1]) + { + LogDebug("HevcNalDecode:ShortTermRefPicSet: num_positive_pics > sps_max_dec_pic_buffering_minus1"); + return rpset; + } + + rpset.delta_poc_s0_minus1.resize(rpset.num_negative_pics); + rpset.used_by_curr_pic_s0_flag.resize(rpset.num_negative_pics); + + for(std::size_t i=0; i. + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#ifndef HEVC_NAL_DECODE +#define HEVC_NAL_DECODE + +#include "Hevc.h" +#include "BitstreamReader.h" + +#include +#include +#include + +namespace HEVC +{ + class HevcNalDecode + { + public: + NALUnitType processNALUnit(const uint8_t *pdata, std::size_t size, hevchdr& h); + + protected: + NALUnitType processNALUnitHeader(BitstreamReader &bs); + void Remove3Byte(uint8_t* dst, const uint8_t* src, int length); + void processSPS(std::shared_ptr psps, BitstreamReader &bs); + ProfileTierLevel processProfileTierLevel(std::size_t max_sub_layers_minus1, BitstreamReader &bs); + HrdParameters processHrdParameters(uint8_t commonInfPresentFlag, std::size_t maxNumSubLayersMinus1, BitstreamReader &bs); + ShortTermRefPicSet processShortTermRefPicSet(std::size_t stRpsIdx, size_t num_short_term_ref_pic_sets, const std::vector &refPicSets, std::shared_ptr psps, BitstreamReader &bs); + VuiParameters processVuiParameters(std::size_t sps_max_sub_layers_minus1, BitstreamReader &bs); + ScalingListData processScalingListData(BitstreamReader &bs); + SubLayerHrdParameters processSubLayerHrdParameters(uint8_t sub_pic_hrd_params_present_flag, std::size_t CpbCnt, BitstreamReader &bs); + }; +} + +#endif + diff --git a/DirectShowFilters/BDReader/source/StreamParser.cpp b/DirectShowFilters/BDReader/source/StreamParser.cpp index 12c0e555b8f..8ca5e607f16 100644 --- a/DirectShowFilters/BDReader/source/StreamParser.cpp +++ b/DirectShowFilters/BDReader/source/StreamParser.cpp @@ -28,10 +28,13 @@ #include "StreamParser.h" #include #include +#include "HEVC\Hevc.h" // For more details for memory leak detection see the alloctracing.h header #include "..\..\alloctracing.h" +using namespace HEVC; + extern void LogDebug(const char *fmt, ...) ; StreamParser::StreamParser() From 8e6a8271cd9f2dae17f7098b9458a126f01e2eee Mon Sep 17 00:00:00 2001 From: epbk Date: Mon, 6 Nov 2023 16:57:50 +0100 Subject: [PATCH 7/7] MP1-5180: BDReader: Update project configuration --- DirectShowFilters/BDReader/BDReader.vcxproj | 6 ++++++ DirectShowFilters/BDReader/source/FrameHeaderParser.cpp | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/DirectShowFilters/BDReader/BDReader.vcxproj b/DirectShowFilters/BDReader/BDReader.vcxproj index 51daeb26d41..727a6f02089 100644 --- a/DirectShowFilters/BDReader/BDReader.vcxproj +++ b/DirectShowFilters/BDReader/BDReader.vcxproj @@ -353,6 +353,9 @@ + + + @@ -377,6 +380,9 @@ + + + diff --git a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp index 5206e138151..cf317bc16ac 100644 --- a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp +++ b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp @@ -1686,8 +1686,6 @@ bool CFrameHeaderParser::Read(hevchdr& h, int len, CMediaType* pmt) h.progressive = true; h.AvgTimePerFrame = 370000; //27 Hz - BYTE* pBuff = GetBufferPos(); - while (GetRemaining() > 4 && (h.spslen == 0 || h.ppslen == 0 || h.vpslen == 0)) { const int nal_len = BitRead(32);