android - 使用 OpenMAX IL 硬件渲染到 Android Surface

标签 android android-ndk android-mediaplayer android-library openmax

我想按照此处所述使用 OMX 硬件渲染器: http://www.slideshare.net/RaghavanVenkateswaran/iomx-in-android

操作系统:Android 2.3.4

使用的系统库:libmedia、libbinder、libstagefright、libutils

我设备上的 OMX 组件:

组件名称:OMX.ITTIAM.AAC.decode,组件角色:audio_decoder.aac

组件名称:OMX.ITTIAM.AAC.encode,组件角色:audio_encoder.aac

组件名称:OMX.TI.720P.Decoder,组件角色:video_decoder.mpeg4

组件名称:OMX.TI.720P.Decoder,组件角色:video_decoder.avc

组件名称:OMX.TI.720P.Encoder,组件角色:video_encoder.mpeg4

组件名称:OMX.TI.720P.Encoder,组件角色:video_encoder.avc

组件名称:OMX.TI.AAC.decode,组件角色:audio_decoder.aac

组件名称:OMX.TI.AAC.encode,组件角色:audio_encoder.aac

组件名称:OMX.TI.AMR.decode,组件角色:audio_decoder.amrnb

组件名称:OMX.TI.AMR.encode,组件角色:audio_encoder.amrnb

组件名称:OMX.TI.Camera,组件角色:camera.yuv

组件名称:OMX.TI.JPEG.decoder,组件角色:image_decoder.jpeg

组件名称:OMX.TI.JPEG.encoder,组件角色:image_encoder.jpeg

组件名称:OMX.TI.MP3.decode,组件角色:audio_decoder.mp3

组件名称:OMX.TI.VPP,组件角色:iv_renderer.yuv.overlay

组件名称:OMX.TI.Video.Decoder,组件角色:video_decoder.h263

组件名称:OMX.TI.Video.Decoder,组件角色:video_decoder.avc

组件名称:OMX.TI.Video.Decoder,组件角色:video_decoder.mpeg2

组件名称:OMX.TI.Video.Decoder,组件角色:video_decoder.mpeg4

组件名称:OMX.TI.Video.Decoder,组件角色:video_decoder.wmv

组件名称:OMX.TI.Video.encoder,组件角色:video_encoder.mpeg4

组件名称:OMX.TI.Video.encoder,组件角色:video_encoder.h263

组件名称:OMX.TI.Video.encoder,组件角色:video_encoder.avc

组件名称:OMX.TI.WBAMR.decode,组件角色:audio_decoder.amrwb

组件名称:OMX.TI.WBAMR.encode,组件角色:audio_encoder.amrwb

组件名称:OMX.TI.WMA.decode,组件角色:audio_decoder.wma

我已经完成了这些步骤:

1,以这种方式通过 JNI 传递 Android Surface 对象(与在 native MediaPlayer 中完全一样):

JNI(C++):

static void com_mautilus_media_MMediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz)
{
    __android_log_print(ANDROID_LOG_INFO, TAG, "setVideoSurface");

    MMediaPlayer *mp = getMediaPlayer(env, thiz);

    if (mp == NULL )
    {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return;
    }

    setVideoSurface(mp, env, thiz);

}
static void setVideoSurface(MMediaPlayer *mp, JNIEnv *env, jobject thiz)
{
    __android_log_print(ANDROID_LOG_INFO, TAG, "setVideoSurface");

    jobject surface = env->GetObjectField(thiz, fields.surface);

    if (surface != NULL && mp != NULL)
    {
        const android::sp<android::Surface> native_surface = get_surface(env, surface);
        mp->setVideoSurface(native_surface);

    }
}

MMediaPlayer 中的 Surface 变量声明为:

android::sp<android::Surface> surface;

Java:

private Surface mSurface; // accessed by native methods
private SurfaceHolder mSurfaceHolder;

public void setDisplay(SurfaceHolder sh)
{
    mSurfaceHolder = sh;

    if (sh != null)
    {
        mSurface = sh.getSurface();
    }
    else
    {
        mSurface = null;
    }

    setVideoSurface(); // Native function call
}

2、初始化IOMX节点:

注意:硬编码值仅用于简单和测试目的

android::sp<android::IServiceManager> serviceManager = android::defaultServiceManager();
android::sp<android::IBinder> binder = serviceManager>getService(android::String16("media.player"));
android::sp<android::IMediaPlayerService> mediaPlayerService = android::interface_cast<android::IMediaPlayerService>(binder);
android::sp<android::IOMX> iomx = mediaPlayerService->getOMX();


android::IOMX::node_id node;

// observer is instance of class derived from android::BnOMXObserver class
iomx->allocateNode("OMX.TI.VPP", observer, &mRendererNode->node);

OMX_PARAM_PORTDEFINITIONTYPE portDefn;
portDefn.nPortIndex = 1;

iomx->getParameter(node, OMX_IndexParamPortDefinition, &portDefn, sizeof(portDefn));

//portDefn.nBufferCountActual = mInBufCnt; // set some suitable value here or don’t update to
//use default value

portDefn.format.video.nFrameWidth = 256; // width of the video to be played
portDefn.format.video.nFrameHeight = 144; // height of video to be played
portDefn.format.video.nStride = 256;
portDefn.format.video.nSliceHeight = 144;
iomx->setParameter(node, OMX_IndexParamPortDefinition, &portDefn, sizeof(portDefn));


portDefn.nPortIndex = 2;
iomx->getParameter(node, OMX_IndexParamPortDefinition, &portDefn, sizeof(portDefn));
//portDefn.nBufferCountActual = iOutBufCnt; // set suitable value or leave to default.
portDefn.nBufferSize = (256 * 144 * 3) / 2;
portDefn.format.video.nFrameWidth = 256;
portDefn.format.video.nFrameHeight = 144;
portDefn.format.video.nStride = 256;
portDefn.format.video.nSliceHeight = 144;
iomx->setParameter(node, OMX_IndexParamPortDefinition, &portDefn, sizeof(portDefn));

3、尝试创建OMX渲染器:

android::sp<android::IOMXRenderer> mOMXRenderer;

mOMXRenderer = omxContext->iomx->createRenderer(surface, "OMX.TI.VPP", OMX_COLOR_FormatYUV420Planar, 256, 144, displayWidth, displayHeight, 0);

总是返回 NULL。

有人知道这有什么问题吗?我在初始化错误的组件吗?或者必须遵循一些特殊的调用顺序?还是别的?

最佳答案

使用 IOMX.h 中定义的 createRendererFromJavaSurface

关于android - 使用 OpenMAX IL 硬件渲染到 Android Surface,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13730356/

相关文章:

android - <div> 在 android 中发送电子邮件时不创建列

java - 使用 Android 播放来自 jar 资源的音频文件

java - 内部类中的方法被 proguard 剥离

安卓媒体播放器 : prepared video takes 250ms to start playing

android - 为什么这会使我的屏幕消失并导致手机崩溃?

Android从右到左的线性布局

android - 如何增加 TextView 中的行间距。?

android - 当 EditText 为空时无法找出禁用按钮的代码

android - 使用ARMCC编译Android原生库

java - 如何在另一个Android Project中使用生成的.so库?