[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:06:17 CEST 2015
On Tue, Apr 21, 2015, at 19:04, Thomas Guillem wrote:
> 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.
Same patch, but I added a temporary workaround for HEVC.
>
> 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