//MobiclipDecoder d;

        public void AddFrame(Bitmap Frame)
        {
            if (mEncoder == null)
            {
                mEncoder = new MobiEncoder(18, Frame.Width, Frame.Height);
                //d = new MobiclipDecoder((uint)Frame.Width, (uint)Frame.Height, MobiclipDecoder.MobiclipVersion.Moflex3DS);
            }
            byte[] data = mEncoder.EncodeFrame(Frame);
            //d.Data = data;
            //d.Offset = 0;
            //Bitmap test = d.DecodeFrame();
            if (data.Length <= (0x1000 - 0x80))//safe margin
            {
                WriteDataBlock();
                WriteEp(0, data, 0, data.Length, true);
                WriteEp(0, null, 0, 0);
            }
            else
            {
                int pos = 0;
                int left = data.Length;
                while (left >= (0x1000 - 0x80))
                {
                    WriteDataBlock();
                    WriteEp(0, data, pos, 0x1000 - 0x80, left == (0x1000 - 0x80));
                    WriteEp(0, null, 0, 0);
                    pos += 0x1000 - 0x80;
                    left -= 0x1000 - 0x80;
                }
                if (left > 0)
                {
                    WriteDataBlock();
                    WriteEp(0, data, pos, left, true);
                    WriteEp(0, null, 0, 0);
                }
            }
        }
示例#2
0
        public bool Predict { get; set; }//Just assume previous frame, no compensation data

        public void SetupDCTs(MobiEncoder Context)
        {
            for (int y = 0; y < 2; y++)
            {
                for (int x = 0; x < 2; x++)
                {
                    if (YUseComplex8x8[x + y * 2] && !YUse4x4[x + y * 2])
                    {
                        int[] Block2 = new int[64];
                        byte[] CompVals = GetCompvals8x8(YPredictionMode, Context.YDec, X + x * 8, Y + y * 8, Context.Stride, 0);
                        for (int i = 0; i < 64; i++)
                        {
                            Block2[i] = YData8x8[x + y * 2][i] - CompVals[i];
                        }
                        int[] dct = MobiEncoder.DCT64(Block2);
                        YDCT8x8[x + y * 2] = new int[64];
                        for (int i = 0; i < 64; i++)
                        {
                            YDCT8x8[x + y * 2][MobiConst.ZigZagTable8x8[i]] = (int)Math.Round(dct[i] / Context.QTable8x8[i]);
                        }
                        int lastnonzero = 0;
                        for (int i = 0; i < 64; i++)
                        {
                            if (YDCT8x8[x + y * 2][i] != 0) lastnonzero = i;
                        }
                        if (lastnonzero == 0 && YDCT8x8[x + y * 2][0] == 0) YUseComplex8x8[x + y * 2] = false;
                        byte[] decresult;
                        if (YUseComplex8x8[x + y * 2])
                        {
                            int[] realdct = new int[64];
                            for (int i = 0; i < 64; i++)
                            {
                                realdct[i] = (int)Math.Round(dct[i] / Context.QTable8x8[i]);
                                realdct[i] = realdct[i] * (int)Context.QTable8x8[i];
                            }
                            decresult = MobiEncoder.IDCT64(realdct, CompVals);
                        }
                        else decresult = CompVals;
                        Set8x8BlockPixels(Context.YDec, X + x * 8, Y + y * 8, Context.Stride, 0, decresult);
                    }
                    else if (YUseComplex8x8[x + y * 2] && YUse4x4[x + y * 2])
                    {
                        for (int y2 = 0; y2 < 2; y2++)
                        {
                            for (int x2 = 0; x2 < 2; x2++)
                            {
                                if (YUseDCT4x4[x + y * 2][x2 + y2 * 2])
                                {
                                    int[] Block2 = new int[16];
                                    byte[] CompVals = GetCompvals4x4(10 + YPredictionMode, Context.YDec, X + x * 8 + x2 * 4, Y + y * 8 + y2 * 4, Context.Stride, 0);
                                    for (int i = 0; i < 16; i++)
                                    {
                                        Block2[i] = YData4x4[x + y * 2][x2 + y2 * 2][i] - CompVals[i];
                                    }
                                    int[] dct = MobiEncoder.DCT16(Block2);
                                    YDCT4x4[x + y * 2][x2 + y2 * 2] = new int[16];
                                    for (int i = 0; i < 16; i++)
                                    {
                                        YDCT4x4[x + y * 2][x2 + y2 * 2][MobiConst.ZigZagTable4x4[i]] = (int)Math.Round(dct[i] / Context.QTable4x4[i]);
                                    }
                                    int lastnonzero = 0;
                                    for (int i = 0; i < 16; i++)
                                    {
                                        if (YDCT4x4[x + y * 2][x2 + y2 * 2][i] != 0) lastnonzero = i;
                                    }
                                    if (lastnonzero == 0 && YDCT4x4[x + y * 2][x2 + y2 * 2][0] == 0) YUseDCT4x4[x + y * 2][x2 + y2 * 2] = false;
                                    byte[] decresult;
                                    if (YUseDCT4x4[x + y * 2][x2 + y2 * 2])
                                    {
                                        int[] realdct = new int[16];
                                        for (int i = 0; i < 16; i++)
                                        {
                                            realdct[i] = (int)Math.Round(dct[i] / Context.QTable4x4[i]);
                                            realdct[i] = realdct[i] * (int)Context.QTable4x4[i];
                                        }
                                        decresult = MobiEncoder.IDCT16(realdct, CompVals);
                                    }
                                    else decresult = CompVals;
                                    Set4x4BlockPixels(Context.YDec, X + x * 8 + x2 * 4, Y + y * 8 + y2 * 4, Context.Stride, 0, decresult);
                                }
                            }
                        }
                    }
                }
            }
            if (UVUseComplex8x8[0] && !UVUse4x4[0])
            {
                int[] Block2 = new int[64];
                byte[] CompVals = GetCompvals8x8(UVPredictionMode, Context.UVDec, X / 2, Y / 2, Context.Stride, 0);
                for (int i = 0; i < 64; i++)
                {
                    Block2[i] = UData[i] - CompVals[i];
                }
                int[] dct = MobiEncoder.DCT64(Block2);
                UVDCT8x8[0] = new int[64];
                for (int i = 0; i < 64; i++)
                {
                    UVDCT8x8[0][MobiConst.ZigZagTable8x8[i]] = (int)Math.Round(dct[i] / Context.QTable8x8[i]);
                }
                int lastnonzero = 0;
                for (int i = 0; i < 64; i++)
                {
                    if (UVDCT8x8[0][i] != 0) lastnonzero = i;
                }
                if (lastnonzero == 0 && UVDCT8x8[0][0] == 0) UVUseComplex8x8[0] = false;
                byte[] decresult;
                if (UVUseComplex8x8[0])
                {
                    int[] realdct = new int[64];
                    for (int i = 0; i < 64; i++)
                    {

                        realdct[i] = (int)Math.Round(dct[i] / Context.QTable8x8[i]);
                        realdct[i] = realdct[i] * (int)Context.QTable8x8[i];
                    }
                    decresult = MobiEncoder.IDCT64(realdct, CompVals);
                }
                else decresult = CompVals;
                Set8x8BlockPixels(Context.UVDec, X / 2, Y / 2, Context.Stride, 0, decresult);
            }
            if (UVUseComplex8x8[1] && !UVUse4x4[1])
            {
                int[] Block2 = new int[64];
                byte[] CompVals = GetCompvals8x8(UVPredictionMode, Context.UVDec, X / 2, Y / 2, Context.Stride, Context.Stride / 2);
                for (int i = 0; i < 64; i++)
                {
                    Block2[i] = VData[i] - CompVals[i];
                }
                int[] dct = MobiEncoder.DCT64(Block2);
                UVDCT8x8[1] = new int[64];
                for (int i = 0; i < 64; i++)
                {
                    UVDCT8x8[1][MobiConst.ZigZagTable8x8[i]] = (int)Math.Round(dct[i] / Context.QTable8x8[i]);
                }
                int lastnonzero = 0;
                for (int i = 0; i < 64; i++)
                {
                    if (UVDCT8x8[1][i] != 0) lastnonzero = i;
                }
                if (lastnonzero == 0 && UVDCT8x8[1][0] == 0) UVUseComplex8x8[1] = false;
                byte[] decresult;
                if (UVUseComplex8x8[1])
                {
                    int[] realdct = new int[64];
                    for (int i = 0; i < 64; i++)
                    {

                        realdct[i] = (int)Math.Round(dct[i] / Context.QTable8x8[i]);
                        realdct[i] = realdct[i] * (int)Context.QTable8x8[i];
                    }
                    decresult = MobiEncoder.IDCT64(realdct, CompVals);
                }
                else decresult = CompVals;
                Set8x8BlockPixels(Context.UVDec, X / 2, Y / 2, Context.Stride, Context.Stride / 2, decresult);
            }
        }
示例#3
0
 //This analyzer should determine the best block configuration for a macro block (mb)
 public static void ConfigureBlockY(MobiEncoder Encoder, MacroBlock Block)
 {
     List<BlockScore> scores = new List<BlockScore>();
     //8x8
     if (Block.Y >= 8)
     {
         int score = 0;
         score += GetScore8x8(Block.YData8x8[0], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[0], Encoder.YDec, Block.X, Block.Y, Encoder.Stride, 0, Encoder.QTable8x8, 0));
         score += GetScore8x8(Block.YData8x8[1], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[1], Encoder.YDec, Block.X + 8, Block.Y, Encoder.Stride, 0, Encoder.QTable8x8, 0));
         score += GetScore8x8(Block.YData8x8[2], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[2], Encoder.YDec, Block.X, Block.Y + 8, Encoder.Stride, 0, Encoder.QTable8x8, 0));
         score += GetScore8x8(Block.YData8x8[3], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[3], Encoder.YDec, Block.X + 8, Block.Y + 8, Encoder.Stride, 0, Encoder.QTable8x8, 0));
         scores.Add(new BlockScore() { BlockConfigId = 0, Score = score });
         score = 0;
         int b = 0;
         for (int y = 0; y < 16; y += 8)
         {
             for (int x = 0; x < 16; x += 8)
             {
                 int b2 = 0;
                 for (int y2 = 0; y2 < 8; y2 += 4)
                 {
                     for (int x2 = 0; x2 < 8; x2 += 4)
                     {
                         score += GetScore4x4(Block.YData4x4[b][b2],
                             MacroBlock.EncodeDecode4x4Block(Block.YData4x4[b][b2], Encoder.YDec, Block.X + x + x2, Block.Y + y + y2, Encoder.Stride, 0, Encoder.QTable4x4, 10 + 0));
                         b2++;
                     }
                 }
                 b++;
             }
         }
         scores.Add(new BlockScore() { BlockConfigId = 0 | (1 << 5), Score = score });
     }
     if (Block.X >= 8)
     {
         int score = 0;
         score += GetScore8x8(Block.YData8x8[0], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[0], Encoder.YDec, Block.X, Block.Y, Encoder.Stride, 0, Encoder.QTable8x8, 1));
         score += GetScore8x8(Block.YData8x8[1], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[1], Encoder.YDec, Block.X + 8, Block.Y, Encoder.Stride, 0, Encoder.QTable8x8, 1));
         score += GetScore8x8(Block.YData8x8[2], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[2], Encoder.YDec, Block.X, Block.Y + 8, Encoder.Stride, 0, Encoder.QTable8x8, 1));
         score += GetScore8x8(Block.YData8x8[3], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[3], Encoder.YDec, Block.X + 8, Block.Y + 8, Encoder.Stride, 0, Encoder.QTable8x8, 1));
         scores.Add(new BlockScore() { BlockConfigId = 1, Score = score });
         score = 0;
         int b = 0;
         for (int y = 0; y < 16; y += 8)
         {
             for (int x = 0; x < 16; x += 8)
             {
                 int b2 = 0;
                 for (int y2 = 0; y2 < 8; y2 += 4)
                 {
                     for (int x2 = 0; x2 < 8; x2 += 4)
                     {
                         score += GetScore4x4(Block.YData4x4[b][b2],
                             MacroBlock.EncodeDecode4x4Block(Block.YData4x4[b][b2], Encoder.YDec, Block.X + x + x2, Block.Y + y + y2, Encoder.Stride, 0, Encoder.QTable4x4, 10 + 1));
                         b2++;
                     }
                 }
                 b++;
             }
         }
         scores.Add(new BlockScore() { BlockConfigId = 1 | (1 << 5), Score = score });
     }
     //TODO: block type2
     //Block type 3
     {
         int score = 0;
         score += GetScore8x8(Block.YData8x8[0], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[0], Encoder.YDec, Block.X, Block.Y, Encoder.Stride, 0, Encoder.QTable8x8, 3));
         score += GetScore8x8(Block.YData8x8[1], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[1], Encoder.YDec, Block.X + 8, Block.Y, Encoder.Stride, 0, Encoder.QTable8x8, 3));
         score += GetScore8x8(Block.YData8x8[2], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[2], Encoder.YDec, Block.X, Block.Y + 8, Encoder.Stride, 0, Encoder.QTable8x8, 3));
         score += GetScore8x8(Block.YData8x8[3], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[3], Encoder.YDec, Block.X + 8, Block.Y + 8, Encoder.Stride, 0, Encoder.QTable8x8, 3));
         scores.Add(new BlockScore() { BlockConfigId = 3, Score = score });
         score = 0;
         int b = 0;
         for (int y = 0; y < 16; y += 8)
         {
             for (int x = 0; x < 16; x += 8)
             {
                 int b2 = 0;
                 for (int y2 = 0; y2 < 8; y2 += 4)
                 {
                     for (int x2 = 0; x2 < 8; x2 += 4)
                     {
                         score += GetScore4x4(Block.YData4x4[b][b2],
                             MacroBlock.EncodeDecode4x4Block(Block.YData4x4[b][b2], Encoder.YDec, Block.X + x + x2, Block.Y + y + y2, Encoder.Stride, 0, Encoder.QTable4x4, 10 + 3));
                         b2++;
                     }
                 }
                 b++;
             }
         }
         scores.Add(new BlockScore() { BlockConfigId = 3 | (1 << 5), Score = score });
     }
     if (Block.X >= 8 && Block.Y >= 8)
     {
         for (int i = 4; i <= 7; i++)
         {
             int score = 0;
             score += GetScore8x8(Block.YData8x8[0], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[0], Encoder.YDec, Block.X, Block.Y, Encoder.Stride, 0, Encoder.QTable8x8, i));
             score += GetScore8x8(Block.YData8x8[1], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[1], Encoder.YDec, Block.X + 8, Block.Y, Encoder.Stride, 0, Encoder.QTable8x8, i));
             score += GetScore8x8(Block.YData8x8[2], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[2], Encoder.YDec, Block.X, Block.Y + 8, Encoder.Stride, 0, Encoder.QTable8x8, i));
             score += GetScore8x8(Block.YData8x8[3], MacroBlock.EncodeDecode8x8Block(Block.YData8x8[3], Encoder.YDec, Block.X + 8, Block.Y + 8, Encoder.Stride, 0, Encoder.QTable8x8, i));
             scores.Add(new BlockScore() { BlockConfigId = i, Score = score });
             score = 0;
             int b = 0;
             for (int y = 0; y < 16; y += 8)
             {
                 for (int x = 0; x < 16; x += 8)
                 {
                     int b2 = 0;
                     for (int y2 = 0; y2 < 8; y2 += 4)
                     {
                         for (int x2 = 0; x2 < 8; x2 += 4)
                         {
                             score += GetScore4x4(Block.YData4x4[b][b2],
                                 MacroBlock.EncodeDecode4x4Block(Block.YData4x4[b][b2], Encoder.YDec, Block.X + x + x2, Block.Y + y + y2, Encoder.Stride, 0, Encoder.QTable4x4, 10 + i));
                             b2++;
                         }
                     }
                     b++;
                 }
             }
             scores.Add(new BlockScore() { BlockConfigId = i | (1 << 5), Score = score });
         }
     }
     BlockScore best = null;
     foreach (BlockScore s in scores)
     {
         if (best == null || s.Score < best.Score || (s.Score == best.Score && (s.BlockConfigId & 0x20) == 0 && (best.BlockConfigId & 0x20) != 0)) best = s;
     }
     Block.YPredictionMode = best.BlockConfigId & 0x1F;
     Block.YUseComplex8x8[0] = true;
     Block.YUseComplex8x8[1] = true;
     Block.YUseComplex8x8[2] = true;
     Block.YUseComplex8x8[3] = true;
     if (((best.BlockConfigId >> 5) & 1) == 1)
     {
         Block.YUse4x4[0] = true;
         Block.YUse4x4[1] = true;
         Block.YUse4x4[2] = true;
         Block.YUse4x4[3] = true;
         for (int i = 0; i < 4; i++)
         {
             for (int j = 0; j < 4; j++)
             {
                 Block.YUseDCT4x4[i][j] = true;
             }
         }
     }
 }
示例#4
0
 public static int AnalyzeBlockUV(MobiEncoder Encoder, MacroBlock Block)
 {
     List<BlockScore> scores = new List<BlockScore>();
     //8x8
     if (Block.Y >= 8)
     {
         int score = 0;
         score += GetScore8x8(Block.UData, MacroBlock.EncodeDecode8x8Block(Block.UData, Encoder.UVDec, Block.X / 2, Block.Y / 2, Encoder.Stride, 0, Encoder.QTable8x8, 0));
         score += GetScore8x8(Block.VData, MacroBlock.EncodeDecode8x8Block(Block.VData, Encoder.UVDec, Block.X / 2, Block.Y / 2, Encoder.Stride, Encoder.Stride / 2, Encoder.QTable8x8, 0));
         scores.Add(new BlockScore() { BlockConfigId = 0, Score = score });
     }
     if (Block.X >= 8)
     {
         int score = 0;
         score += GetScore8x8(Block.UData, MacroBlock.EncodeDecode8x8Block(Block.UData, Encoder.UVDec, Block.X / 2, Block.Y / 2, Encoder.Stride, 0, Encoder.QTable8x8, 1));
         score += GetScore8x8(Block.VData, MacroBlock.EncodeDecode8x8Block(Block.VData, Encoder.UVDec, Block.X / 2, Block.Y / 2, Encoder.Stride, Encoder.Stride / 2, Encoder.QTable8x8, 1));
         scores.Add(new BlockScore() { BlockConfigId = 1, Score = score });
     }
     //TODO: block type2
     //Block type 3
     {
         int score = 0;
         score += GetScore8x8(Block.UData, MacroBlock.EncodeDecode8x8Block(Block.UData, Encoder.UVDec, Block.X / 2, Block.Y / 2, Encoder.Stride, 0, Encoder.QTable8x8, 3));
         score += GetScore8x8(Block.VData, MacroBlock.EncodeDecode8x8Block(Block.VData, Encoder.UVDec, Block.X / 2, Block.Y / 2, Encoder.Stride, Encoder.Stride / 2, Encoder.QTable8x8, 3));
         scores.Add(new BlockScore() { BlockConfigId = 3, Score = score });
     }
     if (Block.X >= 8 && Block.Y >= 8)
     {
         for (int i = 4; i <= 7; i++)
         {
             int score = 0;
             score += GetScore8x8(Block.UData, MacroBlock.EncodeDecode8x8Block(Block.UData, Encoder.UVDec, Block.X / 2, Block.Y / 2, Encoder.Stride, 0, Encoder.QTable8x8, i));
             score += GetScore8x8(Block.VData, MacroBlock.EncodeDecode8x8Block(Block.VData, Encoder.UVDec, Block.X / 2, Block.Y / 2, Encoder.Stride, Encoder.Stride / 2, Encoder.QTable8x8, i));
             scores.Add(new BlockScore() { BlockConfigId = i, Score = score });
         }
     }
     BlockScore best = null;
     foreach (BlockScore s in scores)
     {
         if (best == null || s.Score < best.Score) best = s;
     }
     return best.BlockConfigId;
 }