Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d89cb1eb authored by Andy Hung's avatar Andy Hung Committed by Android (Google) Code Review
Browse files

Merge "Add AudioRecord timestamps"

parents 6e2c6ccd 0ad99c05
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -19874,6 +19874,7 @@ package android.media {
    method public android.media.AudioDeviceInfo getRoutedDevice();
    method public int getSampleRate();
    method public int getState();
    method public int getTimestamp(android.media.AudioTimestamp, int);
    method public int read(byte[], int, int);
    method public int read(byte[], int, int, int);
    method public int read(short[], int, int);
@@ -19945,6 +19946,8 @@ package android.media {
  public final class AudioTimestamp {
    ctor public AudioTimestamp();
    field public static final int TIMEBASE_BOOTTIME = 1; // 0x1
    field public static final int TIMEBASE_MONOTONIC = 0; // 0x0
    field public long framePosition;
    field public long nanoTime;
  }
+3 −0
Original line number Diff line number Diff line
@@ -21140,6 +21140,7 @@ package android.media {
    method public android.media.AudioDeviceInfo getRoutedDevice();
    method public int getSampleRate();
    method public int getState();
    method public int getTimestamp(android.media.AudioTimestamp, int);
    method public int read(byte[], int, int);
    method public int read(byte[], int, int, int);
    method public int read(short[], int, int);
@@ -21213,6 +21214,8 @@ package android.media {
  public final class AudioTimestamp {
    ctor public AudioTimestamp();
    field public static final int TIMEBASE_BOOTTIME = 1; // 0x1
    field public static final int TIMEBASE_MONOTONIC = 0; // 0x0
    field public long framePosition;
    field public long nanoTime;
  }
+3 −0
Original line number Diff line number Diff line
@@ -19883,6 +19883,7 @@ package android.media {
    method public android.media.AudioDeviceInfo getRoutedDevice();
    method public int getSampleRate();
    method public int getState();
    method public int getTimestamp(android.media.AudioTimestamp, int);
    method public int read(byte[], int, int);
    method public int read(byte[], int, int, int);
    method public int read(short[], int, int);
@@ -19954,6 +19955,8 @@ package android.media {
  public final class AudioTimestamp {
    ctor public AudioTimestamp();
    field public static final int TIMEBASE_BOOTTIME = 1; // 0x1
    field public static final int TIMEBASE_MONOTONIC = 0; // 0x0
    field public long framePosition;
    field public long nanoTime;
  }
+46 −0
Original line number Diff line number Diff line
@@ -54,6 +54,10 @@ struct audio_attributes_fields_t {
};
static audio_attributes_fields_t javaAudioAttrFields;
static audio_record_fields_t     javaAudioRecordFields;
static struct {
    jfieldID  fieldFramePosition;     // AudioTimestamp.framePosition
    jfieldID  fieldNanoTime;          // AudioTimestamp.nanoTime
} javaAudioTimestampFields;

struct audiorecord_callback_cookie {
    jclass      audioRecord_class;
@@ -678,7 +682,40 @@ static void android_media_AudioRecord_disableDeviceCallback(
    }
}

// ----------------------------------------------------------------------------
static jint android_media_AudioRecord_get_timestamp(JNIEnv *env, jobject thiz,
        jobject timestamp, jint timebase) {
    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);

    if (lpRecorder == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioRecord pointer for getTimestamp()");
        return (jint)AUDIO_JAVA_ERROR;
    }

    // TODO Enable.
#if 0
    // get the record timestamp
    ExtendedTimestamp ts;
    jint status = nativeToJavaStatus(lpRecorder->getExtendedTimestamp(&ts));

    if (status == AUDIO_JAVA_SUCCESS) {
        // set the data
        int64_t position, time;

        status = nativeToJavaStatus(ts.getBestTimestamp(&position, &time, timebase));
        if (status == AUDIO_JAVA_SUCCESS) {
            env->SetLongField(
                    timestamp, javaAudioTimestampFields.fieldFramePosition, position);
            env->SetLongField(
                    timestamp, javaAudioTimestampFields.fieldNanoTime, time);
        }
    }
    return status;
#else
    return (jint)AUDIO_JAVA_INVALID_OPERATION;
#endif
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@@ -716,6 +753,8 @@ static const JNINativeMethod gMethods[] = {
    {"native_enableDeviceCallback", "()V", (void *)android_media_AudioRecord_enableDeviceCallback},
    {"native_disableDeviceCallback", "()V",
                                        (void *)android_media_AudioRecord_disableDeviceCallback},
    {"native_get_timestamp", "(Landroid/media/AudioTimestamp;I)I",
                                       (void *)android_media_AudioRecord_get_timestamp},
};

// field names found in android/media/AudioRecord.java
@@ -758,6 +797,13 @@ int register_android_media_AudioRecord(JNIEnv *env)
    javaAudioAttrFields.fieldFormattedTags = GetFieldIDOrDie(env,
            audioAttrClass, "mFormattedTags", "Ljava/lang/String;");

    // Get the RecordTimestamp class and fields
    jclass audioTimestampClass = FindClassOrDie(env, "android/media/AudioTimestamp");
    javaAudioTimestampFields.fieldFramePosition =
            GetFieldIDOrDie(env, audioTimestampClass, "framePosition", "J");
    javaAudioTimestampFields.fieldNanoTime =
            GetFieldIDOrDie(env, audioTimestampClass, "nanoTime", "J");

    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}

+30 −0
Original line number Diff line number Diff line
@@ -825,6 +825,33 @@ public class AudioRecord implements AudioRouting
        return native_get_pos_update_period();
    }

    /**
     * Poll for an {@link AudioTimestamp} on demand.
     * <p>
     * The AudioTimestamp reflects the frame delivery information at
     * the earliest point available in the capture pipeline.
     * <p>
     * Calling {@link #startRecording()} following a {@link #stop()} will reset
     * the frame count to 0.
     *
     * @param timestamp a reference to a non-null AudioTimestamp instance.
     * @param timebase one of
     *        {@link AudioTimestamp#TIMEBASE_BOOTTIME AudioTimestamp.TIMEBASE_BOOTTIME} or
     *        {@link AudioTimestamp#TIMEBASE_MONOTONIC AudioTimestamp.TIMEBASE_MONOTONIC}.
     * @return {@link #SUCCESS} if a timestamp is available,
     *         or {@link #ERROR_INVALID_OPERATION} if a timestamp not available.
     */
     public int getTimestamp(@NonNull AudioTimestamp timestamp,
             @AudioTimestamp.Timebase int timebase)
     {
         if (timestamp == null ||
                 (timebase != AudioTimestamp.TIMEBASE_BOOTTIME
                 && timebase != AudioTimestamp.TIMEBASE_MONOTONIC)) {
             throw new IllegalArgumentException();
         }
         return native_get_timestamp(timestamp, timebase);
     }

    /**
     * Returns the minimum buffer size required for the successful creation of an AudioRecord
     * object, in byte units.
@@ -1709,6 +1736,9 @@ public class AudioRecord implements AudioRouting
    private native final void native_enableDeviceCallback();
    private native final void native_disableDeviceCallback();

    private native final int native_get_timestamp(@NonNull AudioTimestamp timestamp,
            @AudioTimestamp.Timebase int timebase);

    //---------------------------------------------------------
    // Utility methods
    //------------------
Loading