Ejemplo n.º 1
0
 private void mvZero(Context context, PictureHeader ph, MPEGPred pred, int mbX, int mbY, int[][] mbPix)
 {
     if (ph.picture_coding_type == PictureHeader.PredictiveCoded)
     {
         pred.predict16x16NoMV(refFrames[0], mbX << 4, mbY << 4, ph.pictureCodingExtension == null ? PictureCodingExtension.Frame
                 : ph.pictureCodingExtension.picture_structure, 0, mbPix);
     }
     else
     {
         int[][] pp = mbPix;
         if (context.lastPredB.macroblock_motion_backward == 1)
         {
             pred.predict16x16NoMV(refFrames[0], mbX << 4, mbY << 4, ph.pictureCodingExtension == null ? PictureCodingExtension.Frame
                     : ph.pictureCodingExtension.picture_structure, 1, pp);
             pp = new int[][] { new int[mbPix[0].Length], new int[mbPix[1].Length], new int[mbPix[2].Length] };
         }
         if (context.lastPredB.macroblock_motion_forward == 1)
         {
             pred.predict16x16NoMV(refFrames[1], mbX << 4, mbY << 4, ph.pictureCodingExtension == null ? PictureCodingExtension.Frame
                     : ph.pictureCodingExtension.picture_structure, 0, pp);
             if (mbPix != pp)
             {
                 avgPred(mbPix, pp);
             }
         }
     }
 }
Ejemplo n.º 2
0
        public static PictureHeader read(MemoryStream bb)
        {
            BitReader     inb = new BitReader(bb);
            PictureHeader ph  = new PictureHeader();

            ph.temporal_reference  = inb.readNBit(10);
            ph.picture_coding_type = inb.readNBit(3);
            ph.vbv_delay           = inb.readNBit(16);
            if (ph.picture_coding_type == 2 || ph.picture_coding_type == 3)
            {
                ph.full_pel_forward_vector = inb.read1Bit();
                ph.forward_f_code          = inb.readNBit(3);
            }
            if (ph.picture_coding_type == 3)
            {
                ph.full_pel_backward_vector = inb.read1Bit();
                ph.backward_f_code          = inb.readNBit(3);
            }
            while (inb.read1Bit() == 1)
            {
                inb.readNBit(8);
            }

            return(ph);
        }
Ejemplo n.º 3
0
        public Picture decodeFrame(MemoryStream ByteBuffer, int[][] buf)
        {
            PictureHeader ph = readHeader(ByteBuffer);

            if (refFrames[0] == null && ph.picture_coding_type > 1 || refFrames[1] == null && ph.picture_coding_type > 2)
            {
                throw new Exception("Not enough references to decode " + (ph.picture_coding_type == 1 ? "P" : "B")
                                    + " frame");
            }
            Context context = initContext(sh, ph);
            Picture pic     = new Picture(context.codedWidth, context.codedHeight, buf, context.color, new Rect(0, 0,
                                                                                                                context.picWidth, context.picHeight));

            if (ph.pictureCodingExtension != null && ph.pictureCodingExtension.picture_structure != PictureCodingExtension.Frame)
            {
                decodePicture(context, ph, ByteBuffer, buf, ph.pictureCodingExtension.picture_structure - 1, 1);
                ph      = readHeader(ByteBuffer);
                context = initContext(sh, ph);
                decodePicture(context, ph, ByteBuffer, buf, ph.pictureCodingExtension.picture_structure - 1, 1);
            }
            else
            {
                decodePicture(context, ph, ByteBuffer, buf, 0, 0);
            }

            if (ph.picture_coding_type == PictureHeader.IntraCoded ||
                ph.picture_coding_type == PictureHeader.PredictiveCoded)
            {
                Picture unused = refFrames[1];
                refFrames[1] = refFrames[0];
                refFrames[0] = copyAndCreateIfNeeded(pic, unused);
            }

            return(pic);
        }
Ejemplo n.º 4
0
        private void resetDCPredictors(Context context, PictureHeader ph)
        {
            int rval = 1 << 7;

            if (ph.pictureCodingExtension != null)
            {
                rval = 1 << (7 + ph.pictureCodingExtension.intra_dc_precision);
            }
            context.intra_dc_predictor[0] = context.intra_dc_predictor[1] = context.intra_dc_predictor[2] = rval;
        }
Ejemplo n.º 5
0
        public Picture decodePicture(Context context, PictureHeader ph, MemoryStream buffer, int[][] buf, int vertOff,
                                     int vertStep)
        {
            int planeSize = context.codedWidth * context.codedHeight;

            if (buf.Length < 3 || buf[0].Length < planeSize || buf[1].Length < planeSize || buf[2].Length < planeSize)
            {
                throw new Exception("ByteBuffer too small to hold output picture [" + context.codedWidth + "x"
                                    + context.codedHeight + "]");
            }

            try
            {
                MemoryStream segment;
                while ((segment = MPEGUtil.nextSegment(buffer)) != null)
                {
                    if (segment.get(3) >= MPEGConst.SLICE_START_CODE_FIRST && segment.get(3) <= MPEGConst.SLICE_START_CODE_LAST)
                    {
                        segment.position(4);
                        try
                        {
                            decodeSlice(ph, segment.get(3) & 0xff, context, buf, new BitReader(segment), vertOff, vertStep);
                        }
                        catch (Exception e)
                        {
                            //e.printStackTrace();
                        }
                    }
                    else if (segment.get(3) >= 0xB3 && segment.get(3) != 0xB6 && segment.get(3) != 0xB7)
                    {
                        throw new Exception("Unexpected start code " + segment.get(3));
                    }
                    else if (segment.get(3) == 0x0)
                    {
                        //buffer.reset();
                        break;
                    }
                }

                Picture pic = new Picture(context.codedWidth, context.codedHeight, buf, context.color);
                if ((ph.picture_coding_type == PictureHeader.IntraCoded || ph.picture_coding_type == PictureHeader.PredictiveCoded) &&
                    ph.pictureCodingExtension != null && ph.pictureCodingExtension.picture_structure != PictureCodingExtension.Frame)
                {
                    refFields[ph.pictureCodingExtension.picture_structure - 1] = copyAndCreateIfNeeded(pic,
                                                                                                       refFields[ph.pictureCodingExtension.picture_structure - 1]);
                }

                return(pic);
            }
            catch (IOException e)
            {
                throw e;
            }
        }
Ejemplo n.º 6
0
        private PictureHeader readHeader(MemoryStream buffer)
        {
            PictureHeader ph = null;
            MemoryStream  segment;
            MemoryStream  fork = buffer.duplicate();

            while ((segment = MPEGUtil.nextSegment(fork)) != null)
            {
                int code = segment.getInt() & 0xff;
                if (code == MPEGConst.SEQUENCE_HEADER_CODE)
                {
                    SequenceHeader newSh = SequenceHeader.read(segment);
                    if (sh != null)
                    {
                        newSh.copyExtensions(sh);
                    }
                    sh = newSh;
                }
                else if (code == MPEGConst.GROUP_START_CODE)
                {
                    gh = GOPHeader.read(segment);
                }
                else if (code == MPEGConst.PICTURE_START_CODE)
                {
                    ph = PictureHeader.read(segment);
                }
                else if (code == MPEGConst.EXTENSION_START_CODE)
                {
                    int extType = segment.get(4) >> 4;
                    if (extType == SequenceHeader.Sequence_Extension || extType == SequenceHeader.Sequence_Scalable_Extension ||
                        extType == SequenceHeader.Sequence_Display_Extension)
                    {
                        SequenceHeader.readExtension(segment, sh);
                    }
                    else
                    {
                        PictureHeader.readExtension(segment, ph, sh);
                    }
                }
                else if (code == MPEGConst.USER_DATA_START_CODE)
                {
                    // do nothing
                }
                else
                {
                    break;
                }
                buffer.position(fork.position());
            }
            return(ph);
        }
Ejemplo n.º 7
0
        protected Context initContext(SequenceHeader sh, PictureHeader ph)
        {
            Context context = new Context();

            context.codedWidth  = (sh.horizontal_size + 15) & ~0xf;
            context.codedHeight = getCodedHeight(sh, ph);
            context.mbWidth     = (sh.horizontal_size + 15) >> 4;
            context.mbHeight    = (sh.vertical_size + 15) >> 4;
            context.picWidth    = sh.horizontal_size;
            context.picHeight   = sh.vertical_size;

            int chromaFormat = SequenceExtension.Chroma420;

            if (sh.sequenceExtension != null)
            {
                chromaFormat = sh.sequenceExtension.chroma_format;
            }

            context.color = getColor(chromaFormat);

            context.scan = MPEGConst.scan[ph.pictureCodingExtension == null ? 0 : ph.pictureCodingExtension.alternate_scan];

            int[] inter = sh.non_intra_quantiser_matrix == null?zigzag(MPEGConst.defaultQMatInter, context.scan)
                              : sh.non_intra_quantiser_matrix;

            int[] intra = sh.intra_quantiser_matrix == null?zigzag(MPEGConst.defaultQMatIntra, context.scan)
                              : sh.intra_quantiser_matrix;

            context.qMats = new int[][] { inter, inter, intra, intra };

            if (ph.quantMatrixExtension != null)
            {
                if (ph.quantMatrixExtension.non_intra_quantiser_matrix != null)
                {
                    context.qMats[0] = ph.quantMatrixExtension.non_intra_quantiser_matrix;
                }
                if (ph.quantMatrixExtension.chroma_non_intra_quantiser_matrix != null)
                {
                    context.qMats[1] = ph.quantMatrixExtension.chroma_non_intra_quantiser_matrix;
                }
                if (ph.quantMatrixExtension.intra_quantiser_matrix != null)
                {
                    context.qMats[2] = ph.quantMatrixExtension.intra_quantiser_matrix;
                }
                if (ph.quantMatrixExtension.chroma_intra_quantiser_matrix != null)
                {
                    context.qMats[3] = ph.quantMatrixExtension.chroma_intra_quantiser_matrix;
                }
            }
            return(context);
        }
Ejemplo n.º 8
0
        public void decodeSlice(PictureHeader ph, int verticalPos, Context context, int[][] buf, BitReader ing, int vertOff,
                                int vertStep)
        {
            int stride = context.codedWidth;

            resetDCPredictors(context, ph);

            int mbRow = verticalPos - 1;

            if (sh.vertical_size > 2800)
            {
                mbRow += (ing.readNBit(3) << 7);
            }
            if (sh.sequenceScalableExtension != null &&
                sh.sequenceScalableExtension.scalable_mode == SequenceScalableExtension.DATA_PARTITIONING)
            {
                int priorityBreakpoint = ing.readNBit(7);
            }
            int qScaleCode = ing.readNBit(5);

            if (ing.read1Bit() == 1)
            {
                int intraSlice = ing.read1Bit();
                ing.skip(7);
                while (ing.read1Bit() == 1)
                {
                    ing.readNBit(8);
                }
            }

            MPEGPred pred = new MPEGPred(ph.pictureCodingExtension != null ? ph.pictureCodingExtension.f_code
                    : new int[][] { new int[] { ph.forward_f_code, ph.forward_f_code },
                                    new int[] { ph.backward_f_code, ph.backward_f_code } },
                                         sh.sequenceExtension != null ? sh.sequenceExtension.chroma_format : SequenceExtension.Chroma420,
                                         ph.pictureCodingExtension != null && ph.pictureCodingExtension.top_field_first == 0 ? false : true);

            int[] ctx = new int[] { qScaleCode };

            for (int prevAddr = mbRow * context.mbWidth - 1; ing.checkNBit(23) != 0;)
            {
                // TODO: decode skipped!!!
                prevAddr = decodeMacroblock(ph, context, prevAddr, ctx, buf, stride, ing, vertOff, vertStep, pred);
                context.mbNo++;
            }
        }
Ejemplo n.º 9
0
        public static void readExtension(MemoryStream bb, PictureHeader ph, SequenceHeader sh)
        {
            ph.m_hasExtensions = true;
            BitReader inb     = new BitReader(bb);
            int       extType = inb.readNBit(4);

            switch (extType)
            {
            case Quant_Matrix_Extension:
                ph.quantMatrixExtension = QuantMatrixExtension.read(inb);
                break;

            case Copyright_Extension:
                ph.copyrightExtension = CopyrightExtension.read(inb);
                break;

            case Picture_Display_Extension:
                ph.pictureDisplayExtension = PictureDisplayExtension.read(inb, sh.sequenceExtension,
                                                                          ph.pictureCodingExtension);
                break;

            case Picture_Coding_Extension:
                ph.pictureCodingExtension = PictureCodingExtension.read(inb);
                break;

            case Picture_Spatial_Scalable_Extension:
                ph.pictureSpatialScalableExtension = PictureSpatialScalableExtension.read(inb);
                break;

            case Picture_Temporal_Scalable_Extension:
                ph.pictureTemporalScalableExtension = PictureTemporalScalableExtension.read(inb);
                break;

            default:
                throw new Exception("Unsupported extension: " + extType);
            }
        }
Ejemplo n.º 10
0
        public int decodeMacroblock(PictureHeader ph, Context context, int prevAddr, int[] qScaleCode, int[][] buf,
                                    int stride, BitReader bits, int vertOff, int vertStep, MPEGPred pred)
        {
            int mbAddr = prevAddr;

            while (bits.checkNBit(11) == 0x8)
            {
                bits.skip(11);
                mbAddr += 33;
            }
            mbAddr += MPEGConst.vlcAddressIncrement.readVLC(bits) + 1;

            int chromaFormat = SequenceExtension.Chroma420;

            if (sh.sequenceExtension != null)
            {
                chromaFormat = sh.sequenceExtension.chroma_format;
            }

            for (int i = prevAddr + 1; i < mbAddr; i++)
            {
                int[][] predFwda = new int[][] { new int[256], new int[1 << (chromaFormat + 5)],
                                                 new int[1 << (chromaFormat + 5)] };
                int mbXa = i % context.mbWidth;
                int mbYa = i / context.mbWidth;
                if (ph.picture_coding_type == PictureHeader.PredictiveCoded)
                {
                    pred.reset();
                }
                mvZero(context, ph, pred, mbXa, mbYa, predFwda);
                put(predFwda, buf, stride, chromaFormat, mbXa, mbYa, context.codedWidth, context.codedHeight >> vertStep,
                    vertOff, vertStep);
            }

            VLC vlcMBTypea = MPEGConst.vlcMBType(ph.picture_coding_type, sh.sequenceScalableExtension);

            nVideo.Codecs.MPEG12.MPEGConst.MBType[] mbTypeVal = MPEGConst.mbTypeVal(ph.picture_coding_type, sh.sequenceScalableExtension);

            nVideo.Codecs.MPEG12.MPEGConst.MBType mbType = mbTypeVal[vlcMBTypea.readVLC(bits)];

            if (mbType.macroblock_intra != 1 || (mbAddr - prevAddr) > 1)
            {
                resetDCPredictors(context, ph);
            }

            int spatial_temporal_weight_code = 0;

            if (mbType.spatial_temporal_weight_code_flag == 1 && ph.pictureSpatialScalableExtension != null &&
                ph.pictureSpatialScalableExtension.spatial_temporal_weight_code_table_index != 0)
            {
                spatial_temporal_weight_code = bits.readNBit(2);
            }

            int motion_type = -1;

            if (mbType.macroblock_motion_forward != 0 || mbType.macroblock_motion_backward != 0)
            {
                if (ph.pictureCodingExtension == null || ph.pictureCodingExtension.picture_structure == PictureCodingExtension.Frame &&
                    ph.pictureCodingExtension.frame_pred_frame_dct == 1)
                {
                    motion_type = 2;
                }
                else
                {
                    motion_type = bits.readNBit(2);
                }
            }

            int dctType = 0;

            if (ph.pictureCodingExtension != null && ph.pictureCodingExtension.picture_structure == PictureCodingExtension.Frame &&
                ph.pictureCodingExtension.frame_pred_frame_dct == 0 &&
                (mbType.macroblock_intra != 0 || mbType.macroblock_pattern != 0))
            {
                dctType = bits.read1Bit();
            }
            // buf[3][mbAddr] = dctType;

            if (mbType.macroblock_quant != 0)
            {
                qScaleCode[0] = bits.readNBit(5);
            }
            bool concealmentMv = ph.pictureCodingExtension != null &&
                                 ph.pictureCodingExtension.concealment_motion_vectors != 0;

            int[][] predFwd = null;
            int     mbX     = mbAddr % context.mbWidth;
            int     mbY     = mbAddr / context.mbWidth;

            if (mbType.macroblock_intra == 1)
            {
                if (concealmentMv)
                {
                    // TODO read consealment vectors
                }
                else
                {
                    pred.reset();
                }
            }
            else if (mbType.macroblock_motion_forward != 0)
            {
                int refIdx = ph.picture_coding_type == PictureHeader.PredictiveCoded ? 0 : 1;
                predFwd = new int[][] { new int[256], new int[1 << (chromaFormat + 5)], new int[1 << (chromaFormat + 5)] };
                if (ph.pictureCodingExtension == null || ph.pictureCodingExtension.picture_structure == PictureCodingExtension.Frame)
                {
                    pred.predictInFrame(refFrames[refIdx], mbX << 4, mbY << 4, predFwd, bits, motion_type, 0,
                                        spatial_temporal_weight_code);
                }
                else
                {
                    if (ph.picture_coding_type == PictureHeader.PredictiveCoded)
                    {
                        pred.predictInField(refFields, mbX << 4, mbY << 4, predFwd, bits, motion_type, 0,
                                            ph.pictureCodingExtension.picture_structure - 1);
                    }
                    else
                    {
                        pred.predictInField(new Picture[] { refFrames[refIdx], refFrames[refIdx] }, mbX << 4, mbY << 4,
                                            predFwd, bits, motion_type, 0, ph.pictureCodingExtension.picture_structure - 1);
                    }
                }
            }
            else if (ph.picture_coding_type == PictureHeader.PredictiveCoded)
            {
                predFwd = new int[][] { new int[256], new int[1 << (chromaFormat + 5)], new int[1 << (chromaFormat + 5)] };
                pred.reset();
                mvZero(context, ph, pred, mbX, mbY, predFwd);
            }

            int[][] predBack = null;
            if (mbType.macroblock_motion_backward != 0)
            {
                predBack = new int[][] { new int[256], new int[1 << (chromaFormat + 5)], new int[1 << (chromaFormat + 5)] };
                if (ph.pictureCodingExtension == null || ph.pictureCodingExtension.picture_structure == PictureCodingExtension.Frame)
                {
                    pred.predictInFrame(refFrames[0], mbX << 4, mbY << 4, predBack, bits, motion_type, 1,
                                        spatial_temporal_weight_code);
                }
                else
                {
                    pred.predictInField(new Picture[] { refFrames[0], refFrames[0] }, mbX << 4, mbY << 4, predBack, bits,
                                        motion_type, 1, ph.pictureCodingExtension.picture_structure - 1);
                }
            }
            context.lastPredB = mbType;
            int[][] pp = mbType.macroblock_intra == 1 ? new int[][] { new int[256], new int[1 << (chromaFormat + 5)],
                                                                      new int[1 << (chromaFormat + 5)] } : buildPred(predFwd, predBack);

            //if (mbType.macroblock_intra != 0 && concealmentMv)
            //Assert.assertEquals(1, bits.read1Bit()); // Marker

            int cbp = mbType.macroblock_intra == 1 ? 0xfff : 0;

            if (mbType.macroblock_pattern != 0)
            {
                cbp = readCbPattern(bits);
            }

            VLC vlcCoeff = MPEGConst.vlcCoeff0;

            if (ph.pictureCodingExtension != null && mbType.macroblock_intra == 1 &&
                ph.pictureCodingExtension.intra_vlc_format == 1)
            {
                vlcCoeff = MPEGConst.vlcCoeff1;
            }

            int[] qScaleTab = ph.pictureCodingExtension != null && ph.pictureCodingExtension.q_scale_type == 1 ? MPEGConst.qScaleTab2
                    : MPEGConst.qScaleTab1;
            int qScale = qScaleTab[qScaleCode[0]];

            int intra_dc_mult = 8;

            if (ph.pictureCodingExtension != null)
            {
                intra_dc_mult = 8 >> ph.pictureCodingExtension.intra_dc_precision;
            }

            int blkCount = 6 + (chromaFormat == SequenceExtension.Chroma420 ? 0 : (chromaFormat == SequenceExtension.Chroma422 ? 2 : 6));

            int[] block = new int[64];
            //        System.out.print(mbAddr + ": ");
            for (int i = 0, cbpMask = 1 << (blkCount - 1); i < blkCount; i++, cbpMask >>= 1)
            {
                if ((cbp & cbpMask) == 0)
                {
                    continue;
                }
                int[] qmat = context.qMats[(i >= 4 ? 1 : 0) + (mbType.macroblock_intra << 1)];

                if (mbType.macroblock_intra == 1)
                {
                    blockIntra(bits, vlcCoeff, block, context.intra_dc_predictor, i, context.scan,
                               sh.hasExtensions() || ph.hasExtensions() ? 12 : 8, intra_dc_mult, qScale, qmat);
                }
                else
                {
                    blockInter(bits, vlcCoeff, block, context.scan,
                               sh.hasExtensions() || ph.hasExtensions() ? 12 : 8, qScale, qmat);
                }

                mapBlock(block, pp[MPEGConst.BLOCK_TO_CC[i]], i, dctType, chromaFormat);
            }

            put(pp, buf, stride, chromaFormat, mbX, mbY, context.codedWidth, context.codedHeight >> vertStep, vertOff,
                vertStep);

            return(mbAddr);
        }
Ejemplo n.º 11
0
        public static int getCodedHeight(SequenceHeader sh, PictureHeader ph)
        {
            int field = ph.pictureCodingExtension != null && ph.pictureCodingExtension.picture_structure != PictureCodingExtension.Frame ? 1 : 0;

            return((((sh.vertical_size >> field) + 15) & ~0xf) << field);
        }