MediaCodec: add reset() + documentation fixes
Bug: 12034929
Change-Id: I38f89a2e4c41e0ceb3fdae4522b9c04f6c43a4f1
diff --git a/api/current.txt b/api/current.txt
index 2e25e33..9c09f14 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14427,6 +14427,7 @@
method public final void release();
method public final void releaseOutputBuffer(int, boolean);
method public final void releaseOutputBuffer(int, long);
+ method public final void reset();
method public void setCallback(android.media.MediaCodec.Callback);
method public final void setParameters(android.os.Bundle);
method public final void setVideoScalingMode(int);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 4abcb81..f84c383 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -136,14 +136,17 @@
* cycle is necessary.
*
* <p> During its life, a codec conceptually exists in one of the following states:
- * Initialized, Configured, Executing, Uninitialized, (omitting transitory states
+ * Initialized, Configured, Executing, Error, Uninitialized, (omitting transitory states
* between them). When created by one of the factory methods,
* the codec is in the Initialized state; {@link #configure} brings it to the
* Configured state; {@link #start} brings it to the Executing state.
* In the Executing state, decoding or encoding occurs through the buffer queue
* manipulation described above. The method {@link #stop}
* returns the codec to the Initialized state, whereupon it may be configured again,
- * and {@link #release} brings the codec to the terminal Uninitialized state.
+ * and {@link #release} brings the codec to the terminal Uninitialized state. When
+ * a codec error occurs, the codec moves to the Error state. Use {@link #reset} to
+ * bring the codec back to the Initialized state, or {@link #release} to move it
+ * to the Uninitialized state.
*
* <p> The factory methods
* {@link #createByCodecName},
@@ -170,7 +173,8 @@
* then resources are temporarily unavailable and the method may be retried at a later time.
* If both {@link MediaCodec.CodecException#isRecoverable}
* and {@link MediaCodec.CodecException#isTransient} return false,
- * then the {@link MediaCodec.CodecException} is fatal and the codec must be released.
+ * then the {@link MediaCodec.CodecException} is fatal and the codec must be
+ * {@link #reset reset} or {@link #release released}.
* Both {@link MediaCodec.CodecException#isRecoverable} and
* {@link MediaCodec.CodecException#isTransient} do not return true at the same time.
*/
@@ -429,6 +433,23 @@
}
/**
+ * Returns the codec to its initial (Initialized) state.
+ *
+ * Call this if an {@link MediaCodec.CodecException#isRecoverable unrecoverable}
+ * error has occured to reset the codec to its initial state after creation.
+ *
+ * @throws CodecException if an unrecoverable error has occured and the codec
+ * could not be reset.
+ * @throws IllegalStateException if in the Uninitialized state.
+ */
+ public final void reset() {
+ freeAllTrackedBuffers(); // free buffers first
+ native_reset();
+ }
+
+ private native final void native_reset();
+
+ /**
* Make sure you call this when you're done to free up any opened
* component instance instead of relying on the garbage collector
* to do this for you at some point in the future.
@@ -646,9 +667,10 @@
/**
* After filling a range of the input buffer at the specified index
* submit it to the component. Once an input buffer is queued to
- * the codec, it MUST not be used until it is later retrieved by
- * {#getInputBuffer} in response to a {#dequeueInputBuffer}
- * response.
+ * the codec, it MUST NOT be used until it is later retrieved by
+ * {@link #getInputBuffer} in response to a {@link #dequeueInputBuffer}
+ * return value or a {@link Callback#onInputBufferAvailable}
+ * callback.
* <p>
* Many decoders require the actual compressed data stream to be
* preceded by "codec specific data", i.e. setup data used to initialize
@@ -905,9 +927,10 @@
* the codec. If you previously specified a surface when configuring this
* video decoder you can optionally render the buffer.
*
- * Once an output buffer is released to the codec, it MUST not
- * be used until it is later retrieved by {#getOutputBuffer} in
- * response to a {#dequeueOutputBuffer} response
+ * Once an output buffer is released to the codec, it MUST NOT
+ * be used until it is later retrieved by {@link #getOutputBuffer} in response
+ * to a {@link #dequeueOutputBuffer} return value or a
+ * {@link Callback#onOutputBufferAvailable} callback.
*
* @param index The index of a client-owned output buffer previously returned
* from a call to {@link #dequeueOutputBuffer}.
@@ -961,9 +984,10 @@
* </td></tr>
* </table>
*
- * Once an output buffer is released to the codec, it MUST not
- * be used until it is later retrieved by {#getOutputBuffer} in
- * response to a {#dequeueOutputBuffer} response
+ * Once an output buffer is released to the codec, it MUST NOT
+ * be used until it is later retrieved by {@link #getOutputBuffer} in response
+ * to a {@link #dequeueOutputBuffer} return value or a
+ * {@link Callback#onOutputBufferAvailable} callback.
*
* @param index The index of a client-owned output buffer previously returned
* from a call to {@link #dequeueOutputBuffer}.
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index b7294b8..04ff098 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -197,6 +197,10 @@
return mCodec->flush();
}
+status_t JMediaCodec::reset() {
+ return mCodec->reset();
+}
+
status_t JMediaCodec::queueInputBuffer(
size_t index,
size_t offset, size_t size, int64_t timeUs, uint32_t flags,
@@ -854,6 +858,26 @@
throwExceptionAsNecessary(env, err);
}
+static void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
+ ALOGV("android_media_MediaCodec_reset");
+
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL) {
+ // should never be here
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+
+ status_t err = codec->reset();
+ if (err != OK) {
+ // treat all errors as fatal for now, though resource not available
+ // errors could be treated as transient.
+ err = 0x80000000;
+ }
+ throwExceptionAsNecessary(env, err);
+}
+
static void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
ALOGV("android_media_MediaCodec_flush");
@@ -1398,6 +1422,8 @@
static JNINativeMethod gMethods[] = {
{ "native_release", "()V", (void *)android_media_MediaCodec_release },
+ { "native_reset", "()V", (void *)android_media_MediaCodec_reset },
+
{ "native_setCallback",
"(Landroid/media/MediaCodec$Callback;)V",
(void *)android_media_MediaCodec_native_setCallback },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 2e650e3..dbccb0f 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -56,6 +56,7 @@
status_t start();
status_t stop();
+ status_t reset();
status_t flush();