[FFmpeg-devel] avcodec/mediacodec: add av_mediacodec_render_buffer_at_time()

Submitted by Aman Gupta on Aug. 1, 2018, 1:34 a.m.

Details

Message ID 20180801013415.11040-1-ffmpeg@tmm1.net
State Accepted
Headers show

Commit Message

Aman Gupta Aug. 1, 2018, 1:34 a.m.
From: Aman Gupta <aman@tmm1.net>

The existing av_mediacodec_release_buffer allows the user to render
or discard the Surface-backed frame. This new method allows the user
to control exactly when the frame will be rendered to it's SurfaceView.

Available since Android API 21.

Signed-off-by: Aman Gupta <aman@tmm1.net>
---
 doc/APIchanges                  |  3 +++
 libavcodec/mediacodec.c         | 21 +++++++++++++++++++++
 libavcodec/mediacodec.h         | 13 +++++++++++++
 libavcodec/mediacodec_wrapper.c |  2 +-
 libavcodec/version.h            |  2 +-
 5 files changed, 39 insertions(+), 2 deletions(-)

Comments

Aman Gupta Oct. 12, 2018, 3:53 a.m.
On Tue, Jul 31, 2018 at 6:34 PM Aman Gupta <ffmpeg@tmm1.net> wrote:

> From: Aman Gupta <aman@tmm1.net>
>
> The existing av_mediacodec_release_buffer allows the user to render
> or discard the Surface-backed frame. This new method allows the user
> to control exactly when the frame will be rendered to it's SurfaceView.
>
> Available since Android API 21.
>
> Signed-off-by: Aman Gupta <aman@tmm1.net>
> ---
>  doc/APIchanges                  |  3 +++
>  libavcodec/mediacodec.c         | 21 +++++++++++++++++++++
>  libavcodec/mediacodec.h         | 13 +++++++++++++
>  libavcodec/mediacodec_wrapper.c |  2 +-
>  libavcodec/version.h            |  2 +-
>  5 files changed, 39 insertions(+), 2 deletions(-)
>
> diff --git a/doc/APIchanges b/doc/APIchanges
> index efe15ba4e0..62394fd837 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -15,6 +15,9 @@ libavutil:     2017-10-21
>
>  API changes, most recent first:
>
> +2018-08-01 - xxxxxxxxxx - lavc 58.23.100 - mediacodec.h
> +  Add av_mediacodec_render_buffer_at_time().
> +
>  2018-05-xx - xxxxxxxxxx - lavf 58.15.100 - avformat.h
>    Add pmt_version field to AVProgram
>
> diff --git a/libavcodec/mediacodec.c b/libavcodec/mediacodec.c
> index b0aae43a87..aa14624fd0 100644
> --- a/libavcodec/mediacodec.c
> +++ b/libavcodec/mediacodec.c
> @@ -102,6 +102,22 @@ int av_mediacodec_release_buffer(AVMediaCodecBuffer
> *buffer, int render)
>      return 0;
>  }
>
> +int av_mediacodec_render_buffer_at_time(AVMediaCodecBuffer *buffer,
> int64_t time)
> +{
> +    MediaCodecDecContext *ctx = buffer->ctx;
> +    int released = atomic_fetch_add(&buffer->released, 1);
> +
> +    if (!released && (ctx->delay_flush || buffer->serial ==
> atomic_load(&ctx->serial))) {
> +        atomic_fetch_sub(&ctx->hw_buffer_count, 1);
> +        av_log(ctx->avctx, AV_LOG_DEBUG,
> +               "Rendering output buffer %zd (%p) ts=%"PRId64" with
> time=%"PRId64" [%d pending]\n",
> +               buffer->index, buffer, buffer->pts, time,
> atomic_load(&ctx->hw_buffer_count));
> +        return ff_AMediaCodec_releaseOutputBufferAtTime(ctx->codec,
> buffer->index, time);
> +    }
> +
> +    return 0;
> +}
> +
>  #else
>
>  #include <stdlib.h>
> @@ -125,4 +141,9 @@ int av_mediacodec_release_buffer(AVMediaCodecBuffer
> *buffer, int render)
>      return AVERROR(ENOSYS);
>  }
>
> +int av_mediacodec_render_buffer_at_time(AVMediaCodecBuffer *buffer,
> int64_t time)
> +{
> +    return AVERROR(ENOSYS);
> +}
> +
>  #endif
> diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
> index 5606d24a1e..4c8545df03 100644
> --- a/libavcodec/mediacodec.h
> +++ b/libavcodec/mediacodec.h
> @@ -85,4 +85,17 @@ typedef struct MediaCodecBuffer AVMediaCodecBuffer;
>   */
>  int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render);
>
> +/**
> + * Release a MediaCodec buffer and render it at the given time to the
> surface
> + * that is associated with the decoder. The timestamp must be within one
> second
> + * of the current java/lang/System#nanoTime() (which is implemented using
> + * CLOCK_MONOTONIC on Android). See the Android MediaCodec documentation
> + * of android/media/MediaCodec#releaseOutputBuffer(int,long) for more
> details.
> + *
> + * @param buffer the buffer to render
> + * @param time timestamp in nanoseconds of when to render the buffer
> + * @return 0 on success, < 0 otherwise
> + */
> +int av_mediacodec_render_buffer_at_time(AVMediaCodecBuffer *buffer,
> int64_t time);
> +
>  #endif /* AVCODEC_MEDIACODEC_H */
> diff --git a/libavcodec/mediacodec_wrapper.c
> b/libavcodec/mediacodec_wrapper.c
> index c47c2c9a41..a024e3bdb1 100644
> --- a/libavcodec/mediacodec_wrapper.c
> +++ b/libavcodec/mediacodec_wrapper.c
> @@ -1432,7 +1432,7 @@ int
> ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, i
>
>      JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
>
> -    (*env)->CallVoidMethod(env, codec->object,
> codec->jfields.release_output_buffer_at_time_id, (jint)idx, timestampNs);
> +    (*env)->CallVoidMethod(env, codec->object,
> codec->jfields.release_output_buffer_at_time_id, (jint)idx,
> (jlong)timestampNs);
>      if (ff_jni_exception_check(env, 1, codec) < 0) {
>          ret = AVERROR_EXTERNAL;
>          goto fail;
> diff --git a/libavcodec/version.h b/libavcodec/version.h
> index 3f0d98efdf..a91e5f01e6 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -28,7 +28,7 @@
>  #include "libavutil/version.h"
>
>  #define LIBAVCODEC_VERSION_MAJOR  58
> -#define LIBAVCODEC_VERSION_MINOR  22
> +#define LIBAVCODEC_VERSION_MINOR  23
>  #define LIBAVCODEC_VERSION_MICRO 100
>
>  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
>

Updated diff to use 58.33.100 and pushed to master.


> --
> 2.18.0
>
>

Patch hide | download patch | download mbox

diff --git a/doc/APIchanges b/doc/APIchanges
index efe15ba4e0..62394fd837 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,9 @@  libavutil:     2017-10-21
 
 API changes, most recent first:
 
+2018-08-01 - xxxxxxxxxx - lavc 58.23.100 - mediacodec.h
+  Add av_mediacodec_render_buffer_at_time().
+
 2018-05-xx - xxxxxxxxxx - lavf 58.15.100 - avformat.h
   Add pmt_version field to AVProgram
 
diff --git a/libavcodec/mediacodec.c b/libavcodec/mediacodec.c
index b0aae43a87..aa14624fd0 100644
--- a/libavcodec/mediacodec.c
+++ b/libavcodec/mediacodec.c
@@ -102,6 +102,22 @@  int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render)
     return 0;
 }
 
+int av_mediacodec_render_buffer_at_time(AVMediaCodecBuffer *buffer, int64_t time)
+{
+    MediaCodecDecContext *ctx = buffer->ctx;
+    int released = atomic_fetch_add(&buffer->released, 1);
+
+    if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) {
+        atomic_fetch_sub(&ctx->hw_buffer_count, 1);
+        av_log(ctx->avctx, AV_LOG_DEBUG,
+               "Rendering output buffer %zd (%p) ts=%"PRId64" with time=%"PRId64" [%d pending]\n",
+               buffer->index, buffer, buffer->pts, time, atomic_load(&ctx->hw_buffer_count));
+        return ff_AMediaCodec_releaseOutputBufferAtTime(ctx->codec, buffer->index, time);
+    }
+
+    return 0;
+}
+
 #else
 
 #include <stdlib.h>
@@ -125,4 +141,9 @@  int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render)
     return AVERROR(ENOSYS);
 }
 
+int av_mediacodec_render_buffer_at_time(AVMediaCodecBuffer *buffer, int64_t time)
+{
+    return AVERROR(ENOSYS);
+}
+
 #endif
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 5606d24a1e..4c8545df03 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -85,4 +85,17 @@  typedef struct MediaCodecBuffer AVMediaCodecBuffer;
  */
 int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render);
 
+/**
+ * Release a MediaCodec buffer and render it at the given time to the surface
+ * that is associated with the decoder. The timestamp must be within one second
+ * of the current java/lang/System#nanoTime() (which is implemented using
+ * CLOCK_MONOTONIC on Android). See the Android MediaCodec documentation
+ * of android/media/MediaCodec#releaseOutputBuffer(int,long) for more details.
+ *
+ * @param buffer the buffer to render
+ * @param time timestamp in nanoseconds of when to render the buffer
+ * @return 0 on success, < 0 otherwise
+ */
+int av_mediacodec_render_buffer_at_time(AVMediaCodecBuffer *buffer, int64_t time);
+
 #endif /* AVCODEC_MEDIACODEC_H */
diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c
index c47c2c9a41..a024e3bdb1 100644
--- a/libavcodec/mediacodec_wrapper.c
+++ b/libavcodec/mediacodec_wrapper.c
@@ -1432,7 +1432,7 @@  int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, i
 
     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
 
-    (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, (jint)idx, timestampNs);
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, (jint)idx, (jlong)timestampNs);
     if (ff_jni_exception_check(env, 1, codec) < 0) {
         ret = AVERROR_EXTERNAL;
         goto fail;
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 3f0d98efdf..a91e5f01e6 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,7 +28,7 @@ 
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR  58
-#define LIBAVCODEC_VERSION_MINOR  22
+#define LIBAVCODEC_VERSION_MINOR  23
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \