[vlc-devel] [PATCH 2/2] mediacodec: handle vc1/h264/hevc opening if there is no extradata
Thomas Guillem
thomas at gllm.fr
Tue Apr 21 19:04:38 CEST 2015
For h264/vc1: do a delayed opening from DecodeVideo if there is no extradata in
OpenDecoder.
For hevc: abort mediacodec if there is no extradata. This a temporary
workaround waiting for a better hevc packetizer.
Fixes #14429
---
modules/codec/omxil/android_mediacodec.c | 177 +++++++++++++++++++++++--------
1 file changed, 135 insertions(+), 42 deletions(-)
diff --git a/modules/codec/omxil/android_mediacodec.c b/modules/codec/omxil/android_mediacodec.c
index 5d78953..6314107 100644
--- a/modules/codec/omxil/android_mediacodec.c
+++ b/modules/codec/omxil/android_mediacodec.c
@@ -29,6 +29,7 @@
#include <jni.h>
#include <stdint.h>
+#include <assert.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
@@ -264,6 +265,7 @@ static const struct member members[] = {
*****************************************************************************/
static int OpenDecoder(vlc_object_t *);
static void CloseDecoder(vlc_object_t *);
+static void CloseMediaCodec(decoder_t *p_dec, JNIEnv *env);
static picture_t *DecodeVideo(decoder_t *, block_t **);
@@ -390,17 +392,14 @@ end:
}
/*****************************************************************************
- * OpenDecoder: Create the decoder instance
+ * OpenMediaCodec: Create the mediacodec instance
*****************************************************************************/
-static int OpenDecoder(vlc_object_t *p_this)
+static int OpenMediaCodec(decoder_t *p_dec, JNIEnv* env)
{
- decoder_t *p_dec = (decoder_t*)p_this;
- decoder_sys_t *p_sys;
-
- if (p_dec->fmt_in.i_cat != VIDEO_ES && !p_dec->b_force)
- return VLC_EGENERIC;
-
+ decoder_sys_t *p_sys = p_dec->p_sys;
const char *mime = NULL;
+ size_t fmt_profile = 0;
+
switch (p_dec->fmt_in.i_codec) {
case VLC_CODEC_HEVC: mime = "video/hevc"; break;
case VLC_CODEC_H264: mime = "video/avc"; break;
@@ -411,32 +410,12 @@ static int OpenDecoder(vlc_object_t *p_this)
case VLC_CODEC_VP8: mime = "video/x-vnd.on2.vp8"; break;
case VLC_CODEC_VP9: mime = "video/x-vnd.on2.vp9"; break;
default:
- msg_Dbg(p_dec, "codec %4.4s not supported", (char *)&p_dec->fmt_in.i_codec);
- return VLC_EGENERIC;
+ vlc_assert_unreachable();
}
- size_t fmt_profile = 0;
if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
h264_get_profile_level(&p_dec->fmt_in, &fmt_profile, NULL, NULL);
- /* Allocate the memory needed to store the decoder's structure */
- if ((p_dec->p_sys = p_sys = calloc(1, sizeof(*p_sys))) == NULL)
- return VLC_ENOMEM;
-
- p_dec->pf_decode_video = DecodeVideo;
-
- p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
- p_dec->fmt_out.video = p_dec->fmt_in.video;
- p_dec->fmt_out.audio = p_dec->fmt_in.audio;
- p_dec->b_need_packetized = true;
-
- JNIEnv* env = NULL;
- if (!(env = jni_get_env(THREAD_NAME)))
- goto error;
-
- if (!InitJNIFields(p_dec, env))
- goto error;
-
int num_codecs = (*env)->CallStaticIntMethod(env, jfields.media_codec_list_class,
jfields.get_codec_count);
jobject codec_name = NULL;
@@ -671,51 +650,145 @@ loopclean:
return VLC_SUCCESS;
error:
- CloseDecoder(p_this);
+ CloseMediaCodec(p_dec, env);
return VLC_EGENERIC;
}
-static void CloseDecoder(vlc_object_t *p_this)
+/*****************************************************************************
+ * CloseMediaCodec: Close the mediacodec instance
+ *****************************************************************************/
+static void CloseMediaCodec(decoder_t *p_dec, JNIEnv *env)
{
- decoder_t *p_dec = (decoder_t *)p_this;
decoder_sys_t *p_sys = p_dec->p_sys;
- JNIEnv *env = NULL;
if (!p_sys)
return;
+ free(p_sys->name);
+ p_sys->name = NULL;
+
/* Invalidate all pictures that are currently in flight in order
* to prevent the vout from using destroyed output buffers. */
- if (p_sys->direct_rendering)
+ if (p_sys->direct_rendering) {
InvalidateAllPictures(p_dec);
+ p_sys->direct_rendering = false;
+ }
- if (!(env = jni_get_env(THREAD_NAME)))
- goto cleanup;
-
- if (p_sys->input_buffers)
+ if (p_sys->input_buffers) {
(*env)->DeleteGlobalRef(env, p_sys->input_buffers);
- if (p_sys->output_buffers)
+ p_sys->input_buffers = NULL;
+ }
+ if (p_sys->output_buffers) {
(*env)->DeleteGlobalRef(env, p_sys->output_buffers);
+ p_sys->output_buffers = NULL;
+ }
if (p_sys->codec) {
if (p_sys->started)
{
(*env)->CallVoidMethod(env, p_sys->codec, jfields.stop);
if (CHECK_EXCEPTION())
msg_Err(p_dec, "Exception in MediaCodec.stop");
+ p_sys->started = false;
}
if (p_sys->allocated)
{
(*env)->CallVoidMethod(env, p_sys->codec, jfields.release);
if (CHECK_EXCEPTION())
msg_Err(p_dec, "Exception in MediaCodec.release");
+ p_sys->allocated = false;
}
(*env)->DeleteGlobalRef(env, p_sys->codec);
+ p_sys->codec = NULL;
}
- if (p_sys->buffer_info)
+ if (p_sys->buffer_info) {
(*env)->DeleteGlobalRef(env, p_sys->buffer_info);
+ p_sys->buffer_info = NULL;
+ }
+}
+
+/*****************************************************************************
+ * OpenDecoder: Create the decoder instance
+ *****************************************************************************/
+static int OpenDecoder(vlc_object_t *p_this)
+{
+ decoder_t *p_dec = (decoder_t*)p_this;
+ JNIEnv* env = NULL;
+
+ if (p_dec->fmt_in.i_cat != VIDEO_ES && !p_dec->b_force)
+ return VLC_EGENERIC;
+
+ switch (p_dec->fmt_in.i_codec) {
+ case VLC_CODEC_HEVC:
+ case VLC_CODEC_H264:
+ case VLC_CODEC_H263:
+ case VLC_CODEC_MP4V:
+ case VLC_CODEC_WMV3:
+ case VLC_CODEC_VC1:
+ case VLC_CODEC_VP8:
+ case VLC_CODEC_VP9:
+ break;
+ default:
+ msg_Dbg(p_dec, "codec %4.4s not supported", (char *)&p_dec->fmt_in.i_codec);
+ return VLC_EGENERIC;
+ }
+
+ /* Allocate the memory needed to store the decoder's structure */
+ if ((p_dec->p_sys = calloc(1, sizeof(*p_dec->p_sys))) == NULL)
+ return VLC_ENOMEM;
+
+ p_dec->pf_decode_video = DecodeVideo;
+
+ p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
+ p_dec->fmt_out.video = p_dec->fmt_in.video;
+ p_dec->fmt_out.audio = p_dec->fmt_in.audio;
+ p_dec->b_need_packetized = true;
+
+ if (!(env = jni_get_env(THREAD_NAME)))
+ goto error;
+
+ if (!InitJNIFields(p_dec, env))
+ goto error;
+
+ if (!p_dec->fmt_in.i_extra
+ && (p_dec->fmt_in.i_codec == VLC_CODEC_VC1
+ || p_dec->fmt_in.i_codec == VLC_CODEC_H264
+ || p_dec->fmt_in.i_codec == VLC_CODEC_HEVC))
+ {
+ /* TODO:
+ * remove this workaround when hevc packetizer can send extradata */
+ if(p_dec->fmt_in.i_codec == VLC_CODEC_HEVC)
+ {
+ msg_Err(p_dec, "Can't open hevc without extradata");
+ return VLC_EGENERIC;
+ }
+ msg_Warn(p_dec, "waiting for extra data for codec %4.4s",
+ p_dec->fmt_in.i_extra);
+ return VLC_SUCCESS;
+ } else
+ return OpenMediaCodec(p_dec, env);
+
+ error:
+ CloseDecoder(p_this);
+ return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * CloseDecoder: Close the decoder instance
+ *****************************************************************************/
+static void CloseDecoder(vlc_object_t *p_this)
+{
+ decoder_t *p_dec = (decoder_t *)p_this;
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ JNIEnv *env = NULL;
+
+ if (!p_sys)
+ return;
+
+ if ((env = jni_get_env(THREAD_NAME)))
+ CloseMediaCodec(p_dec, env);
+ else
+ msg_Warn(p_dec, "Can't get a JNIEnv, can't close mediacodec !");
-cleanup:
- free(p_sys->name);
ArchitectureSpecificCopyHooksDestroy(p_sys->pixel_format, &p_sys->architecture_specific_data);
free(p_sys->pp_inflight_pictures);
if (p_sys->timestamp_fifo)
@@ -1032,6 +1105,26 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
if (!(env = jni_get_env(THREAD_NAME)))
goto endclean;
+ /* try delayed opening if there is a new extra data */
+ if (!p_sys->codec && p_dec->fmt_in.i_extra)
+ {
+ if (OpenMediaCodec(p_dec, env) != VLC_SUCCESS)
+ {
+ p_sys->error_state = true;
+ goto endclean;
+ }
+ }
+
+ if (!p_sys->codec)
+ {
+ if (p_block)
+ {
+ block_Release(p_block);
+ *pp_block = NULL;
+ }
+ return NULL;
+ }
+
if (p_block && p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) {
block_Release(p_block);
*pp_block = NULL;
--
2.1.3
More information about the vlc-devel
mailing list