[Android] 在Jni中对SurfaceView渲染一张图片

ANativeWindow渲染RGB

在jni渲染图片有很多方式,比如OpenGL,这里介绍实现方式最简单的一种:直接对surface进行操作。
原理也很简单,我们直接将数据拷贝到ANativeWindow的缓存队列中,然后由系统进行处理现实到屏幕上。

  • 首先创建surfaceView,只需要通过jni传入surface对象即可:
import android.content.Context;
import android.util.AttributeSet;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MyVideoView extends SurfaceView implements SurfaceHolder.Callback {
    private OnSurfaceListener listener;
    private SurfaceHolder mHolder;

    public MyVideoView(Context context) {
        super(context);
        init();
    }

    public MyVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyVideoView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        mHolder = this.getHolder();
        mHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        setSurface(holder.getSurface()); //初始化
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        setSurface(null); //通知jni层释放surface
    }

    @Override
    public Surface getSurface() {
        SurfaceHolder holder = getHolder();
        if (holder != null) {
            return holder.getSurface();
        }
        return null;
    }   
}

public static native void setSurface(Surface surface);

jni相关接口的实现这里不做讨论

  • 接下来是在native中获取surface对象并进行初始化:
ANativeWindow *mANativeWindow = (ANativeWindow *)ANativeWindow_fromSurface(env, jsurface);
// 需要先设定图像的尺寸和格式
ANativeWindow_setBuffersGeometry(mANativeWindow, videoWidth, videoHeight, WINDOW_FORMAT_RGBA_8888);

mANativeWindow 既是surface在jni层的映射

  • 开始进行渲染(data是传入的RGB图像数据):
    ANativeWindow_Buffer nwBuffer;
    if (0 != ANativeWindow_lock(mANativeWindow, &nwBuffer, NULL)) {
        LOGE("ANativeWindow_lock() error");
        return;
    }
    if (nwBuffer.width >= nwBuffer.stride) {
        memcpy(nwBuffer.bits, data, len);
    } else {
        /*fixed花屏问题:
         * 输出stride和width的日志发现,如果正常显示则stride==width, 通过注释可以看出应该是内存对齐问题导致的, 调整代码:
         */
        int i;
        for (i = 0; i < height; ++i) {
            memcpy(nwBuffer.bits + nwBuffer.stride * i * RGB_SIZE, data + width * i * RGB_SIZE, width * RGB_SIZE);
        }
    }
    if (0 != ANativeWindow_unlockAndPost(player->mANativeWindow)) {
        LOGE("ANativeWindow_unlockAndPost error");
        return;
    }

需要注意的是 nwBuffer.stride >= nwBuffer.width。因为nwBuffer.stride 为 POT 即2的n次方

  • 完成渲染后必须对surface进行释放:
ANativeWindow_release(mANativeWindow);

参考:
http://blog.csdn.net/lsingle/article/details/38174049?utm_source=tuicool&utm_medium=referral

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值