/// <summary> /// Adds log information and movement vector metadata to a given frame /// </summary> /// <param name="frame"> /// The basic frame to be enhanced with metadata /// </param> /// <param name="macroblockPartitionData"> /// A byte array containing the macroblock decision information to be added to the frame. /// Invalid values yield undefined behavior. /// </param> /// <param name="vectorData"> /// An array of arrays containing the vector data to be added to the frame. /// If not enough data is present, the two-dimensional zero vector (0,0) is used for all remaining macroblocks. /// </param> /// <param name="index"> /// The index of the given frame in the video stream. /// Used for selecting the right metadata for the given frame. /// </param> /// <returns> /// An instance of AnnotatedFrame bearing the given parameters as source of information. /// </returns> private static AnnotatedFrame AddAnnotations(Frame frame, byte[] macroblockPartitionData, int[][] vectorData, int index) { int macroBlockNumber = frame.Size.Width / 16 * frame.Size.Height / 16; MacroblockDecision[] decisions = new MacroblockDecision[macroBlockNumber]; for (int i = 0; i < decisions.Length; i++) { decisions[i] = new MacroblockDecision(); } if (macroblockPartitionData != null) { for (int i = 0; i < decisions.Length && macroBlockNumber * index + i < macroblockPartitionData.Length; i++) { decisions[i].PartitioningDecision = (MacroblockPartitioning)macroblockPartitionData[macroBlockNumber * index + i]; } } if (vectorData != null) { for (int i = 0; i < decisions.Length; i++) { // if we run out of vectors just pretend there are plenty zero vectors if (index < vectorData.Length && vectorData[index].Length > i * 2 + 1) { decisions[i].Movement = new Vector(vectorData[index][i * 2], vectorData[index][i * 2 + 1]); } else { decisions[i].Movement = new Vector(0, 0); } } } return(new AnnotatedFrame(frame, decisions)); }
/// <summary> /// Generates an AnnotatedFrame with randomly filled Data and the given Macroblock decisions. /// </summary> /// <returns> An annotated Frame with random Data and the given Macroblock decisions.</returns> public static AnnotatedFrame GenerateAnnFrame(MacroblockDecision[,] decisions) { var testSize = new YuvKA.VideoModel.Size(8, 8); var output = new AnnotatedFrame(testSize, decisions); for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { output[x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y)); } } return output; }
/// <summary> /// Adds log information and movement vector metadata to a given frame /// </summary> /// <param name="frame"> /// The basic frame to be enhanced with metadata /// </param> /// <param name="macroblockPartitionData"> /// A byte array containing the macroblock decision information to be added to the frame. /// Invalid values yield undefined behavior. /// </param> /// <param name="vectorData"> /// An array of arrays containing the vector data to be added to the frame. /// If not enough data is present, the two-dimensional zero vector (0,0) is used for all remaining macroblocks. /// </param> /// <param name="index"> /// The index of the given frame in the video stream. /// Used for selecting the right metadata for the given frame. /// </param> /// <returns> /// An instance of AnnotatedFrame bearing the given parameters as source of information. /// </returns> private static AnnotatedFrame AddAnnotations(Frame frame, byte[] macroblockPartitionData, int[][] vectorData, int index) { int macroBlockNumber = frame.Size.Width / 16 * frame.Size.Height / 16; MacroblockDecision[] decisions = new MacroblockDecision[macroBlockNumber]; for (int i = 0; i < decisions.Length; i++) { decisions[i] = new MacroblockDecision(); } if (macroblockPartitionData != null) { for (int i = 0; i < decisions.Length && macroBlockNumber * index + i < macroblockPartitionData.Length; i++) { decisions[i].PartitioningDecision = (MacroblockPartitioning)macroblockPartitionData[macroBlockNumber * index + i]; } } if (vectorData != null) { for (int i = 0; i < decisions.Length; i++) { // if we run out of vectors just pretend there are plenty zero vectors if (index < vectorData.Length && vectorData[index].Length > i * 2 + 1) { decisions[i].Movement = new Vector(vectorData[index][i * 2], vectorData[index][i * 2 + 1]); } else { decisions[i].Movement = new Vector(0, 0); } } } return new AnnotatedFrame(frame, decisions); }
public void TestVecorOverlay() { Frame testFrame = new Frame(new YuvKA.VideoModel.Size(64, 48)); for (int x = 0; x < testFrame.Size.Width; x++) { for (int y = 0; y < testFrame.Size.Height; y++) { testFrame[x, y] = new Rgb(111, 111, 111); } } MacroblockDecision[] decisions = new MacroblockDecision[12]; decisions[0] = new MacroblockDecision { Movement = new Vector(0.0, 12.0) }; decisions[1] = new MacroblockDecision { Movement = new Vector(12.0, 12.0) }; decisions[2] = new MacroblockDecision { Movement = new Vector(12.0, 0.0) }; decisions[3] = new MacroblockDecision { Movement = new Vector(12.0, -12.0) }; decisions[4] = new MacroblockDecision { Movement = new Vector(3.0, -12.0) }; decisions[5] = new MacroblockDecision { Movement = new Vector(-38.0, -15.0) }; decisions[6] = new MacroblockDecision { Movement = new Vector(-120.0, 0.0) }; decisions[7] = new MacroblockDecision { Movement = new Vector(-20.0, 20.0) }; decisions[8] = new MacroblockDecision { Movement = new Vector(4.0, 0.0) }; decisions[9] = new MacroblockDecision { Movement = new Vector(0.0, 4.0) }; decisions[10] = new MacroblockDecision { Movement = new Vector(4.0, 4.0) }; decisions[11] = new MacroblockDecision { Movement = new Vector(-4.0, 0.0) }; Frame[] input = { new AnnotatedFrame(testFrame, decisions) }; OverlayNode node = new OverlayNode { Type = new MoveVectorsOverlay() }; node.ProcessCore(input, 0); List<Frame> output = new List<Frame>(); output.Add(node.Data); YuvEncoder.Encode(@"..\..\..\..\output\VectorOverlayTest_64x48.yuv", output); }
public void TestMacroBlockOverlay() { Frame testFrame = new Frame(new YuvKA.VideoModel.Size(64, 64)); for (int x = 0; x < testFrame.Size.Width; x++) { for (int y = 0; y < testFrame.Size.Height; y++) { testFrame[x, y] = new Rgb(111, 111, 111); } } MacroblockDecision[] decisions = new MacroblockDecision[16]; decisions[0] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.InterSkip }; decisions[1] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter16x16 }; decisions[2] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter16x8 }; decisions[3] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter8x16 }; decisions[4] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter8x8 }; decisions[5] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter4x8 }; decisions[6] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter8x4 }; decisions[7] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter4x4 }; decisions[8] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Intra16x16 }; decisions[9] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Intra8x8 }; decisions[10] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Intra4x4 }; decisions[11] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Unknown }; decisions[12] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter8x8OrBelow }; decisions[13] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.IntraPCM }; decisions[14] = new MacroblockDecision { PartitioningDecision = null }; decisions[15] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Unknown }; Frame[] input = { new AnnotatedFrame(testFrame, decisions) }; OverlayNode node = new OverlayNode { Type = new BlocksOverlay() }; node.ProcessCore(input, 0); List<Frame> output = new List<Frame>(); output.Add(node.Data); YuvEncoder.Encode(@"..\..\..\..\output\BlockOverlayTest_64x64.yuv", output); }