FileDocCategorySizeDatePackage
JavaDecoder.javaAPI DocJMF 2.1.1e10278Mon May 12 12:21:00 BST 2003com.ibm.media.codec.video.h263

JavaDecoder

public class JavaDecoder extends VideoCodec

Fields Summary
private static final int
rMask
private static final int
gMask
private static final int
bMask
private static final boolean
DEBUG
private H263Decoder
javaDecoder
private FrameBuffer
outputFrame
public static final int[]
widths
public static final int[]
heights
private int
videoWidth
private int
videoHeight
private boolean
FormatSizeInitFlag
private int
payloadLength
static boolean
nativeAvail
Constructors Summary
public JavaDecoder()

     
	if (plugInExists("com.sun.media.codec.video.vh263.NativeDecoder", PlugInManager.CODEC)) {
	    try {
		JMFSecurityManager.loadLibrary("jmutil");
		JMFSecurityManager.loadLibrary("jmvh263");
		nativeAvail = true;
	    } catch (Throwable t) { }
	}
    
        supportedInputFormats = new VideoFormat[] {new VideoFormat(VideoFormat.H263),new VideoFormat(VideoFormat.H263_RTP) };
        defaultOutputFormats  = new VideoFormat[] {new RGBFormat() };
        PLUGIN_NAME = "H.263 Decoder";

    
Methods Summary
public booleancheckFormat(javax.media.Format format)


      if ( (format.getEncoding()).equals(VideoFormat.H263_RTP) ) {
        return true;
      }
      else {
        return super.checkFormat(format);
      }

    
public voidclose()

        javaDecoder=null;
    
booleandecodeData(javax.media.Buffer inputBuffer, int inputLength, javax.media.Buffer outputBuffer, boolean rtpData)


        int ret;
        int [] outData = (int [])outputBuffer.getData();
        byte[] inputData = (byte [])inputBuffer.getData();


        if (inputLength <= 0) {
            return false;
        }

        javaDecoder.initBitstream();
        int inputOffset=inputBuffer.getOffset();
        if (rtpData) {

//          RTPHeader rtpHeader= (RTPHeader) inputBuffer.getHeader();
            if (DEBUG) {
        	  System.out.println("[javadecoder:decodeData] inputBuffer.getTimeStamp()=" + inputBuffer.getTimeStamp());
//	          System.out.println("[javadecoder:decodeData] rtpHeader.getMarker()=" + inputBuffer.getHeader().getMarker());
                  }
          ret = javaDecoder.DecodeRtpPacket(inputData,inputOffset+payloadLength,inputLength,inputData,inputOffset,inputBuffer.getTimeStamp());
          if(ret ==  H263Decoder.H263_RC_PICTURE_FORMAT_NOT_INITED) {
          if (DEBUG)
            System.out.println("[javadecoder:decodeData] FORMAT_NOT_INITED returing false");
            return false;
            }
        }
        else {
           ret = javaDecoder.DecodePicture(inputData,inputOffset,true);
        }


        if (ret == H263Decoder.H263_RC_PICTURE_FORMAT_NOT_SUPPORTED) {
        if (DEBUG)
            System.out.println("[javadecoder:decodeData] throwing exception - format is not supported ");
            throw new RuntimeException("Currently this picture format is not supported!");
        }

        if (ret == H263Decoder.H263_RC_PICTURE_DONE) {
              int outWidth  = outputFormat.getSize().width;
              int outHeight = outputFormat.getSize().height;
              outputFrame = javaDecoder.CurrentFrame;
	      YCbCrToRGB.convert(outputFrame.Y,outputFrame.Cb,outputFrame.Cr,outData,outputFrame.width,outputFrame.height,outWidth,outHeight,255,4);
              return true;
            }
        else {
        if (DEBUG)
          System.out.println("[javadecoder:decodeData] ret != H263Decoder.H263_RC_PICTURE_DONE returning false");
          return false;
        }


    
protected javax.media.Format[]getMatchingOutputFormats(javax.media.Format in)

      	VideoFormat     ivf  = (VideoFormat) in;
	Dimension       inSize = ivf.getSize();
        int             maxDataLength=ivf.getMaxDataLength();

        if ( (ivf.getEncoding()).equals(VideoFormat.H263_RTP) ) {
          supportedOutputFormats= new  VideoFormat[] {

                new RGBFormat (new Dimension(videoWidth,videoHeight),
                videoWidth * videoHeight, int[].class,
	        ivf.getFrameRate(),			       
                32,
      	        rMask, gMask, bMask,
                1,videoWidth,
		Format.FALSE, // flipped
		Format.NOT_SPECIFIED // endian
                ) /*,

                new RGBFormat (null,
                Format.NOT_SPECIFIED, int[].class,
                32,
      	        rMask, gMask, bMask,
                1,Format.NOT_SPECIFIED )*/ };

        }

        else {
          supportedOutputFormats= new  VideoFormat[] {
                new RGBFormat (new Dimension(inSize),
                inSize.width * inSize.height, int[].class,
                ivf.getFrameRate(),
                32,
      	        rMask, gMask, bMask,
                1,inSize.width,
		Format.FALSE, // flipped
		Format.NOT_SPECIFIED // endian
                ) };
        }

        return  supportedOutputFormats;
    
public static intgetPayloadHeaderLength(byte[] input, int offset)


       int l = 0;
       byte b = input[offset];

	if ( (b & 0x80) != 0) { //mode B or C
	    if ((b & 0x40) != 0) //mode C
		l = 12;
	    else //mode B
		l = 8;
	} else { //mode A
	    l = 4;
	}

	return l;
    
protected voidinitDecoder()

        javaDecoder = new H263Decoder(true);
    
public voidopen()

        initDecoder();
    
public intprocess(javax.media.Buffer inputBuffer, javax.media.Buffer outputBuffer)



      boolean rtpData = false;

      if (!checkInputBuffer(inputBuffer) ) {
         return BUFFER_PROCESSED_FAILED;
      }

      if (isEOM(inputBuffer) ) {
         propagateEOM(outputBuffer);
         return BUFFER_PROCESSED_OK;
      }

      VideoFormat ivf=(VideoFormat) inputBuffer.getFormat();
      int inLength=inputBuffer.getLength();
      int inMaxLength=ivf.getMaxDataLength();
      int outMaxLength=outputFormat.getMaxDataLength();
      int inputOffset=inputBuffer.getOffset();

      byte[] inData =(byte[]) inputBuffer.getData();

      if ( (ivf.getEncoding()).equals(VideoFormat.H263_RTP) ) {
        rtpData = true;
        payloadLength=getPayloadHeaderLength(inData,inputOffset);

        if ( (inData[inputOffset+payloadLength] == 0) && (inData[inputOffset+payloadLength+1] == 0) &&
	                                                ((inData[inputOffset+payloadLength+2] & 0xfc) == 0x80)) {
              int s = (inData[inputOffset+payloadLength+4] >> 2) & 0x7;


              if ( (videoWidth!=widths[s]) || (videoHeight!=heights[s])  ) {

                 videoWidth=widths[s];
                 videoHeight=heights[s];


                 outputFormat = new RGBFormat (new Dimension(videoWidth,videoHeight),
                    videoWidth * videoHeight, int[].class,
                    ivf.getFrameRate(),
                    32,
      	            rMask, gMask, bMask,
                    1,videoWidth,
                    Format.FALSE, // flipped
		    Format.NOT_SPECIFIED // endian
                  );


                  outMaxLength = videoWidth*videoHeight;

                  if (FormatSizeInitFlag)
                    videoResized();       // allocate a new decoder only after it was actually used
               }

               FormatSizeInitFlag=true;

        }

        if (false == FormatSizeInitFlag) {
          return BUFFER_PROCESSED_FAILED;
        }

      }


    int[] outData = validateIntArraySize(outputBuffer,outMaxLength );

      /*
       *  <PATCH> check for insufficient input:
       *  The decoder might read up to 8 additional bytes before checking for EOS
       *  It does not bother the native code, but can cause ArrayOutOfBounds
       *  in Java code
       */
      if ( (inLength+8+inputOffset)>inData.length) {
        if (DEBUG)
         System.out.println("allocating more data for H.263");
         int newLength=(inLength > inMaxLength) ? inLength : inMaxLength;

         byte[] tempArray=new byte[inputOffset+newLength+8];
         System.arraycopy(inData,0,tempArray,0,inLength+inputOffset);
         inData=tempArray;
         inputBuffer.setData(tempArray);
         //inputBuffer.setOffset(0);

      }

      /*
       *  <PATCH> pad input with EOS
       */
      inData[inputOffset+inLength] = 0;
      inData[inputOffset+inLength+1] = 0;
      inData[inputOffset+inLength+2]= (byte) 0xfc;
      inLength += 3;
      inputBuffer.setLength(inLength);

      if (rtpData)
        inLength-=payloadLength;  // this is the length of the bitstream

      boolean ret = decodeData(inputBuffer,inLength,outputBuffer,rtpData);
      if (ret) {
           updateOutput(outputBuffer,outputFormat, outMaxLength, 0);
           return BUFFER_PROCESSED_OK;
       }
       else {
       if (DEBUG)
         System.out.println("[JavaDecoder] : returning OUTPUT_BUFFER_NOT_FILLED; ");
         return OUTPUT_BUFFER_NOT_FILLED;
       }


    
public voidreset()

       initDecoder();
    
public javax.media.FormatsetInputFormat(javax.media.Format format)
Set the data input format.

return
false if the format is not supported.

	if (nativeAvail)
	    return null;
	if (super.setInputFormat(format) != null) {
	    reset();
	    return format;
	} else
	    return null;
    
protected voidvideoResized()

        initDecoder();