예제 #1
0
 public boolean testRecord() throws Exception {
   AudioStream stream = getRecordedStream();
   if (stream != null) {
     audioSpec.inferResultsFrom(stream); // do not move this before the corrector
     return stream.isValid(recordTimeMS) && stream.isDecodeable();
   } else return false;
 }
 @Override
 public synchronized void start() throws IllegalStateException, IOException {
   if (!mStreaming) {
     configure();
     super.start();
   }
 }
  /** Stops the stream. */
  public synchronized void stop() {
    if (mStreaming) {

      Log.d(TAG, "Interrupting threads...");
      mThread.interrupt();
      mAudioRecord.stop();
      mAudioRecord.release();
      mAudioRecord = null;

      super.stop();
    }
  }
  public synchronized void configure() throws IllegalStateException, IOException {
    super.configure();
    mQuality = mRequestedQuality.clone();

    // Checks if the user has supplied an exotic sampling rate
    int i = 0;
    for (; i < AUDIO_SAMPLING_RATES.length; i++) {
      if (AUDIO_SAMPLING_RATES[i] == mQuality.samplingRate) {
        mSamplingRateIndex = i;
        break;
      }
    }
    // If he did, we force a reasonable one: 16 kHz
    if (i > 12) mQuality.samplingRate = 16000;

    if (mMode != mRequestedMode || mPacketizer == null) {
      mMode = mRequestedMode;

      mPacketizer = new AACLATMPacketizer();

      mPacketizer.setDestination(mDestination, mRtpPort, mRtcpPort);
      mPacketizer.getRtpSocket().setOutputStream(mOutputStream, mChannelIdentifier);
    }

    mProfile = 2; // AAC LC
    mChannel = 1;
    mConfig = mProfile << 11 | mSamplingRateIndex << 7 | mChannel << 3;

    mSessionDescription =
        "m=audio "
            + String.valueOf(getDestinationPorts()[0])
            + " RTP/AVP 96\r\n"
            + "a=rtpmap:96 mpeg4-generic/"
            + mQuality.samplingRate
            + "\r\n"
            + "a=fmtp:96 streamtype=5; profile-level-id=15; mode=AAC-hbr; config="
            + Integer.toHexString(mConfig)
            + "; SizeLength=13; IndexLength=3; IndexDeltaLength=3;\r\n";
  }
예제 #5
0
  /**
   * Records a short sample of AAC ADTS from the microphone to find out what the sampling rate
   * really is On some phone indeed, no error will be reported if the sampling rate used differs
   * from the one selected with setAudioSamplingRate
   *
   * @throws IOException
   * @throws IllegalStateException
   */
  private void testADTS() throws IllegalStateException, IOException {

    if (mSettings != null) {
      if (mSettings.contains("aac-" + mSamplingRate)) {
        String[] s = mSettings.getString("aac-" + mSamplingRate, "").split(",");
        mActualSamplingRate = Integer.valueOf(s[0]);
        mConfig = Integer.valueOf(s[1]);
        mChannel = Integer.valueOf(s[2]);
        return;
      }
    }

    final String TESTFILE =
        Environment.getExternalStorageDirectory().getPath() + "/spydroid-test.adts";

    if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
      throw new IllegalStateException("No external storage or external storage not ready !");
    }

    // The structure of an ADTS packet is described here:
    // http://wiki.multimedia.cx/index.php?title=ADTS

    // ADTS header is 7 or 9 bytes long
    byte[] buffer = new byte[9];

    // That means the H264Stream will behave as a regular MediaRecorder object
    // it will not start the packetizer thread and can be used to save video in a file
    setMode(MODE_DEFAULT);
    mMediaRecorder.setOutputFile(TESTFILE);

    super.prepare();
    start();

    // We record for 1 sec
    // TODO: use the MediaRecorder.OnInfoListener
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
    }

    stop();
    setMode(MODE_STREAMING);

    File file = new File(TESTFILE);
    RandomAccessFile raf = new RandomAccessFile(file, "r");

    // ADTS packets start with a sync word: 12bits set to 1
    while (true) {
      if ((raf.readByte() & 0xFF) == 0xFF) {
        buffer[0] = raf.readByte();
        if ((buffer[0] & 0xF0) == 0xF0) break;
      }
    }

    raf.read(buffer, 1, 5);

    mSamplingRateIndex = (buffer[1] & 0x3C) >> 2;
    mProfile = ((buffer[1] & 0xC0) >> 6) + 1;
    mChannel = (buffer[1] & 0x01) << 2 | (buffer[2] & 0xC0) >> 6;
    mActualSamplingRate = sADTSSamplingRates[mSamplingRateIndex];

    // 5 bits for the object type / 4 bits for the sampling rate / 4 bits for the channel / padding
    mConfig = mProfile << 11 | mSamplingRateIndex << 7 | mChannel << 3;

    Log.i(TAG, "MPEG VERSION: " + ((buffer[0] & 0x08) >> 3));
    Log.i(TAG, "PROTECTION: " + (buffer[0] & 0x01));
    Log.i(TAG, "PROFILE: " + sAudioObjectTypes[mProfile]);
    Log.i(TAG, "SAMPLING FREQUENCY: " + mActualSamplingRate);
    Log.i(TAG, "CHANNEL: " + mChannel);

    raf.close();

    if (mSettings != null) {
      Editor editor = mSettings.edit();
      editor.putString(
          "aac-" + mSamplingRate, mActualSamplingRate + "," + mConfig + "," + mChannel);
      editor.commit();
    }

    if (!file.delete()) Log.e(TAG, "Temp file could not be erased");
  }
예제 #6
0
 public void prepare() throws IllegalStateException, IOException {
   testADTS();
   ((AACADTSPacketizer) mPacketizer).setSamplingRate(mActualSamplingRate);
   super.prepare();
 }