Package com.xuggle.xuggler

Examples of com.xuggle.xuggler.IContainer


  @Test
  public void testCreateSDPData()
  {
    IContainerFormat format = IContainerFormat.make();
    format.setOutputFormat("rtp", null, null);
    IContainer container = IContainer.make();
    container.open("rtp://127.0.0.1:23832", IContainer.Type.WRITE, format);
    IStream stream = container.addNewStream(0);
    IStreamCoder coder = stream.getStreamCoder();
    coder.setCodec(ICodec.ID.CODEC_ID_H263);
    coder.setWidth(352);
    coder.setHeight(288);
    coder.setPixelType(IPixelFormat.Type.YUV420P);
    coder.setTimeBase(IRational.make(1,90000));
    coder.open();
   
    IBuffer buffer = IBuffer.make(null, 4192);
    int len = container.createSDPData(buffer);
    assertTrue(len > 1);
    byte[] stringBuf = new byte[len-1];
    buffer.get(0, stringBuf, 0, stringBuf.length);
    String sdp = new String(stringBuf);
    assertNotNull(sdp);
    log.debug("SDP({}) = {}", sdp.length(), sdp);
   
    String otherSdp = container.createSDPData();
    assertEquals(sdp, otherSdp);
  }
View Full Code Here


            }
        }

        logger.trace("Opening stream in a Xuggler container using format {}",
                format);
        IContainer container = IContainer.make();
        XugglerException.throwIfInError(container.open(encoded, format));

        logger.trace("Looking for first audio stream in container");
        int streamId = -1;
        IStreamCoder audioCoder = null;
        int numStreams = container.getNumStreams();
        for (int num = 0; num < numStreams; num++) {
            IStream stream = container.getStream(num);
            IStreamCoder coder = stream.getStreamCoder();
            if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) {
                streamId = num;
                audioCoder = coder;
                break;
View Full Code Here

    @Override
    public JizzTrackInfo read(InputStream in) throws IOException,
            UnsupportedTrackTypeException {
        logger.trace("Opening stream in a Xuggler container");
        IContainer container = IContainer.make();
        XugglerException.throwIfInError(container.open(in, null));
        try {
            IMetaData metadata = container.getMetaData();
            logger.trace("Got Xuggler metadata: {}", metadata);
            return new XugglerTrackInfoImpl(metadata);
        } finally {
            logger.trace("Closing Xuggler container");
            XugglerException.throwIfInError(container.close());
        }
    }
View Full Code Here

      throw new IllegalArgumentException("must pass in a filename as the first argument");
   
    String filename = args[0];
   
    // Create a Xuggler container object
    IContainer container = IContainer.make();
   
    // Open up the container
    if (container.open(filename, IContainer.Type.READ, null) < 0)
      throw new IllegalArgumentException("could not open file: " + filename);
   
    // query how many streams the call to open found
    int numStreams = container.getNumStreams();
   
    // and iterate through the streams to find the first audio stream
    int audioStreamId = -1;
    IStreamCoder audioCoder = null;
    for(int i = 0; i < numStreams; i++)
    {
      // Find the stream object
      IStream stream = container.getStream(i);
      // Get the pre-configured decoder that can decode this stream;
      IStreamCoder coder = stream.getStreamCoder();
     
      if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO)
      {
        audioStreamId = i;
        audioCoder = coder;
        break;
      }
    }
    if (audioStreamId == -1)
      throw new RuntimeException("could not find audio stream in container: "+filename);
   
    /*
     * Now we have found the audio stream in this file.  Let's open up our decoder so it can
     * do work.
     */
    if (audioCoder.open(null, null) < 0)
      throw new RuntimeException("could not open audio decoder for container: "+filename);
   
    /*
     * And once we have that, we ask the Java Sound System to get itself ready.
     */
    openJavaSound(audioCoder);
   
    /*
     * Now, we start walking through the container looking at each packet.
     */
    IPacket packet = IPacket.make();
    while(container.readNextPacket(packet) >= 0)
    {
      /*
       * Now we have a packet, let's see if it belongs to our audio stream
       */
      if (packet.getStreamIndex() == audioStreamId)
      {
        /*
         * We allocate a set of samples with the same number of channels as the
         * coder tells us is in this buffer.
         *
         * We also pass in a buffer size (1024 in our example), although Xuggler
         * will probably allocate more space than just the 1024 (it's not important why).
         */
        IAudioSamples samples = IAudioSamples.make(1024, audioCoder.getChannels());
       
        /*
         * A packet can actually contain multiple sets of samples (or frames of samples
         * in audio-decoding speak).  So, we may need to call decode audio multiple
         * times at different offsets in the packet's data.  We capture that here.
         */
        int offset = 0;
       
        /*
         * Keep going until we've processed all data
         */
        while(offset < packet.getSize())
        {
          int bytesDecoded = audioCoder.decodeAudio(samples, packet, offset);
          if (bytesDecoded < 0)
            throw new RuntimeException("got error decoding audio in: " + filename);
          offset += bytesDecoded;
          /*
           * Some decoder will consume data in a packet, but will not be able to construct
           * a full set of samples yet.  Therefore you should always check if you
           * got a complete set of samples from the decoder
           */
          if (samples.isComplete())
          {
            playJavaSound(samples);
          }
        }
      }
      else
      {
        /*
         * This packet isn't part of our audio stream, so we just silently drop it.
         */
        do {} while(false);
      }
     
    }
    /*
     * Technically since we're exiting anyway, these will be cleaned up by
     * the garbage collector... but because we're nice people and want
     * to be invited places for Christmas, we're going to show how to clean up.
     */
    closeJavaSound();
   
    if (audioCoder != null)
    {
      audioCoder.close();
      audioCoder = null;
    }
    if (container !=null)
    {
      container.close();
      container = null;
    }
  }
View Full Code Here

          musicPath = mp;
        }

        public IMediaWriter addMusic(int streamIndex, IMediaWriter orangeMovie,long total)
        {
                IContainer container = IContainer.make();      
                System.out.println("Adding music");
               
                if (container.open(musicPath, IContainer.Type.READ, null) < 0)
                {
                      throw new IllegalArgumentException("could not open file");
                }

                int numStreams = container.getNumStreams();

                int audioStreamId = -1;
                IStreamCoder audioCoder = null;
                for(int i = 0; i < numStreams; i++)
                {
                        IStream stream = container.getStream(i);
                    IStreamCoder coder = stream.getStreamCoder();

                    if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO)
                    {
                        audioStreamId = i;
                        audioCoder = coder;
                        audioCoder.setBitRate(container.getBitRate());
                        break;
                    }
                }

                if (audioStreamId == -1)
                {
                        throw new RuntimeException("could not find audio stream in container");
                }
                 
                audioCoder.setSampleFormat(IAudioSamples.Format.FMT_S16);
                audioCoder.open();
                IPacket packet = IPacket.make();
                
                long timer = 0;
                boolean stoper = false;
                
                while(stoper == false)
                {
                        container.readNextPacket(packet);
                    if (packet.getStreamIndex() == audioStreamId)
                    {
                        IAudioSamples samples = IAudioSamples.make(512, audioCoder.getChannels(),IAudioSamples.Format.FMT_S16 );
                        int offset = 0;
                        while(offset < packet.getSize())
View Full Code Here

        "you must install the GPL version of Xuggler (with IVideoResampler" +
        " support) for this demo to work");

    // create a Xuggler container object

    IContainer container = IContainer.make();

    // open up the container

    if (container.open(filename, IContainer.Type.READ, null) < 0)
      throw new IllegalArgumentException("could not open file: " + filename);

    // query how many streams the call to open found

    int numStreams = container.getNumStreams();

    // and iterate through the streams to find the first video stream

    int videoStreamId = -1;
    IStreamCoder videoCoder = null;
    for(int i = 0; i < numStreams; i++)
    {
      // find the stream object

      IStream stream = container.getStream(i);

      // get the pre-configured decoder that can decode this stream;

      IStreamCoder coder = stream.getStreamCoder();

      if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO)
      {
        videoStreamId = i;
        videoCoder = coder;
        break;
      }
    }

    if (videoStreamId == -1)
      throw new RuntimeException("could not find video stream in container: "+filename);

    // Now we have found the video stream in this file.  Let's open up
    // our decoder so it can do work

    if (videoCoder.open() < 0)
      throw new RuntimeException(
        "could not open video decoder for container: " + filename);

    IVideoResampler resampler = null;
    if (videoCoder.getPixelType() != IPixelFormat.Type.BGR24)
    {
      // if this stream is not in BGR24, we're going to need to
      // convert it.  The VideoResampler does that for us.

      resampler = IVideoResampler.make(
        videoCoder.getWidth(), videoCoder.getHeight(), IPixelFormat.Type.BGR24,
        videoCoder.getWidth(), videoCoder.getHeight(), videoCoder.getPixelType());
      if (resampler == null)
        throw new RuntimeException(
          "could not create color space resampler for: " + filename);
    }

    // Now, we start walking through the container looking at each packet.

    IPacket packet = IPacket.make();
    while(container.readNextPacket(packet) >= 0)
    {
     
      // Now we have a packet, let's see if it belongs to our video strea

      if (packet.getStreamIndex() == videoStreamId)
      {
        // We allocate a new picture to get the data out of Xuggle

        IVideoPicture picture = IVideoPicture.make(videoCoder.getPixelType(),
            videoCoder.getWidth(), videoCoder.getHeight());

        int offset = 0;
        while(offset < packet.getSize())
        {
          // Now, we decode the video, checking for any errors.

          int bytesDecoded = videoCoder.decodeVideo(picture, packet, offset);
          if (bytesDecoded < 0)
            throw new RuntimeException("got error decoding video in: " + filename);
          offset += bytesDecoded;
         
          // Some decoders will consume data in a packet, but will not
          // be able to construct a full video picture yet.  Therefore
          // you should always check if you got a complete picture from
          // the decode.

          if (picture.isComplete())
          {
            IVideoPicture newPic = picture;
           
            // If the resampler is not null, it means we didn't get the
            // video in BGR24 format and need to convert it into BGR24
            // format.

            if (resampler != null)
            {
              // we must resample
              newPic = IVideoPicture.make(
                resampler.getOutputPixelFormat(), picture.getWidth(),
                picture.getHeight());
              if (resampler.resample(newPic, picture) < 0)
                throw new RuntimeException(
                  "could not resample video from: " + filename);
            }

            if (newPic.getPixelType() != IPixelFormat.Type.BGR24)
              throw new RuntimeException(
                "could not decode video as BGR 24 bit data in: " + filename);

            // convert the BGR24 to an Java buffered image

            BufferedImage javaImage = Utils.videoPictureToImage(newPic);

            // process the video frame

            processFrame(newPic, javaImage);
          }
        }
      }
      else
      {
        // This packet isn't part of our video stream, so we just
        // silently drop it.
        do {} while(false);
      }
    }

    // Technically since we're exiting anyway, these will be cleaned up
    // by the garbage collector... but because we're nice people and
    // want to be invited places for Christmas, we're going to show how
    // to clean up.

    if (videoCoder != null)
    {
      videoCoder.close();
      videoCoder = null;
    }
    if (container !=null)
    {
      container.close();
      container = null;
    }
  }
View Full Code Here

    // Let's make sure that we can actually convert video pixel formats.
    if (!IVideoResampler.isSupported(IVideoResampler.Feature.FEATURE_COLORSPACECONVERSION))
      throw new RuntimeException("you must install the GPL version of Xuggler (with IVideoResampler support) for this demo to work");

    // Create a Xuggler container object
    IContainer container = IContainer.make();

    // Tell Xuggler about the device format
    IContainerFormat format = IContainerFormat.make();
    if (format.setInputFormat(driverName) < 0)
      throw new IllegalArgumentException("couldn't open webcam device: " + driverName);

    // devices, unlike most files, need to have parameters set in order
    // for Xuggler to know how to configure them, for a webcam, these
    // parameters make sense

    IMetaData params = IMetaData.make();
   
    params.setValue("framerate", "30/1");
    params.setValue("video_size", "320x240");   

    // Open up the container
    int retval = container.open(deviceName, IContainer.Type.READ, format,
        false, true, params, null);
    if (retval < 0)
    {
      // This little trick converts the non friendly integer return value into
      // a slightly more friendly object to get a human-readable error name
      IError error = IError.make(retval);
      throw new IllegalArgumentException("could not open file: " + deviceName + "; Error: " + error.getDescription());
    }     

    // query how many streams the call to open found
    int numStreams = container.getNumStreams();

    // and iterate through the streams to find the first video stream
    int videoStreamId = -1;
    IStreamCoder videoCoder = null;
    for(int i = 0; i < numStreams; i++)
    {
      // Find the stream object
      IStream stream = container.getStream(i);
      // Get the pre-configured decoder that can decode this stream;
      IStreamCoder coder = stream.getStreamCoder();

      if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO)
      {
        videoStreamId = i;
        videoCoder = coder;
        break;
      }
    }
    if (videoStreamId == -1)
      throw new RuntimeException("could not find video stream in container: "+deviceName);

    /*
     * Now we have found the video stream in this file.  Let's open up our decoder so it can
     * do work.
     */
    if (videoCoder.open() < 0)
      throw new RuntimeException("could not open video decoder for container: "+deviceName);

    IVideoResampler resampler = null;
    if (videoCoder.getPixelType() != IPixelFormat.Type.BGR24)
    {
      // if this stream is not in BGR24, we're going to need to
      // convert it.  The VideoResampler does that for us.
      resampler = IVideoResampler.make(videoCoder.getWidth(), videoCoder.getHeight(), IPixelFormat.Type.BGR24,
          videoCoder.getWidth(), videoCoder.getHeight(), videoCoder.getPixelType());
      if (resampler == null)
        throw new RuntimeException("could not create color space resampler for: " + deviceName);
    }
    /*
     * And once we have that, we draw a window on screen
     */
    openJavaWindow();

    /*
     * Now, we start walking through the container looking at each packet.
     */
    IPacket packet = IPacket.make();
    while(container.readNextPacket(packet) >= 0)
    {
      /*
       * Now we have a packet, let's see if it belongs to our video stream
       */
      if (packet.getStreamIndex() == videoStreamId)
      {
        /*
         * We allocate a new picture to get the data out of Xuggler
         */
        IVideoPicture picture = IVideoPicture.make(videoCoder.getPixelType(),
            videoCoder.getWidth(), videoCoder.getHeight());

        int offset = 0;
        while(offset < packet.getSize())
        {
          /*
           * Now, we decode the video, checking for any errors.
           *
           */
          int bytesDecoded = videoCoder.decodeVideo(picture, packet, offset);
          if (bytesDecoded < 0)
            throw new RuntimeException("got error decoding video in: " + deviceName);
          offset += bytesDecoded;

          /*
           * Some decoders will consume data in a packet, but will not be able to construct
           * a full video picture yet.  Therefore you should always check if you
           * got a complete picture from the decoder
           */
          if (picture.isComplete())
          {
            IVideoPicture newPic = picture;
            /*
             * If the resampler is not null, that means we didn't get the video in BGR24 format and
             * need to convert it into BGR24 format.
             */
            if (resampler != null)
            {
              // we must resample
              newPic = IVideoPicture.make(resampler.getOutputPixelFormat(), picture.getWidth(), picture.getHeight());
              if (resampler.resample(newPic, picture) < 0)
                throw new RuntimeException("could not resample video from: " + deviceName);
            }
            if (newPic.getPixelType() != IPixelFormat.Type.BGR24)
              throw new RuntimeException("could not decode video as BGR 24 bit data in: " + deviceName);

            // Convert the BGR24 to an Java buffered image
            BufferedImage javaImage = Utils.videoPictureToImage(newPic);

            // and display it on the Java Swing window
            updateJavaWindow(javaImage);
          }
        }
      }
      else
      {
        /*
         * This packet isn't part of our video stream, so we just silently drop it.
         */
        do {} while(false);
      }

    }
    /*
     * Technically since we're exiting anyway, these will be cleaned up by
     * the garbage collector... but because we're nice people and want
     * to be invited places for Christmas, we're going to show how to clean up.
     */
    if (videoCoder != null)
    {
      videoCoder.close();
      videoCoder = null;
    }
    if (container !=null)
    {
      container.close();
      container = null;
    }
    closeJavaWindow();

  }
View Full Code Here

    // Let's make sure that we can actually convert video pixel formats.
    if (!IVideoResampler.isSupported(IVideoResampler.Feature.FEATURE_COLORSPACECONVERSION))
      throw new RuntimeException("you must install the GPL version of Xuggler (with IVideoResampler support) for this demo to work");
   
    // Create a Xuggler container object
    IContainer container = IContainer.make();
   
    // Open up the container
    if (container.open(filename, IContainer.Type.READ, null) < 0)
      throw new IllegalArgumentException("could not open file: " + filename);
   
    // query how many streams the call to open found
    int numStreams = container.getNumStreams();
   
    // and iterate through the streams to find the first audio stream
    int videoStreamId = -1;
    IStreamCoder videoCoder = null;
    int audioStreamId = -1;
    IStreamCoder audioCoder = null;
    for(int i = 0; i < numStreams; i++)
    {
      // Find the stream object
      IStream stream = container.getStream(i);
      // Get the pre-configured decoder that can decode this stream;
      IStreamCoder coder = stream.getStreamCoder();
     
      if (videoStreamId == -1 && coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO)
      {
        videoStreamId = i;
        videoCoder = coder;
      }
      else if (audioStreamId == -1 && coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO)
      {
        audioStreamId = i;
        audioCoder = coder;
      }
    }
    if (videoStreamId == -1 && audioStreamId == -1)
      throw new RuntimeException("could not find audio or video stream in container: "+filename);
   
    /*
     * Check if we have a video stream in this file.  If so let's open up our decoder so it can
     * do work.
     */
    IVideoResampler resampler = null;
    if (videoCoder != null)
    {
      if(videoCoder.open() < 0)
        throw new RuntimeException("could not open audio decoder for container: "+filename);
   
      if (videoCoder.getPixelType() != IPixelFormat.Type.BGR24)
      {
        // if this stream is not in BGR24, we're going to need to
        // convert it.  The VideoResampler does that for us.
        resampler = IVideoResampler.make(videoCoder.getWidth(), videoCoder.getHeight(), IPixelFormat.Type.BGR24,
            videoCoder.getWidth(), videoCoder.getHeight(), videoCoder.getPixelType());
        if (resampler == null)
          throw new RuntimeException("could not create color space resampler for: " + filename);
      }
      /*
       * And once we have that, we draw a window on screen
       */
      openJavaVideo();
    }
   
    if (audioCoder != null)
    {
      if (audioCoder.open() < 0)
        throw new RuntimeException("could not open audio decoder for container: "+filename);
     
      /*
       * And once we have that, we ask the Java Sound System to get itself ready.
       */
      try
      {
        openJavaSound(audioCoder);
      }
      catch (LineUnavailableException ex)
      {
        throw new RuntimeException("unable to open sound device on your system when playing back container: "+filename);
      }
    }
   
   
    /*
     * Now, we start walking through the container looking at each packet.
     */
    IPacket packet = IPacket.make();
    mFirstVideoTimestampInStream = Global.NO_PTS;
    mSystemVideoClockStartTime = 0;
    while(container.readNextPacket(packet) >= 0)
    {
      /*
       * Now we have a packet, let's see if it belongs to our video stream
       */
      if (packet.getStreamIndex() == videoStreamId)
      {
        /*
         * We allocate a new picture to get the data out of Xuggler
         */
        IVideoPicture picture = IVideoPicture.make(videoCoder.getPixelType(),
            videoCoder.getWidth(), videoCoder.getHeight());
       
        /*
         * Now, we decode the video, checking for any errors.
         *
         */
        int bytesDecoded = videoCoder.decodeVideo(picture, packet, 0);
        if (bytesDecoded < 0)
          throw new RuntimeException("got error decoding audio in: " + filename);

        /*
         * Some decoders will consume data in a packet, but will not be able to construct
         * a full video picture yet.  Therefore you should always check if you
         * got a complete picture from the decoder
         */
        if (picture.isComplete())
        {
          IVideoPicture newPic = picture;
          /*
           * If the resampler is not null, that means we didn't get the video in BGR24 format and
           * need to convert it into BGR24 format.
           */
          if (resampler != null)
          {
            // we must resample
            newPic = IVideoPicture.make(resampler.getOutputPixelFormat(), picture.getWidth(), picture.getHeight());
            if (resampler.resample(newPic, picture) < 0)
              throw new RuntimeException("could not resample video from: " + filename);
          }
          if (newPic.getPixelType() != IPixelFormat.Type.BGR24)
            throw new RuntimeException("could not decode video as BGR 24 bit data in: " + filename);

          long delay = millisecondsUntilTimeToDisplay(newPic);
          // if there is no audio stream; go ahead and hold up the main thread.  We'll end
          // up caching fewer video pictures in memory that way.
          try
          {
            if (delay > 0)
              Thread.sleep(delay);
          }
          catch (InterruptedException e)
          {
            return;
          }

          // And finally, convert the picture to an image and display it

          mScreen.setImage(Utils.videoPictureToImage(newPic));
        }
      }
      else if (packet.getStreamIndex() == audioStreamId)
      {
        /*
         * We allocate a set of samples with the same number of channels as the
         * coder tells us is in this buffer.
         *
         * We also pass in a buffer size (1024 in our example), although Xuggler
         * will probably allocate more space than just the 1024 (it's not important why).
         */
        IAudioSamples samples = IAudioSamples.make(1024, audioCoder.getChannels());
       
        /*
         * A packet can actually contain multiple sets of samples (or frames of samples
         * in audio-decoding speak).  So, we may need to call decode audio multiple
         * times at different offsets in the packet's data.  We capture that here.
         */
        int offset = 0;
       
        /*
         * Keep going until we've processed all data
         */
        while(offset < packet.getSize())
        {
          int bytesDecoded = audioCoder.decodeAudio(samples, packet, offset);
          if (bytesDecoded < 0)
            throw new RuntimeException("got error decoding audio in: " + filename);
          offset += bytesDecoded;
          /*
           * Some decoder will consume data in a packet, but will not be able to construct
           * a full set of samples yet.  Therefore you should always check if you
           * got a complete set of samples from the decoder
           */
          if (samples.isComplete())
          {
            // note: this call will block if Java's sound buffers fill up, and we're
            // okay with that.  That's why we have the video "sleeping" occur
            // on another thread.
            playJavaSound(samples);
          }
        }
      }
      else
      {
        /*
         * This packet isn't part of our video stream, so we just silently drop it.
         */
        do {} while(false);
      }
     
    }
    /*
     * Technically since we're exiting anyway, these will be cleaned up by
     * the garbage collector... but because we're nice people and want
     * to be invited places for Christmas, we're going to show how to clean up.
     */
    if (videoCoder != null)
    {
      videoCoder.close();
      videoCoder = null;
    }
    if (audioCoder != null)
    {
      audioCoder.close();
      audioCoder = null;
    }
    if (container !=null)
    {
      container.close();
      container = null;
    }
    closeJavaSound();
    closeJavaVideo();
  }
View Full Code Here

    IMediaWriter writer = new MediaWriter(file.toString());

    // add the audio stream

    ICodec codec = ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_MP3);
    IContainer container = writer.getContainer();
    IStream stream = container.getStream(
        writer.addAudioStream(audioStreamIndex, audioStreamId,
            codec, channelCount, sampleRate));
    int sampleCount = stream.getStreamCoder().getDefaultAudioFrameSize();

    // create a place for audio samples
View Full Code Here

    IMediaWriter writer = new MediaWriter(file.toString());

    // add the audio stream

    ICodec codec = ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_MP3);
    IContainer container = writer.getContainer();
    int streamIndex = writer.addAudioStream(
        audioStreamIndex, audioStreamId, codec, channelCount, sampleRate);
    IStream stream = container.getStream(streamIndex);
    int sampleCount = stream.getStreamCoder().getDefaultAudioFrameSize();

    // create a place for audio samples

    IAudioSamples samples = IAudioSamples.make(sampleCount, channelCount);
View Full Code Here

TOP

Related Classes of com.xuggle.xuggler.IContainer

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.