private void ParallelDecoding(int threadNum, VideoFile video, int possibleMultiFors, int numOfThreads, int?startValue = null, int?endValue = null) { int[,] yDctQuan, cBDctQuan, cRDctQuan, yDiffEncoded, cBDiffEncoded, cRDiffEncoded; int[] yRunLenEncoded, cBRunLenEncoded, cRRunLenEncoded; int offset = possibleMultiFors * keyFrameEvery; int start; int finish; if (startValue != null) { start = (int)startValue; if (endValue != null) { finish = (int)endValue; } else { finish = tempImages.Length; } } else { start = threadNum * offset; finish = (threadNum + 1) * offset; } int[,] yDctQuanDiff = null; int[,] cBDctQuanDiff = null; int[,] cRDctQuanDiff = null; int[,] yDctQuanFromLastFrame = null; int[,] cBDctQuanFromLastFrame = null; int[,] cRDctQuanFromLastFrame = null; for (int i = start; i < finish; i++) { // huffman decoding yRunLenEncoded = HuffmanDecoding(YBitArray[i], video.YHuffmanCounts[i / keyFrameEvery]); cBRunLenEncoded = HuffmanDecoding(CbBitArray[i], video.CbHuffmanCounts[i / keyFrameEvery]); cRRunLenEncoded = HuffmanDecoding(CrBitArray[i], video.CrHuffmanCounts[i / keyFrameEvery]); //Tester.PrintToFile("yRunLenEncodedAfter", yRunLenEncoded); // run length decoding if (subsamplingMode == "4:4:4") { yDiffEncoded = RunLengthEncode.Decode(yRunLenEncoded, 8, video.width, video.height); cBDiffEncoded = RunLengthEncode.Decode(cBRunLenEncoded, 8, video.width, video.height); cRDiffEncoded = RunLengthEncode.Decode(cRRunLenEncoded, 8, video.width, video.height); } else if (subsamplingMode == "4:2:2") { yDiffEncoded = RunLengthEncode.Decode(yRunLenEncoded, 8, video.width, video.height); cBDiffEncoded = RunLengthEncode.Decode(cBRunLenEncoded, 8, video.width / 2, video.height); cRDiffEncoded = RunLengthEncode.Decode(cRRunLenEncoded, 8, video.width / 2, video.height); } else { yDiffEncoded = RunLengthEncode.Decode(yRunLenEncoded, 8, video.width, video.height); cBDiffEncoded = RunLengthEncode.Decode(cBRunLenEncoded, 8, video.width / 2, video.height / 2); cRDiffEncoded = RunLengthEncode.Decode(cRRunLenEncoded, 8, video.width / 2, video.height / 2); } //Tester.PrintToFile("yDiffEncodedAfter", yDiffEncoded); // differential decoding yDctQuan = DifferentialEncoding.Decode(yDiffEncoded, 8); cBDctQuan = DifferentialEncoding.Decode(cBDiffEncoded, 8); cRDctQuan = DifferentialEncoding.Decode(cRDiffEncoded, 8); // it's not a keyframe if (i % keyFrameEvery != 0) { yDctQuanDiff = yDctQuan; cBDctQuanDiff = cBDctQuan; cRDctQuanDiff = cRDctQuan; for (int j = 0; j < yDctQuanFromLastFrame.GetLength(0); j++) { for (int k = 0; k < yDctQuanFromLastFrame.GetLength(1); k++) { yDctQuan[j, k] = yDctQuanFromLastFrame[j, k] + yDctQuanDiff[j, k]; if (subsamplingMode == "4:4:4") { cBDctQuan[j, k] = cBDctQuanFromLastFrame[j, k] + cBDctQuanDiff[j, k]; cRDctQuan[j, k] = cRDctQuanFromLastFrame[j, k] + cRDctQuanDiff[j, k]; } } } if (subsamplingMode != "4:4:4") { for (int j = 0; j < cBDctQuanFromLastFrame.GetLength(0); j++) { for (int k = 0; k < cBDctQuanFromLastFrame.GetLength(1); k++) { cBDctQuan[j, k] = cBDctQuanFromLastFrame[j, k] + cBDctQuanDiff[j, k]; cRDctQuan[j, k] = cRDctQuanFromLastFrame[j, k] + cRDctQuanDiff[j, k]; } } } } yDctQuanFromLastFrame = yDctQuan; cBDctQuanFromLastFrame = cBDctQuan; cRDctQuanFromLastFrame = cRDctQuan; // Tester.PrintToFile("yDctQuanAfter", yDctQuan); // revert dct and quantization DctImage dctImage = new DctImage(video.quality, video.subsamplingMode); int[,] YMatrix = dctImage.RevertDctAndQuantization(yDctQuan); int[,] CbMatrix = dctImage.RevertDctAndQuantization(cBDctQuan); int[,] CrMatrix = dctImage.RevertDctAndQuantization(cRDctQuan); if (subsamplingMode == "4:4:4") { YMatrix = dctImage.TrimValueMatrix(YMatrix, video.width, video.height); CbMatrix = dctImage.TrimValueMatrix(CbMatrix, video.width, video.height); CrMatrix = dctImage.TrimValueMatrix(CrMatrix, video.width, video.height); } else if (subsamplingMode == "4:2:2") { YMatrix = dctImage.TrimValueMatrix(YMatrix, video.width, video.height); CbMatrix = dctImage.TrimValueMatrix(CbMatrix, video.width / 2, video.height); CrMatrix = dctImage.TrimValueMatrix(CrMatrix, video.width / 2, video.height); } else { YMatrix = dctImage.TrimValueMatrix(YMatrix, video.width, video.height); CbMatrix = dctImage.TrimValueMatrix(CbMatrix, video.width / 2, video.height / 2); CrMatrix = dctImage.TrimValueMatrix(CrMatrix, video.width / 2, video.height / 2); } // instantiate YCbCr images YCbCrImage tempImage = new YCbCrImage(YMatrix.GetLength(0), YMatrix.GetLength(1), subsamplingMode); for (int j = 0; j < YMatrix.GetLength(0); j++) { for (int k = 0; k < YMatrix.GetLength(1); k++) { if (subsamplingMode == "4:4:4") { tempImage.pixels[j, k] = new YCbCrPixel(YMatrix[j, k], CbMatrix[j, k], CrMatrix[j, k]); } else if (subsamplingMode == "4:2:2") { double Cb = CbMatrix[(j / 2), k]; double Cr = CrMatrix[(j / 2), k]; tempImage.pixels[j, k] = new YCbCrPixel(YMatrix[j, k], Cb, Cr); } else if (subsamplingMode == "4:2:0") { double Cb = CbMatrix[(j / 2), (k / 2)]; double Cr = CrMatrix[(j / 2), (k / 2)]; tempImage.pixels[j, k] = new YCbCrPixel(YMatrix[j, k], Cb, Cr); } } } tempImages[i] = tempImage; MethodInvoker mi = new MethodInvoker(() => { int newValue = progressBar.Value + numOfThreads; if (newValue <= outputImages.Length) { progressBar.Value = newValue; } else { progressBar.Value = outputImages.Length; } }); if (!progressBar.InvokeRequired) { mi.Invoke(); } } }
public void ParallelEncoding(int threadNum, int possibleMultiFors, int numOfThreads, int?startValue = null, int?endValue = null) { int[,] yDctQuan, cBDctQuan, cRDctQuan, yDiffEncoded, cBDiffEncoded, cRDiffEncoded; int[] yRunLenEncoded, cBRunLenEncoded, cRRunLenEncoded; int[,] accumulatedChangesY = null; int[,] accumulatedChangesCb = null; int[,] accumulatedChangesCr = null; int[,] actualValuesY = null; int[,] actualValuesCb = null; int[,] actualValuesCr = null; List <int[, ]> actualValuesListY = new List <int[, ]>(); List <int[, ]> actualValuesListCb = new List <int[, ]>(); List <int[, ]> actualValuesListCr = new List <int[, ]>(); // needed for multi huffman encoding int[][] YHuffmanValues = new int[keyFrameEvery][]; int[][] CbHuffmanValues = new int[keyFrameEvery][]; int[][] CrHuffmanValues = new int[keyFrameEvery][]; int offset = possibleMultiFors * keyFrameEvery; int start; int finish; if (startValue != null) { start = (int)startValue; if (endValue != null) { finish = (int)endValue; } else { finish = tempImages.Length; } } else { start = threadNum * offset; finish = (threadNum + 1) * offset; } int[,] yDctQuanDiff = null; int[,] cBDctQuanDiff = null; int[,] cRDctQuanDiff = null; int[,] yDctQuanFromLastFrame = null; int[,] cBDctQuanFromLastFrame = null; int[,] cRDctQuanFromLastFrame = null; for (int i = start; i < finish; i++) { DctImage dctImage = new DctImage(tempImages[i], quality, actualValuesListY, actualValuesListCb, actualValuesListCr, actualValuesY, actualValuesCb, actualValuesCr, accumulatedChangesY, accumulatedChangesCb, accumulatedChangesCr); yDctQuan = dctImage.PerformDctAndQuantization(tempImages[i], "Y"); cBDctQuan = dctImage.PerformDctAndQuantization(tempImages[i], "Cb"); cRDctQuan = dctImage.PerformDctAndQuantization(tempImages[i], "Cr"); // it's not a keyframe if (i % keyFrameEvery != 0) { for (int j = 0; j < yDctQuanFromLastFrame.GetLength(0); j++) { for (int k = 0; k < yDctQuanFromLastFrame.GetLength(1); k++) { //yDctQuanDiff[j, k] = GetOptimizedDifference(yDctQuan[j, k] - yDctQuanFromLastFrame[j, k], "y"); yDctQuanDiff[j, k] = yDctQuan[j, k] - yDctQuanFromLastFrame[j, k]; if (subsamplingMode == "4:4:4") { //cBDctQuanDiff[j, k] = GetOptimizedDifference(cBDctQuan[j, k] - cBDctQuanFromLastFrame[j, k], "cB"); cBDctQuanDiff[j, k] = cBDctQuan[j, k] - cBDctQuanFromLastFrame[j, k]; //cRDctQuanDiff[j, k] = GetOptimizedDifference(cRDctQuan[j, k] - cRDctQuanFromLastFrame[j, k], "cR"); cRDctQuanDiff[j, k] = cRDctQuan[j, k] - cRDctQuanFromLastFrame[j, k]; } } } if (subsamplingMode != "4:4:4") { for (int j = 0; j < cBDctQuanFromLastFrame.GetLength(0); j++) { for (int k = 0; k < cBDctQuanFromLastFrame.GetLength(1); k++) { //cBDctQuanDiff[j, k] = GetOptimizedDifference(cBDctQuan[j, k] - cBDctQuanFromLastFrame[j, k], "cB"); cBDctQuanDiff[j, k] = cBDctQuan[j, k] - cBDctQuanFromLastFrame[j, k]; //cRDctQuanDiff[j, k] = GetOptimizedDifference(cRDctQuan[j, k] - cRDctQuanFromLastFrame[j, k], "cR"); cRDctQuanDiff[j, k] = cRDctQuan[j, k] - cRDctQuanFromLastFrame[j, k]; } } } } else { // but actually it's a keyframe yDctQuanDiff = new int[yDctQuan.GetLength(0), yDctQuan.GetLength(1)]; cBDctQuanDiff = new int[cBDctQuan.GetLength(0), cBDctQuan.GetLength(1)]; cRDctQuanDiff = new int[cRDctQuan.GetLength(0), cRDctQuan.GetLength(1)]; accumulatedChangesY = new int[yDctQuan.GetLength(0), yDctQuan.GetLength(1)]; accumulatedChangesCb = new int[cBDctQuan.GetLength(0), cBDctQuan.GetLength(1)]; accumulatedChangesCr = new int[cRDctQuan.GetLength(0), cRDctQuan.GetLength(1)]; actualValuesY = new int[yDctQuan.GetLength(0), yDctQuan.GetLength(1)]; actualValuesCb = new int[cBDctQuan.GetLength(0), cBDctQuan.GetLength(1)]; actualValuesCr = new int[cRDctQuan.GetLength(0), cRDctQuan.GetLength(1)]; for (int x = 0; x < accumulatedChangesY.GetLength(0); x++) { for (int y = 0; y < accumulatedChangesY.GetLength(1); y++) { accumulatedChangesY[x, y] = int.MaxValue; actualValuesY[x, y] = int.MaxValue; } } for (int x = 0; x < accumulatedChangesCb.GetLength(0); x++) { for (int y = 0; y < accumulatedChangesCb.GetLength(1); y++) { accumulatedChangesCb[x, y] = int.MaxValue; accumulatedChangesCr[x, y] = int.MaxValue; actualValuesCb[x, y] = int.MaxValue; actualValuesCr[x, y] = int.MaxValue; } } //actualValuesListY.Clear(); //actualValuesListCb.Clear(); //actualValuesListCr.Clear(); } yDctQuanFromLastFrame = yDctQuan; cBDctQuanFromLastFrame = cBDctQuan; cRDctQuanFromLastFrame = cRDctQuan; // it's not a keyframe if (i % keyFrameEvery != 0) { yDctQuan = yDctQuanDiff; cBDctQuan = cBDctQuanDiff; cRDctQuan = cRDctQuanDiff; } if (subsamplingMode == "4:4:4") { yDctQuan = dctImage.TrimValueMatrix(yDctQuan, width, height); cBDctQuan = dctImage.TrimValueMatrix(cBDctQuan, width, height); cRDctQuan = dctImage.TrimValueMatrix(cRDctQuan, width, height); } else if (subsamplingMode == "4:2:2") { yDctQuan = dctImage.TrimValueMatrix(yDctQuan, width, height); cBDctQuan = dctImage.TrimValueMatrix(cBDctQuan, width / 2, height); cRDctQuan = dctImage.TrimValueMatrix(cRDctQuan, width / 2, height); } else if (subsamplingMode == "4:2:0") { yDctQuan = dctImage.TrimValueMatrix(yDctQuan, width, height); cBDctQuan = dctImage.TrimValueMatrix(cBDctQuan, width / 2, height / 2); cRDctQuan = dctImage.TrimValueMatrix(cRDctQuan, width / 2, height / 2); } // Tester.PrintToFile("yDctQuanBefore", yDctQuan); yDiffEncoded = DifferentialEncoding.Encode(yDctQuan, 8); cBDiffEncoded = DifferentialEncoding.Encode(cBDctQuan, 8); cRDiffEncoded = DifferentialEncoding.Encode(cRDctQuan, 8); //Tester.PrintToFile("yDiffEncodedBefore", yDiffEncoded); yRunLenEncoded = RunLengthEncode.Encode(yDiffEncoded, 8); cBRunLenEncoded = RunLengthEncode.Encode(cBDiffEncoded, 8); cRRunLenEncoded = RunLengthEncode.Encode(cRDiffEncoded, 8); //Tester.PrintToFile("yRunLenEncodedBefore", yRunLenEncoded); // huffman encoding bool lastFrame = false; if (i == tempImages.Length - 1) { lastFrame = true; } MultiHuffmanEncoding(i, yRunLenEncoded, cBRunLenEncoded, cRRunLenEncoded, lastFrame, YHuffmanValues, CbHuffmanValues, CrHuffmanValues); // Tester.PrintToFile("huffmanBefore", YBitArray); // garbage collection //tempImages[i] = null; MethodInvoker mi = new MethodInvoker(() => { int newValue = progressBar.Value + numOfThreads; if (newValue <= inputImages.Length) { progressBar.Value = newValue; } else { progressBar.Value = inputImages.Length; } }); if (!progressBar.InvokeRequired) { mi.Invoke(); } } }