[vlc-devel] [PATCH 6/6] mediacodec: add NDK submodule

Jean-Baptiste Kempf jb at videolan.org
Tue May 19 21:49:32 CEST 2015


LGTM.

On 19 May, Thomas Guillem wrote :
> ---
>  modules/codec/Makefile.am            |   4 +
>  modules/codec/omxil/mediacodec_ndk.c | 554 +++++++++++++++++++++++++++++++++++
>  2 files changed, 558 insertions(+)
>  create mode 100644 modules/codec/omxil/mediacodec_ndk.c
> 
> diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
> index a0a34d9..8683080 100644
> --- a/modules/codec/Makefile.am
> +++ b/modules/codec/Makefile.am
> @@ -406,11 +406,15 @@ libmediacodec_plugin_la_SOURCES = codec/omxil/mediacodec.c codec/omxil/mediacode
>  libmediacodec_jni_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/codec/omxil
>  libmediacodec_jni_plugin_la_SOURCES = codec/omxil/mediacodec_jni.c codec/omxil/mediacodec.h
>  
> +libmediacodec_ndk_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/codec/omxil
> +libmediacodec_ndk_plugin_la_SOURCES = codec/omxil/mediacodec_ndk.c codec/omxil/mediacodec.h
> +
>  codec_LTLIBRARIES += $(LTLIBomxil) $(LTLIBomxil_vout)
>  EXTRA_LTLIBRARIES += libomxil_plugin.la libomxil_vout_plugin.la
>  if HAVE_ANDROID
>  codec_LTLIBRARIES += libiomx_plugin.la libmediacodec_plugin.la
>  codec_LTLIBRARIES += libmediacodec_jni_plugin.la
> +codec_LTLIBRARIES += libmediacodec_ndk_plugin.la
>  endif
>  
>  
> diff --git a/modules/codec/omxil/mediacodec_ndk.c b/modules/codec/omxil/mediacodec_ndk.c
> new file mode 100644
> index 0000000..c25c9f9
> --- /dev/null
> +++ b/modules/codec/omxil/mediacodec_ndk.c
> @@ -0,0 +1,554 @@
> +/*****************************************************************************
> + * mediacodec_ndk.c: Video decoder module using the MediaCodec API via NDK
> + *****************************************************************************
> + * Copyright © 2015 VLC authors and VideoLAN, VideoLabs
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License as published by
> + * the Free Software Foundation; either version 2.1 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program; if not, write to the Free Software Foundation,
> + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
> + *****************************************************************************/
> +
> +/*****************************************************************************
> + * Preamble
> + *****************************************************************************/
> +#ifdef HAVE_CONFIG_H
> +# include "config.h"
> +#endif
> +
> +#include <jni.h>
> +#include <dlfcn.h>
> +#include <stdint.h>
> +#include <assert.h>
> +
> +#include <vlc_common.h>
> +#include <vlc_plugin.h>
> +#include <vlc_modules.h>
> +
> +#include <OMX_Core.h>
> +#include <OMX_Component.h>
> +#include "omxil_utils.h"
> +
> +#include "mediacodec.h"
> +#include "../../video_output/android/utils.h"
> +
> +#define THREAD_NAME "mediacodec_ndk"
> +extern JNIEnv *jni_get_env(const char *name);
> +
> +/*****************************************************************************
> + * Symbols Initialisation
> + *****************************************************************************/
> +
> +typedef enum {
> +    AMEDIA_OK = 0,
> +
> +    AMEDIA_ERROR_BASE                  = -10000,
> +    AMEDIA_ERROR_UNKNOWN               = AMEDIA_ERROR_BASE,
> +    AMEDIA_ERROR_MALFORMED             = AMEDIA_ERROR_BASE - 1,
> +    AMEDIA_ERROR_UNSUPPORTED           = AMEDIA_ERROR_BASE - 2,
> +    AMEDIA_ERROR_INVALID_OBJECT        = AMEDIA_ERROR_BASE - 3,
> +    AMEDIA_ERROR_INVALID_PARAMETER     = AMEDIA_ERROR_BASE - 4,
> +
> +    AMEDIA_DRM_ERROR_BASE              = -20000,
> +    AMEDIA_DRM_NOT_PROVISIONED         = AMEDIA_DRM_ERROR_BASE - 1,
> +    AMEDIA_DRM_RESOURCE_BUSY           = AMEDIA_DRM_ERROR_BASE - 2,
> +    AMEDIA_DRM_DEVICE_REVOKED          = AMEDIA_DRM_ERROR_BASE - 3,
> +    AMEDIA_DRM_SHORT_BUFFER            = AMEDIA_DRM_ERROR_BASE - 4,
> +    AMEDIA_DRM_SESSION_NOT_OPENED      = AMEDIA_DRM_ERROR_BASE - 5,
> +    AMEDIA_DRM_TAMPER_DETECTED         = AMEDIA_DRM_ERROR_BASE - 6,
> +    AMEDIA_DRM_VERIFY_FAILED           = AMEDIA_DRM_ERROR_BASE - 7,
> +    AMEDIA_DRM_NEED_KEY                = AMEDIA_DRM_ERROR_BASE - 8,
> +    AMEDIA_DRM_LICENSE_EXPIRED         = AMEDIA_DRM_ERROR_BASE - 9,
> +
> +} media_status_t;
> +
> +struct AMediaCodec;
> +typedef struct AMediaCodec AMediaCodec;
> +
> +struct AMediaCodecBufferInfo {
> +    int32_t offset;
> +    int32_t size;
> +    int64_t presentationTimeUs;
> +    uint32_t flags;
> +};
> +typedef struct AMediaCodecBufferInfo AMediaCodecBufferInfo;
> +
> +struct AMediaFormat;
> +typedef struct AMediaFormat AMediaFormat;
> +
> +enum {
> +    AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM = 4,
> +    AMEDIACODEC_CONFIGURE_FLAG_ENCODE = 1,
> +    AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED = -3,
> +    AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED = -2,
> +    AMEDIACODEC_INFO_TRY_AGAIN_LATER = -1
> +};
> +
> +struct AMediaCrypto;
> +typedef struct AMediaCrypto AMediaCrypto;
> +
> +typedef AMediaCodec* (*pf_AMediaCodec_createDecoderByType)(const char *mime_type);
> +
> +typedef media_status_t (*pf_AMediaCodec_configure)(AMediaCodec*,
> +        const AMediaFormat* format,
> +        ANativeWindow* surface,
> +        AMediaCrypto *crypto,
> +        uint32_t flags);
> +
> +typedef media_status_t (*pf_AMediaCodec_start)(AMediaCodec*);
> +
> +typedef media_status_t (*pf_AMediaCodec_stop)(AMediaCodec*);
> +
> +typedef media_status_t (*pf_AMediaCodec_flush)(AMediaCodec*);
> +
> +typedef media_status_t (*pf_AMediaCodec_delete)(AMediaCodec*);
> +
> +typedef AMediaFormat* (*pf_AMediaCodec_getOutputFormat)(AMediaCodec*);
> +
> +typedef ssize_t (*pf_AMediaCodec_dequeueInputBuffer)(AMediaCodec*,
> +        int64_t timeoutUs);
> +
> +typedef uint8_t* (*pf_AMediaCodec_getInputBuffer)(AMediaCodec*,
> +        size_t idx, size_t *out_size);
> +
> +typedef media_status_t (*pf_AMediaCodec_queueInputBuffer)(AMediaCodec*,
> +        size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags);
> +
> +typedef ssize_t (*pf_AMediaCodec_dequeueOutputBuffer)(AMediaCodec*,
> +        AMediaCodecBufferInfo *info, int64_t timeoutUs);
> +
> +typedef uint8_t* (*pf_AMediaCodec_getOutputBuffer)(AMediaCodec*,
> +        size_t idx, size_t *out_size);
> +
> +typedef media_status_t (*pf_AMediaCodec_releaseOutputBuffer)(AMediaCodec*,
> +        size_t idx, bool render);
> +
> +typedef AMediaFormat *(*pf_AMediaFormat_new)();
> +typedef media_status_t (*pf_AMediaFormat_delete)(AMediaFormat*);
> +
> +typedef void (*pf_AMediaFormat_setString)(AMediaFormat*,
> +        const char* name, const char* value);
> +
> +typedef void (*pf_AMediaFormat_setInt32)(AMediaFormat*,
> +        const char* name, int32_t value);
> +
> +typedef bool (*pf_AMediaFormat_getInt32)(AMediaFormat*,
> +        const char *name, int32_t *out);
> +
> +struct syms
> +{
> +    struct {
> +        pf_AMediaCodec_createDecoderByType createDecoderByType;
> +        pf_AMediaCodec_configure configure;
> +        pf_AMediaCodec_start start;
> +        pf_AMediaCodec_stop stop;
> +        pf_AMediaCodec_flush flush;
> +        pf_AMediaCodec_delete delete;
> +        pf_AMediaCodec_getOutputFormat getOutputFormat;
> +        pf_AMediaCodec_dequeueInputBuffer dequeueInputBuffer;
> +        pf_AMediaCodec_getInputBuffer getInputBuffer;
> +        pf_AMediaCodec_queueInputBuffer queueInputBuffer;
> +        pf_AMediaCodec_dequeueOutputBuffer dequeueOutputBuffer;
> +        pf_AMediaCodec_getOutputBuffer getOutputBuffer;
> +        pf_AMediaCodec_releaseOutputBuffer releaseOutputBuffer;
> +    } AMediaCodec;
> +    struct {
> +        pf_AMediaFormat_new new;
> +        pf_AMediaFormat_delete delete;
> +        pf_AMediaFormat_setString setString;
> +        pf_AMediaFormat_setInt32 setInt32;
> +        pf_AMediaFormat_getInt32 getInt32;
> +    } AMediaFormat;
> +};
> +static struct syms syms;
> +static native_window_api_t anw_syms;
> +
> +struct members
> +{
> +    const char *name;
> +    int offset;
> +    bool critical;
> +};
> +static struct members members[] =
> +{
> +#define OFF(x) offsetof(struct syms, AMediaCodec.x)
> +    { "AMediaCodec_createDecoderByType", OFF(createDecoderByType), true },
> +    { "AMediaCodec_configure", OFF(configure), true },
> +    { "AMediaCodec_start", OFF(start), true },
> +    { "AMediaCodec_stop", OFF(stop), true },
> +    { "AMediaCodec_flush", OFF(flush), true },
> +    { "AMediaCodec_delete", OFF(delete), true },
> +    { "AMediaCodec_getOutputFormat", OFF(getOutputFormat), true },
> +    { "AMediaCodec_dequeueInputBuffer", OFF(dequeueInputBuffer), true },
> +    { "AMediaCodec_getInputBuffer", OFF(getInputBuffer), true },
> +    { "AMediaCodec_queueInputBuffer", OFF(queueInputBuffer), true },
> +    { "AMediaCodec_dequeueOutputBuffer", OFF(dequeueOutputBuffer), true },
> +    { "AMediaCodec_getOutputBuffer", OFF(getOutputBuffer), true },
> +    { "AMediaCodec_releaseOutputBuffer", OFF(releaseOutputBuffer), true },
> +#undef OFF
> +#define OFF(x) offsetof(struct syms, AMediaFormat.x)
> +    { "AMediaFormat_new", OFF(new), true },
> +    { "AMediaFormat_delete", OFF(delete), true },
> +    { "AMediaFormat_setString", OFF(setString), true },
> +    { "AMediaFormat_setInt32", OFF(setInt32), true },
> +    { "AMediaFormat_getInt32", OFF(getInt32), true },
> +#undef OFF
> +    { NULL, 0, false }
> +};
> +#undef OFF
> +
> +/* Initialize all symbols.
> + * Done only one time during the first initialisation */
> +static bool
> +InitSymbols(vlc_mc *mc)
> +{
> +    static vlc_mutex_t lock = VLC_STATIC_MUTEX;
> +    static int i_init_state = -1;
> +    bool ret;
> +
> +    vlc_mutex_lock(&lock);
> +
> +    if (i_init_state != -1)
> +        goto end;
> +
> +    i_init_state = 0;
> +
> +    void *ndk_handle = dlopen("libmediandk.so", RTLD_NOW);
> +    if (!ndk_handle)
> +        goto end;
> +
> +    for (int i = 0; members[i].name; i++)
> +    {
> +        void *sym = dlsym(ndk_handle, members[i].name);
> +        if (!sym && members[i].critical)
> +        {
> +            dlclose(ndk_handle);
> +            goto end;
> +        }
> +        *(void **)((uint8_t*)&syms + members[i].offset) = sym;
> +    }
> +    void *anw_handle = LoadNativeWindowAPI(&anw_syms);
> +    if (!anw_handle)
> +    {
> +        dlclose(ndk_handle);
> +        goto end;
> +    }
> +
> +    i_init_state = 1;
> +end:
> +    ret = i_init_state == 1;
> +    if (!ret)
> +        msg_Err(mc, "MediaCodec NDK init failed");
> +
> +    vlc_mutex_unlock(&lock);
> +    return ret;
> +}
> +
> +/*****************************************************************************
> + * Module descriptor
> + *****************************************************************************/
> +
> +static int Open(vlc_mc *);
> +static void Close(vlc_mc *);
> +static int Start(vlc_mc *, jobject, const char *, int, int, size_t, int);
> +static int Stop(vlc_mc *);
> +static int Flush(vlc_mc *);
> +static int PutInput(vlc_mc *, const void *, size_t , mtime_t, bool, mtime_t);
> +static int GetOutput(vlc_mc *, vlc_mc_out *, mtime_t);
> +static int ReleaseOutput(vlc_mc *, int, bool);
> +
> +vlc_module_begin()
> +    set_description(N_("MediaCodec via NDK"))
> +    set_capability("mc api", 3)
> +    set_category(CAT_INPUT)
> +    set_subcategory(SUBCAT_INPUT_VCODEC)
> +    set_callbacks(Open, Close)
> +vlc_module_end()
> +
> +struct vlc_mc_sys
> +{
> +    AMediaCodec* p_codec;
> +    AMediaFormat* p_format;
> +    ANativeWindow* p_anw;
> +};
> +
> +/*****************************************************************************
> + * Open
> + *****************************************************************************/
> +static int Open(vlc_mc *mc)
> +{
> +    if (!InitSymbols(mc))
> +        return VLC_EGENERIC;
> +
> +    mc->p_sys = calloc(1, sizeof(vlc_mc_sys));
> +    if (!mc->p_sys)
> +        return VLC_EGENERIC;
> +
> +    mc->start = Start;
> +    mc->stop = Stop;
> +    mc->flush = Flush;
> +    mc->put_in = PutInput;
> +    mc->get_out = GetOutput;
> +    mc->release_out = ReleaseOutput;
> +    return VLC_SUCCESS;
> +}
> +
> +/*****************************************************************************
> + * Close
> + *****************************************************************************/
> +static void Close(vlc_mc *mc)
> +{
> +    free(mc->p_sys);
> +}
> +
> +/*****************************************************************************
> + * Start
> + *****************************************************************************/
> +static int Start(vlc_mc *mc, jobject jsurface, const char *psz_mime,
> +                 int i_width, int i_height, size_t h264_profile, int i_angle)
> +{
> +    vlc_mc_sys *p_sys = mc->p_sys;
> +    int i_ret = VLC_EGENERIC;
> +    (void) h264_profile;
> +
> +    p_sys->p_codec = syms.AMediaCodec.createDecoderByType(psz_mime);
> +    if (!p_sys->p_codec)
> +    {
> +        msg_Err(mc, "AMediaCodec.createDecoderByType for %s failed", psz_mime);
> +        goto error;
> +    }
> +
> +    p_sys->p_format = syms.AMediaFormat.new();
> +    if (!p_sys->p_format)
> +    {
> +        msg_Err(mc, "AMediaFormat.new failed");
> +        goto error;
> +    }
> +
> +    syms.AMediaFormat.setString(p_sys->p_format, "mime", psz_mime);
> +    syms.AMediaFormat.setInt32(p_sys->p_format, "width", i_width);
> +    syms.AMediaFormat.setInt32(p_sys->p_format, "height", i_height);
> +    syms.AMediaFormat.setInt32(p_sys->p_format, "rotation-degrees", i_angle);
> +
> +    if (jsurface)
> +    {
> +        JNIEnv *env;
> +
> +        if (!(env = jni_get_env(THREAD_NAME)))
> +            goto error;
> +        p_sys->p_anw = anw_syms.winFromSurface(env, jsurface);
> +    }
> +
> +    if (syms.AMediaCodec.configure(p_sys->p_codec, p_sys->p_format,
> +                                   p_sys->p_anw, NULL, 0) != AMEDIA_OK)
> +    {
> +        msg_Err(mc, "AMediaCodec.configure failed");
> +        goto error;
> +    }
> +    if (syms.AMediaCodec.start(p_sys->p_codec) != AMEDIA_OK)
> +    {
> +        msg_Err(mc, "AMediaCodec.start failed");
> +        goto error;
> +    }
> +
> +    mc->b_started = true;
> +    mc->b_direct_rendering = !!p_sys->p_anw;
> +    mc->b_support_interlaced = true;
> +    mc->psz_name = ""; // TODO
> +    i_ret = VLC_SUCCESS;
> +
> +    msg_Dbg(mc, "MediaCodec via NDK opened");
> +error:
> +    if (i_ret != VLC_SUCCESS)
> +        Stop(mc);
> +    return i_ret;
> +}
> +
> +/*****************************************************************************
> + * Stop
> + *****************************************************************************/
> +static int Stop(vlc_mc *mc)
> +{
> +    vlc_mc_sys *p_sys = mc->p_sys;
> +
> +    mc->b_direct_rendering = false;
> +    mc->b_support_interlaced = false;
> +    mc->psz_name = NULL;
> +
> +    if (p_sys->p_codec)
> +    {
> +        if (mc->b_started)
> +        {
> +            syms.AMediaCodec.stop(p_sys->p_codec);
> +            mc->b_started = false;
> +        }
> +        syms.AMediaCodec.delete(p_sys->p_codec);
> +        p_sys->p_codec = NULL;
> +    }
> +    if (p_sys->p_format)
> +    {
> +        syms.AMediaFormat.delete(p_sys->p_format);
> +        p_sys->p_format = NULL;
> +    }
> +    if (p_sys->p_anw)
> +    {
> +        anw_syms.winRelease(p_sys->p_anw);
> +        p_sys->p_anw = NULL;
> +    }
> +
> +    msg_Dbg(mc, "MediaCodec via NDK closed");
> +    return VLC_SUCCESS;
> +}
> +
> +/*****************************************************************************
> + * Flush
> + *****************************************************************************/
> +static int Flush(vlc_mc *mc)
> +{
> +    vlc_mc_sys *p_sys = mc->p_sys;
> +
> +    if (syms.AMediaCodec.flush(p_sys->p_codec) == AMEDIA_OK)
> +        return VLC_SUCCESS;
> +    else
> +        return VLC_EGENERIC;
> +}
> +
> +/*****************************************************************************
> + * PutInput
> + *****************************************************************************/
> +static int PutInput(vlc_mc *mc, const void *p_buf, size_t i_size,
> +                    mtime_t i_ts, bool b_config, mtime_t i_timeout)
> +{
> +    vlc_mc_sys *p_sys = mc->p_sys;
> +    ssize_t i_index;
> +    uint8_t *p_mc_buf;
> +    size_t i_mc_size;
> +    (void) b_config;
> +
> +    i_index = syms.AMediaCodec.dequeueInputBuffer(p_sys->p_codec, i_timeout);
> +    if (i_index < 0)
> +    {
> +        if (i_index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
> +            return 0;
> +        else
> +        {
> +            msg_Err(mc, "AMediaCodec.dequeueInputBuffer failed");
> +            return VLC_EGENERIC;
> +        }
> +    }
> +
> +    p_mc_buf = syms.AMediaCodec.getInputBuffer(p_sys->p_codec,
> +                                               i_index, &i_mc_size);
> +    if (!p_mc_buf)
> +        return VLC_EGENERIC;
> +
> +    if (i_mc_size > i_size)
> +        i_mc_size = i_size;
> +    memcpy(p_mc_buf, p_buf, i_mc_size);
> +
> +    if (syms.AMediaCodec.queueInputBuffer(p_sys->p_codec, i_index, 0, i_mc_size,
> +                                          i_ts, 0) == AMEDIA_OK)
> +        return 1;
> +    else
> +    {
> +        msg_Err(mc, "AMediaCodec.queueInputBuffer failed");
> +        return VLC_EGENERIC;
> +    }
> +}
> +
> +static int32_t GetFormatInteger(AMediaFormat *p_format, const char *psz_name)
> +{
> +    int32_t i_out = 0;
> +    syms.AMediaFormat.getInt32(p_format, psz_name, &i_out);
> +    return i_out;
> +}
> +
> +/*****************************************************************************
> + * GetOutput
> + *****************************************************************************/
> +static int GetOutput(vlc_mc *mc, vlc_mc_out *p_out, mtime_t i_timeout)
> +{
> +    vlc_mc_sys *p_sys = mc->p_sys;
> +    AMediaCodecBufferInfo info;
> +    ssize_t i_index;
> +
> +    i_index = syms.AMediaCodec.dequeueOutputBuffer(p_sys->p_codec, &info,
> +                                                   i_timeout);
> +    if (i_index >= 0)
> +    {
> +        p_out->type = MC_OUT_TYPE_BUF;
> +        p_out->u.buf.i_index = i_index;
> +
> +        p_out->u.buf.i_ts = info.presentationTimeUs;
> +
> +        if (mc->b_direct_rendering)
> +        {
> +            p_out->u.buf.p_ptr = NULL;
> +            p_out->u.buf.i_size = 0;
> +        }
> +        else
> +        {
> +            size_t i_mc_size;
> +            uint8_t *p_mc_buf = syms.AMediaCodec.getOutputBuffer(p_sys->p_codec,
> +                                                                 i_index,
> +                                                                 &i_mc_size);
> +            if (!p_mc_buf)
> +            {
> +                msg_Err(mc, "AMediaCodec.getOutputBuffer failed");
> +                return VLC_EGENERIC;
> +            }
> +            p_out->u.buf.p_ptr = p_mc_buf + info.offset;
> +            p_out->u.buf.i_size = i_mc_size;
> +        }
> +        return 1;
> +    }
> +    else if (i_index == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED)
> +    {
> +        AMediaFormat *format = syms.AMediaCodec.getOutputFormat(p_sys->p_codec);
> +
> +        p_out->type = MC_OUT_TYPE_CONF;
> +        p_out->u.conf.width = GetFormatInteger(format, "width");
> +        p_out->u.conf.height = GetFormatInteger(format, "height");
> +        p_out->u.conf.stride = GetFormatInteger(format, "stride");
> +        p_out->u.conf.slice_height = GetFormatInteger(format, "slice-height");
> +        p_out->u.conf.pixel_format = GetFormatInteger(format, "color-format");
> +        p_out->u.conf.crop_left = GetFormatInteger(format, "crop-left");
> +        p_out->u.conf.crop_top = GetFormatInteger(format, "crop-top");
> +        p_out->u.conf.crop_right = GetFormatInteger(format, "crop-right");
> +        p_out->u.conf.crop_bottom = GetFormatInteger(format, "crop-bottom");
> +        return 1;
> +    }
> +    else if (i_index == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED
> +          || i_index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
> +    {
> +        return 0;
> +    }
> +    else
> +    {
> +        msg_Err(mc, "AMediaCodec.dequeueOutputBuffer failed");
> +        return VLC_EGENERIC;
> +    }
> +}
> +
> +/*****************************************************************************
> + * ReleaseOutput
> + *****************************************************************************/
> +static int ReleaseOutput(vlc_mc *mc, int i_index, bool b_render)
> +{
> +    vlc_mc_sys *p_sys = mc->p_sys;
> +
> +    if (syms.AMediaCodec.releaseOutputBuffer(p_sys->p_codec, i_index, b_render)
> +                                             == AMEDIA_OK)
> +        return VLC_SUCCESS;
> +    else
> +        return VLC_EGENERIC;
> +}
> -- 
> 2.1.4
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel

-- 
With my kindest regards,

-- 
Jean-Baptiste Kempf
http://www.jbkempf.com/ - +33 672 704 734
Sent from my Electronic Device



More information about the vlc-devel mailing list