public void start() {
    mRunning = true;
    mSession.setTimestampClock(
        new TimestampClock() {
          public int getCurrentTimestamp() {
            return getCurTs();
          }
        });
    try {
      mPlayer =
          Manager.createPlayer(
              new DataSource(null) {
                SourceStream[] mStream = {mInput};

                public void connect() throws IOException {
                  sLogger.info("connect data source");
                }

                public void disconnect() {
                  sLogger.info("disconnect data source");
                }

                public String getContentType() {
                  return "audio/amr";
                }

                public SourceStream[] getStreams() {
                  return mStream;
                }

                public void start() throws IOException {
                  sLogger.info("start data source");
                }

                public void stop() throws IOException {
                  sLogger.info("start data source");
                }

                public Control getControl(String controlType) {
                  return null;
                }

                public Control[] getControls() {
                  return null;
                }
              });

      mPlayer.addPlayerListener(this);
      mPlayer.realize();
      AudioPathControl lPathCtr =
          (AudioPathControl)
              mPlayer.getControl("net.rim.device.api.media.control.AudioPathControl");
      lPathCtr.setAudioPath(AudioPathControl.AUDIO_PATH_HANDSET);
      mPlayer.prefetch();
      // if ( DeviceInfo.isSimulator() == false) { //only start player on real device
      mPlayer.start();

      if (sLogger.isLevelEnabled(Logger.Info)) sLogger.info("Player is started .");
      // }

    } catch (Throwable e) {
      sLogger.error("player error:", e);
    }
  }
        /* (non-Javadoc)
         * @see java.io.InputStream#read(byte[], int, int)
         */
        public int read(byte[] b, int offset, int length) throws IOException {
          int bytesToReturn = sSilentAmr.length;

          if (mBuffering) {
            bytesToReturn = sSilentAmr.length * 8;
          }
          try {

            if (!priority_set && Thread.currentThread().getPriority() != Thread.MAX_PRIORITY) {
              Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
              priority_set = true;
            }
            // if (sLogger.isLevelEnabled(Logger.Info) && ((mPlayer.getMediaTime()<<3) % 1000 ==
            // 0))sLogger.info("Player media time ["+mPlayer.getMediaTime()+"]");
            int lWrittenLenth = 0;

            while (lWrittenLenth <= bytesToReturn && mRunning) {
              long ts = getCurTs();
              if (mPlayerTs == -1) {
                mPlayerTs = ts;
                sLogger.info("Initializing timestamp to [" + mPlayerTs + "]");
              }
              RtpPacket packet = null;
              try {
                long diff;

                while ((diff = (ts - mPlayerTs)) >= 0) {
                  if (diff > 800) {
                    mPlayerTs = ts - 800;
                    sLogger.warn("Too late, skipping " + ((diff - 800) / 8) + " ms...");
                  }
                  packet = mSession.recvPacket((int) mPlayerTs);
                  if (packet != null) {
                    mReturnedMs += 20;
                    if (mFirstRead) {
                      String lAmrHeader = "#!AMR\n";
                      lWrittenLenth = lAmrHeader.length();
                      System.arraycopy(
                          lAmrHeader.getBytes("US-ASCII"), 0, b, offset, lWrittenLenth);
                      length = length - lWrittenLenth;
                      offset += lWrittenLenth;
                      mFirstRead = false;
                    }
                    if ((length < sSilentAmr.length)) {
                      // special case for end of buffer

                      System.arraycopy(
                          packet.getBytes(), packet.getDataOffset() + 1, b, offset, length);
                      lWrittenLenth += length;
                      mTroncatedPacketSize = length;
                      mTroncatedPacket = packet;
                      if (sLogger.isLevelEnabled(Logger.Warn))
                        sLogger.warn("End of buffer, [" + lWrittenLenth + "] bytes returned");
                      return lWrittenLenth;
                    } else {
                      if (mTroncatedPacket != null) {
                        // special case for troncated packet
                        int remain =
                            mTroncatedPacket.getRealLength()
                                - mTroncatedPacket.getDataOffset()
                                - 1
                                - mTroncatedPacketSize;
                        System.arraycopy(
                            mTroncatedPacket.getBytes(),
                            mTroncatedPacket.getDataOffset() + 1 + mTroncatedPacketSize,
                            b,
                            offset,
                            remain);
                        lWrittenLenth += remain;
                        mTroncatedPacketSize = 0;
                        mTroncatedPacket = null;
                        offset += remain;
                        length -= remain;
                      }
                      // +1 because we need to skip the CMR bytes
                      int datalen = packet.getRealLength() - packet.getDataOffset() - 1;
                      System.arraycopy(
                          packet.getBytes(), packet.getDataOffset() + 1, b, offset, datalen);
                      lWrittenLenth += datalen;
                      length -= datalen;
                      offset += datalen;
                    }
                  }
                  mPlayerTs += 160;
                }

              } catch (RtpException e) {
                sLogger.error("Bad RTP packet", e);
              }
              if (packet == null) Thread.sleep(20);
            }
            if (!mRunning) {
              // to notify end of stream.
              return -1;
            }
            if (sLogger.isLevelEnabled(Logger.Debug))
              sLogger.debug("[" + lWrittenLenth + "] bytes returned");
            return lWrittenLenth;
          } catch (Throwable e) {
            sLogger.error("Exiting player input stream", e);
            return -1;
          } finally {
            if (bytesToReturn > sSilentAmr.length) {
              // we were buffering, so now it's ok resetting value
              mBuffering = false;
            }
          }
        }