/*
 * Copyright (C) 2011 Petr Havlena  [email protected]
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <android/surface.h>
#include <surfaceflinger/Surface.h>
#include <utils/Log.h>
#include <SkBitmap.h>
#include <SkCanvas.h>#define TAG "SurfaceWrapper"using namespace android;static Surface*         surface;
static Surface::SurfaceInfo surfaceInfo;static SkBitmap         bmpClient;
static SkBitmap         bmpSurface;
static SkRect           rect_bmpClient;
static SkRect           rect_bmpSurface;
static SkMatrix         matrix;static
Surface* getNativeSurface(JNIEnv* env, jobject jsurface) {
jclass clazz = env->FindClass("android/view/Surface");
//android 2.2
//jfieldID field_surface = env->GetFieldID(clazz, "mSurface", "I");
//android 2.3
jfieldID field_surface = env->GetFieldID(clazz, "mNativeSurface", "I");
if(field_surface == NULL) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "GetFieldID ERROR, field_surface == NULL!");
return NULL;
}
return (Surface *) env->GetIntField(jsurface, field_surface);
}static
void initBitmap(SkBitmap *bitmap, int format, int width, int height) {
switch (format) {
        case PIXEL_FORMAT_RGBA_8888:
__android_log_print(ANDROID_LOG_INFO, TAG, "setConfig:PIXEL_FORMAT_RGBA_8888");
            bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                width, height);
            break;

        case PIXEL_FORMAT_RGBA_4444:
__android_log_print(ANDROID_LOG_INFO, TAG, "setConfig:PIXEL_FORMAT_RGBA_4444");
            bitmap->setConfig(SkBitmap::kARGB_4444_Config,
                width, height);
            break;

        case PIXEL_FORMAT_RGB_565:
__android_log_print(ANDROID_LOG_INFO, TAG, "setConfig:PIXEL_FORMAT_RGBA_565");
            bitmap->setConfig(SkBitmap::kRGB_565_Config,
                width, height);
            break;

        case PIXEL_FORMAT_A_8:
__android_log_print(ANDROID_LOG_INFO, TAG, "setConfig:PIXEL_FORMAT_A_8");
            bitmap->setConfig(SkBitmap::kA8_Config,
                width, height);
            break;

        default:
__android_log_print(ANDROID_LOG_INFO, TAG, "setConfig:kNo_Config");
            bitmap->setConfig(SkBitmap::kNo_Config,
                width, height);
            break;
    }
}int AndroidSurface_register(JNIEnv* env, jobject jsurface) {
__android_log_print(ANDROID_LOG_INFO, TAG, "registering video surface");

surface = getNativeSurface(env, jsurface);
if(surface == NULL) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "getNativeSurface ERROR, surface == NULL!");
     return ANDROID_SURFACE_RESULT_JNI_EXCEPTION;
}
else{
__android_log_print(ANDROID_LOG_INFO, TAG, "registered");
}
return ANDROID_SURFACE_RESULT_SUCCESS;
}int AndroidSurface_getPixels(int width, int height, void** pixels) {
__android_log_print(ANDROID_LOG_INFO, TAG, "getting surface's pixels %ix%i", width, height);
if(surface == NULL) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "gAndroidSurface_getPixels: surface == NULL!");
        return ANDROID_SURFACE_RESULT_JNI_EXCEPTION;
}    initBitmap(&bmpClient, PIXEL_FORMAT_RGB_565, width, height);
    bmpClient.setIsOpaque(true);
    //-- alloc array of pixels
    if(!bmpClient.allocPixels()) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "gAndroidSurface_getPixels: bmpClient.allocPixels() error!");
        return ANDROID_SURFACE_RESULT_COULDNT_INIT_BITMAP_CLIENT;
}
    *pixels = bmpClient.getPixels();
__android_log_print(ANDROID_LOG_ERROR, TAG, "gAndroidSurface_getPixels:getted *pixels = 0x%08x", *pixels);

    //__android_log_print(ANDROID_LOG_INFO, TAG, "getted");
    return ANDROID_SURFACE_RESULT_SUCCESS;
}static
void doUpdateSurface(bool autoscale) {
    SkCanvas canvas(bmpSurface);    if(autoscale)
    {
        rect_bmpSurface.set(0, 0, bmpSurface.width(), bmpSurface.height());
        rect_bmpClient.set(0, 0, bmpClient.width(), bmpClient.height());
        matrix.setRectToRect(rect_bmpClient, rect_bmpSurface, SkMatrix::kFill_ScaleToFit);
        canvas.drawBitmapMatrix(bmpClient, matrix);
    }
    else
    {
        canvas.drawBitmap(bmpClient, 0, 0);
    }
}int AndroidSurface_updateSurface(bool autoscale) {
    if(surface == NULL) {
        return ANDROID_SURFACE_RESULT_JNI_EXCEPTION;
    }
    if (!surface->isValid()) {
        return ANDROID_SURFACE_RESULT_NOT_VALID;
    }
    if (surface->lock(&surfaceInfo) < 0) {
        return ANDROID_SURFACE_RESULT_COULDNT_LOCK;
    }    /* create surface bitmap with pixels of surface */
    if(bmpSurface.width() != surfaceInfo.w ||
        bmpSurface.height() != surfaceInfo.h)
    {
        initBitmap(&bmpSurface, surfaceInfo.format,
            surfaceInfo.w, surfaceInfo.h);
    }
    bmpSurface.setPixels(surfaceInfo.bits);    /* redraw surface screen */
    doUpdateSurface(autoscale);

    if (surface->unlockAndPost() < 0) {
        return ANDROID_SURFACE_RESULT_COULDNT_UNLOCK_AND_POST;
    }
    return ANDROID_SURFACE_RESULT_SUCCESS;
}int AndroidSurface_unregister() {
    __android_log_print(ANDROID_LOG_INFO, TAG, "unregistering video surface");
    __android_log_print(ANDROID_LOG_INFO, TAG, "unregistered");
    return ANDROID_SURFACE_RESULT_SUCCESS;
}  代码如上 在 jclass clazz = env->FindClass("android/view/Surface");
出错 这个是为什么呢 
谢谢 指导

解决方案 »

  1.   

    出现SIGILL(非法硬件指令)和SIGSEGV(无效内存引用)setFixedSize called;A/libc(11964): Fatal signal 4 (SIGILL) at 0x4c6959b8 (code=1) 
      

  2.   

    你java代码里修改了surface的尺寸,这个修改在不同的线程里操作的所以会导致这种情况。
    你应该在surface渲染线程里setFixedSize
    你可以通过setOnVideoSizeChangedListener来监听或者直接在surfaceChanged方法里设置
      

  3.   

    顺带说一句,这种处理图像显示的方式对于分辨率较大的,或者屏幕分辨率较大的完全不可用。
    瓶颈在doUpdateSurface里的Martix缩放。640变换到1280,在 tegra2 下耗时45ms/frame左右。
    考虑采取别的显示方式吧