⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decoder.java

📁 J2ME MPEG4 解码代码。 以及使用方法。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
        mPastIntraAddress = -2; // See ISO-11172-2 page 36

        // Reset at start of each slice
        mForward.resetPrevious();
        mBackward.resetPrevious();

        /*
         * Macroblocks have an address which is the number of the macroblock 
         * in raster scan order. The top left macroblock in a picture has 
         * address 0, the next one to the right has address 1 and so on. 
         * If there are M macroblocks in a picture, then the bottom right 
         * macroblock has an address M-1.
         */
        mMacroblockAddress = (sliceVerticalPosition - 1) * mMacroblockWidth - 1;

        mQuantizerScale = mInput.getBits(5);

        int extraBitSlice = 0;
        while (mInput.nextBits(1) == 0x1) {
            extraBitSlice = mInput.getBits(1);
            int extraInformationSlice = mInput.getBits(8);
        }
        extraBitSlice = mInput.getBits(1);

        do {
            parseMacroblock();
        } while (mInput.nextBits(23) != 0x0);

        nextStartCode();
    }

    // Used for decoding motion vectors
	private int mMotionHorizontalForwardR;
	private int mMotionVerticalForwardR;

	private int mMotionHorizontalBackwardR;
	private int mMotionVerticalBackwardR;

    private Vlc.MacroblockType mMacroblockType = mVlc.new MacroblockType(); 

    /*
     * A macroblock has 4 luminance blocks and 2 chrominance blocks.
     * The order of blocks in a macroblock is top-left, top-right, 
     * bottom-left, bottom-right block for Y, followed by Cb and Cr.
     * A macroblock is the basic unit for motion compensation and 
     * quantizer scale changes.
     */
	private void parseMacroblock() throws IOException {
        // Discarded by decoder
        while (mInput.nextBits(11) == 0xf) {
            int macroblockStuffing = mInput.getBits(11);
        }

		int macroblockAddressIncrement = 0;

		while (mInput.nextBits(11) == 0x8) {
            int macroblockEscape = mInput.getBits(11);
            macroblockAddressIncrement += 33;
        }

        macroblockAddressIncrement += mVlc.getMacroblockAddressIncrement(mInput);

        // Process skipped macroblocks
		if (macroblockAddressIncrement > 1) {
			mDctDcYPast = mDctDcCrPast = mDctDcCbPast = 1024;

			/*
			 * In P-pictures, the skipped macroblock is defined to be 
			 * a macroblock with a reconstructed motion vector equal 
			 * to zero and no DCT coefficients.
			 */
			if (mPictureCodingType == Picture.P_TYPE) {
				mForward.resetPrevious();

				for (int i = 0; i < macroblockAddressIncrement; ++i) {
					int mbRow = (mMacroblockAddress + 1 + i) / mMacroblockWidth;
					int mbCol = (mMacroblockAddress + 1 + i) % mMacroblockWidth;

					mPictureStore[mCurrent].copy(mPictureStore[mPrevious], mbRow, mbCol);
				}
			}
			/*
			 * In B-pictures, the skipped macroblock is defined to have 
			 * the same macroblock_type (forward, backward, or both motion 
			 * vectors) as the prior macroblock, differential motion 
			 * vectors equal to zero, and no DCT coefficients.
			 */
			else if (mPictureCodingType == Picture.B_TYPE) {
				for (int i = 0; i < macroblockAddressIncrement; ++i) {
					int mbRow = (mMacroblockAddress + 1 + i) / mMacroblockWidth;
					int mbCol = (mMacroblockAddress + 1 + i) % mMacroblockWidth;

    				if (!mMacroblockType.mMacroblockMotionForward && mMacroblockType.mMacroblockMotionBackward)
				    	mPictureStore[mCurrent].compensate(mPictureStore[mFuture], mbRow, mbCol, mBackward);
    				else if (mMacroblockType.mMacroblockMotionForward && !mMacroblockType.mMacroblockMotionBackward)
				    	mPictureStore[mCurrent].compensate(mPictureStore[mPrevious], mbRow, mbCol, mForward);
    				else if (mMacroblockType.mMacroblockMotionForward && mMacroblockType.mMacroblockMotionBackward) {
    					mPictureStore[mCurrent].interpolate(mPictureStore[mPrevious], mPictureStore[mFuture], mbRow, mbCol, mForward, mBackward);
					}
				}
			}
		}

		mMacroblockAddress += macroblockAddressIncrement;

		mMacroblockRow = mMacroblockAddress / mMacroblockWidth;
		mMacroblockCol = mMacroblockAddress % mMacroblockWidth;

		/*
		 * For macroblocks in I pictures, and for intra coded macroblocks in 
		 * P and B pictures, the coded block pattern is not transmitted, but 
		 * is assumed to have a value of 63, i.e. all the blocks in the 
		 * macroblock are coded.
		 */
		int codedBlockPattern = 0x3f;

		mVlc.getMacroblockType(mPictureCodingType, mInput, mMacroblockType);

	    if (!mMacroblockType.mMacroblockIntra) {
	    	mDctDcYPast = mDctDcCrPast = mDctDcCbPast = 1024;
	    	codedBlockPattern = 0;
	    }

		if (mMacroblockType.mMacroblockQuant)
			mQuantizerScale = mInput.getBits(5);

		if (mMacroblockType.mMacroblockMotionForward) {
			int motionHorizontalForwardCode = mVlc.getMotionVector(mInput);
			if (mForwardF != 1 && motionHorizontalForwardCode != 0) {
				mMotionHorizontalForwardR = mInput.getBits(mForwardRSize);
			}

			int motionVerticalForwardCode = mVlc.getMotionVector(mInput);
			if (mForwardF != 1 && motionVerticalForwardCode != 0) {
				mMotionVerticalForwardR = mInput.getBits(mForwardRSize);
			}

			mForward.calculate(motionHorizontalForwardCode, mMotionHorizontalForwardR, motionVerticalForwardCode, mMotionVerticalForwardR);
		}

		if (mMacroblockType.mMacroblockMotionBackward) {
			int motionHorizontalBackwardCode = mVlc.getMotionVector(mInput);
			if (mBackwardF != 1 && motionHorizontalBackwardCode != 0) {
				mMotionHorizontalBackwardR = mInput.getBits(mBackwardRSize);
			}

			int motionVerticalBackwardCode = mVlc.getMotionVector(mInput);
			if (mBackwardF != 1 && motionVerticalBackwardCode != 0) {
				mMotionVerticalBackwardR = mInput.getBits(mBackwardRSize);
			}

			mBackward.calculate(motionHorizontalBackwardCode, mMotionHorizontalBackwardR, motionVerticalBackwardCode, mMotionVerticalBackwardR);
		}

		if (mPictureCodingType == Picture.P_TYPE) {	// See 2.4.4.2
			if (mMacroblockType.mMacroblockMotionForward) {
				mPictureStore[mCurrent].compensate(mPictureStore[mPrevious], mMacroblockRow, mMacroblockCol, mForward);
			}
			else {
				mPictureStore[mCurrent].copy(mPictureStore[mPrevious], mMacroblockRow, mMacroblockCol);
			}
		}
		else if (mPictureCodingType == Picture.B_TYPE) {	// See 2.4.4.3
			if (mMacroblockType.mMacroblockMotionForward && !mMacroblockType.mMacroblockMotionBackward) {
				mPictureStore[mCurrent].compensate(mPictureStore[mPrevious], mMacroblockRow, mMacroblockCol, mForward);
			}
			else if(!mMacroblockType.mMacroblockMotionForward && mMacroblockType.mMacroblockMotionBackward) {
				mPictureStore[mCurrent].compensate(mPictureStore[mFuture], mMacroblockRow, mMacroblockCol, mBackward);
			}
			else if (mMacroblockType.mMacroblockMotionForward && mMacroblockType.mMacroblockMotionBackward) {
				mPictureStore[mCurrent].interpolate(mPictureStore[mPrevious], mPictureStore[mFuture], mMacroblockRow, mMacroblockCol, mForward, mBackward);
			}
		}

		if (mPictureCodingType == Picture.P_TYPE && !mMacroblockType.mMacroblockMotionForward)
			mForward.resetPrevious();

		if (mPictureCodingType == Picture.B_TYPE && mMacroblockType.mMacroblockIntra) {
			mForward.resetPrevious();
			mBackward.resetPrevious();
		}

		if (mMacroblockType.mMacroblockPattern)
			codedBlockPattern = mVlc.getCodedBlockPattern(mInput);

		/*
		 * The Coded Block Pattern informs the decoder which of the six blocks 
		 * in the macroblock are coded, i.e. have transmitted DCT quantized 
		 * coefficients, and which are not coded, i.e. have no additional 
		 * correction after motion compensation
		 */
		for (int i = 0; i < 6; i++)	{
			if ((codedBlockPattern & (1 << (5 - i))) != 0) {
				parseBlock(i);

				if (mMacroblockType.mMacroblockIntra) {
				 	if (i < 4) mPictureStore[mCurrent].setLumBlock(mDctRecon, mMacroblockRow, mMacroblockCol, i);
					else	   mPictureStore[mCurrent].setColBlock(mDctRecon, mMacroblockRow, mMacroblockCol, i);
				}
				else {
					if (i < 4) mPictureStore[mCurrent].correctLumBlock(mDctRecon, mMacroblockRow, mMacroblockCol, i);
					else       mPictureStore[mCurrent].correctColBlock(mDctRecon, mMacroblockRow, mMacroblockCol, i);
				}
			}
		}

		if (mPictureCodingType == Picture.D_TYPE)
			mInput.getBits(1);
	}

    private int[] mNullMatrix = new int[64];
    private int[] mDctRecon   = new int[64];
    private int[] mDctZigzag  = new int[64];

    /*
     * A block is an orthogonal 8-pel by 8-line section of a 
     * luminance or chrominance component.
     */
	private void parseBlock(int index) throws IOException {
		Vlc.RunLevel runLevel = mVlc.new RunLevel();

        System.arraycopy(mNullMatrix, 0, mDctRecon, 0, 64);
        System.arraycopy(mNullMatrix, 0, mDctZigzag, 0, 64);

        int run = 0;

		if (mMacroblockType.mMacroblockIntra) {
            if (index < 4) {
                int dctDCSizeLuminance = mVlc.decodeDCTDCSizeLuminance(mInput);
                int dctDCDifferential = 0;

                if (dctDCSizeLuminance != 0) {
                    dctDCDifferential = mInput.getBits(dctDCSizeLuminance);

                    if ((dctDCDifferential & (1 << (dctDCSizeLuminance - 1))) != 0)
                        mDctZigzag[0] = dctDCDifferential;
                    else
                        mDctZigzag[0] = ((-1 << dctDCSizeLuminance) | (dctDCDifferential + 1));
                }
            }
            else {
                int dctDCSizeChrominance = mVlc.decodeDCTDCSizeChrominance(mInput);
                int dctDCDifferential = 0;

                if (dctDCSizeChrominance != 0) {
                    dctDCDifferential = mInput.getBits(dctDCSizeChrominance);

                    if ((dctDCDifferential & (1 << (dctDCSizeChrominance - 1))) != 0)
                        mDctZigzag[0] = dctDCDifferential;
                    else
                        mDctZigzag[0] = ((-1 << dctDCSizeChrominance) | (dctDCDifferential + 1));
                }
            }
        }
        else {
            // dctCoeffFirst
            mVlc.decodeDCTCoeff(mInput, true, runLevel);

		    run = runLevel.run;
	    	mDctZigzag[run] = runLevel.level;
        }

        if (mPictureCodingType != Picture.D_TYPE) {
            while (mInput.nextBits(2) != 0x2) {
                // dctCoeffNext
            	mVlc.decodeDCTCoeff(mInput, false, runLevel);

                run += runLevel.run + 1;
                mDctZigzag[run] = runLevel.level;
            }
            int endOfBlock = mInput.getBits(2); // Should be == 0x2 (EOB)

            if (mMacroblockType.mMacroblockIntra) {
                if (index == 0)
                    firstLuminanceBlock(mDctRecon);
                else if (index >= 1 && index <= 3)
                    nextLuminanceBlock(mDctRecon);
                else if (index == 4)
                    cbBlock(mDctRecon);
                else if (index == 5)
                    crBlock(mDctRecon);

                mPastIntraAddress = mMacroblockAddress;
            }
            else {
            	// See ISO/IEC 11172 2.4.4.2 / 2.4.4.3
            	for (int i = 0; i < 64; ++i) {
                    int idx = ScanMatrix[i];
                    mDctRecon[i] = ((2 * mDctZigzag[idx] + sign(mDctZigzag[idx])) * mQuantizerScale * NonIntraQuantizerMatrix[i]) >> 4;

                    if ((mDctRecon[i] & 1) == 0) {
                        mDctRecon[i] -= sign(mDctRecon[i]);
                        if (mDctRecon[i] > 2047) mDctRecon[i] = 2047;
                        if (mDctRecon[i] < -2048) mDctRecon[i] = -2048;

                        if (mDctZigzag[idx] == 0)
                            mDctRecon[i] = 0;
                    }
                }
            }

            mIdct.calculate(mDctRecon);
        }
	}

	
	/*
	 * Helper function
	 */
	private int sign(int n) {
		return n > 0? 1 : (n < 0? -1 : 0);
	}

	/*
	 * Reconstruct DCT coefficients, as defined in ISO/IEC 11172 2.4.4.1
	 */
	private void firstLuminanceBlock(int[] dct_recon) throws IOException {
		for (int i = 0; i < 64; ++i) {
			int index = ScanMatrix[i];
			dct_recon[i] = (mDctZigzag[index] * mQuantizerScale * IntraQuantizerMatrix[i]) >> 3;

			if ((dct_recon[i] & 1) == 0) {
				dct_recon[i] -= sign(dct_recon[i]);
				if (dct_recon[i] > 2047) dct_recon[i] = 2047;
				if (dct_recon[i] < -2048) dct_recon[i] = -2048;
			}
		}

		dct_recon[0] = mDctZigzag[0] << 3;

		if (mMacroblockAddress - mPastIntraAddress > 1)
			dct_recon[0] += 1024;
		else
			dct_recon[0] += mDctDcYPast;

		mDctDcYPast = dct_recon[0];
	}

	private void nextLuminanceBlock(int[] dct_recon) throws IOException {
		for (int i = 0; i < 64; ++i) {
			int index = ScanMatrix[i];
			dct_recon[i] = (mDctZigzag[index] * mQuantizerScale * IntraQuantizerMatrix[i]) >> 3;

			if ((dct_recon[i] & 1) == 0) {
				dct_recon[i] -= sign(dct_recon[i]);
				if (dct_recon[i] > 2047) dct_recon[i] = 2047;
				if (dct_recon[i] < -2048) dct_recon[i] = -2048;
			}
		}

		dct_recon[0] = mDctDcYPast + (mDctZigzag[0] << 3);

		mDctDcYPast = dct_recon[0];
	}

	private void cbBlock(int[] dct_recon) throws IOException {
		for (int i = 0; i < 64; ++i) {
			int index = ScanMatrix[i];
			dct_recon[i] = (mDctZigzag[index] * mQuantizerScale * IntraQuantizerMatrix[i]) >> 3;

			if ((dct_recon[i] & 1) == 0) {
				dct_recon[i] -= sign(dct_recon[i]);
				if (dct_recon[i] > 2047) dct_recon[i] = 2047;
				if (dct_recon[i] < -2048) dct_recon[i] = -2048;
			}
		}

		dct_recon[0] = mDctZigzag[0] << 3;

		if (mMacroblockAddress - mPastIntraAddress > 1)
			dct_recon[0] += 1024;
		else
			dct_recon[0] += mDctDcCbPast;

		mDctDcCbPast = dct_recon[0];
	}

	private void crBlock(int[] dct_recon) throws IOException {
		for (int i = 0; i < 64; ++i) {
			int index = ScanMatrix[i];
			dct_recon[i] = (mDctZigzag[index] * mQuantizerScale * IntraQuantizerMatrix[i]) >> 3;

			if ((dct_recon[i] & 1) == 0) {
				dct_recon[i] -= sign(dct_recon[i]);
				if (dct_recon[i] > 2047) dct_recon[i] = 2047;
				if (dct_recon[i] < -2048) dct_recon[i] = -2048;
			}
		}

		dct_recon[0] = mDctZigzag[0] << 3;

		if (mMacroblockAddress - mPastIntraAddress > 1)
			dct_recon[0] += 1024;
		else
			dct_recon[0] += mDctDcCrPast;

		mDctDcCrPast = dct_recon[0];
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -