Пример #1
0
static int  AndroidLockSurface(picture_t *picture)
{
    picture_sys_t *picsys = picture->p_sys;
    vout_display_sys_t *sys = picsys->sys;
    SurfaceInfo *info = &picsys->info;
    uint32_t sw, sh;

    if (!sys->native_surface) {
        picsys->surf = jni_LockAndGetAndroidJavaSurface();
        if (unlikely(!picsys->surf)) {
            jni_UnlockAndroidSurface();
            return VLC_EGENERIC;
        }
        sys->native_surface = jni_AndroidJavaSurfaceToNativeSurface(picsys->surf);
        jni_UnlockAndroidSurface();

        if (!sys->native_surface)
            return VLC_EGENERIC;
    }

    sw = sys->fmt.i_width;
    sh = sys->fmt.i_height;
    // For RGB (32 or 16) we need to align on 8 or 4 pixels, 16 pixels for YUV
    int align_pixels = (16 / picture->p[0].i_pixel_pitch) - 1;
    uint32_t aligned_width = (sw + align_pixels) & ~align_pixels;

    if (aligned_width != sys->i_alloc_width || sh != sys->i_alloc_height) {
        bool configured;
        if (jni_ConfigureSurface(picsys->surf,
                                 aligned_width,
                                 sh,
                                 sys->i_android_hal,
                                 &configured) == -1 || !configured) {
            return VLC_EGENERIC;
        }
        sys->i_alloc_width = aligned_width;
        sys->i_alloc_height = sh;
        sys->native_surface = jni_AndroidJavaSurfaceToNativeSurface(picsys->surf);
        UpdateLayout(sys);
    }

    if (sys->s_lock)
        sys->s_lock(sys->native_surface, info, 1);
    else
        sys->s_lock2(sys->native_surface, info, NULL);

    if (info->w != sys->i_alloc_width || info->h != sh) {
        sys->s_unlockAndPost(sys->native_surface);
        return VLC_EGENERIC;
    }

    picture->p[0].p_pixels = (uint8_t*)info->bits;
    picture->p[0].i_lines = info->h;
    picture->p[0].i_pitch = picture->p[0].i_pixel_pitch * info->s;

    return VLC_SUCCESS;
}
Пример #2
0
static void AndroidUnlockSurface(picture_t *picture) {
    picture_sys_t *picsys = picture->p_sys;
    vout_display_sys_t *sys = picsys->sys;

    if (likely(picsys->surf))
        sys->s_unlockAndPost(picsys->surf);
    jni_UnlockAndroidSurface();
}
Пример #3
0
static int SetupWindowSubtitleSurface(vout_display_sys_t *sys)
{
    int err;
    jobject jsurf = jni_LockAndGetSubtitlesSurface();
    err = AndroidWindow_SetSurface(sys, sys->p_sub_window, jsurf);
    jni_UnlockAndroidSurface();
    err = err == 0 ? AndroidWindow_Setup(sys, sys->p_sub_window, 1) : err;
    return err;
}
Пример #4
0
static int SetupWindowSurface(vout_display_sys_t *sys, unsigned i_pic_count)
{
    int err;
    jobject jsurf = jni_LockAndGetAndroidJavaSurface();
    err = AndroidWindow_SetSurface(sys, sys->p_window, jsurf);
    jni_UnlockAndroidSurface();
    err = err == 0 ? AndroidWindow_Setup(sys, sys->p_window, i_pic_count) : err;
    return err;
}
Пример #5
0
static int  AndroidLockSurface(picture_t *picture) {
    picture_sys_t *picsys = picture->p_sys;
    vout_display_sys_t *sys = picsys->sys;
    SurfaceInfo *info;
    uint32_t sw, sh;
    void *surf;

    sw = picture->p[0].i_visible_pitch / picture->p[0].i_pixel_pitch;
    sh = picture->p[0].i_visible_lines;

    picsys->surf = surf = jni_LockAndGetAndroidSurface();
    info = &(picsys->info);

    if (unlikely(!surf)) {
        jni_UnlockAndroidSurface();
        return VLC_EGENERIC;
    }

    if (sys->s_lock)
        sys->s_lock(surf, info, 1);
    else
        sys->s_lock2(surf, info, NULL);

    // For RGB (32 or 16) we need to align on 8 or 4 pixels, 16 pixels for YUV
    int align_pixels = (16 / picture->p[0].i_pixel_pitch) - 1;
    uint32_t aligned_width = (sw + align_pixels) & ~align_pixels;

    if (info->w != aligned_width || info->h != sh) {
        // input size doesn't match the surface size -> request a resize
        jni_SetAndroidSurfaceSize(sw, sh, sys->i_sar_num, sys->i_sar_den);
        sys->s_unlockAndPost(surf);
        jni_UnlockAndroidSurface();
        return VLC_EGENERIC;
    }

    picture->p[0].p_pixels = (uint8_t*)info->bits;
    picture->p[0].i_lines = info->h;
    picture->p[0].i_pitch = picture->p[0].i_pixel_pitch * info->s;

    if (info->format == 0x32315659 /*ANDROID_IMAGE_FORMAT_YV12*/)
        SetupPictureYV12(info, picture);

    return VLC_SUCCESS;
}
Пример #6
0
static int  AndroidLockSurface(picture_t *picture) {
    picture_sys_t *picsys = picture->p_sys;
    vout_display_sys_t *sys = picsys->sys;
    SurfaceInfo *info;
    uint32_t sw, sh;
    void *surf;

    sw = picture->p[0].i_visible_pitch / picture->p[0].i_pixel_pitch;
    sh = picture->p[0].i_visible_lines;

    picsys->surf = surf = jni_LockAndGetAndroidSurface();
    info = &(picsys->info);

    if (unlikely(!surf)) {
        jni_UnlockAndroidSurface();
        return VLC_EGENERIC;
    }

    if (sys->s_lock)
        sys->s_lock(surf, info, 1);
    else
        sys->s_lock2(surf, info, NULL);

    // input size doesn't match the surface size,
    // request a resize
    if (info->w != sw || info->h != sh) {
        jni_SetAndroidSurfaceSize(sw, sh, sys->i_sar_num, sys->i_sar_den);
        sys->s_unlockAndPost(surf);
        jni_UnlockAndroidSurface();
        return VLC_EGENERIC;
    }

    picture->p->p_pixels = (uint8_t*)info->bits;
    picture->p->i_pitch = 4 * info->s;
    picture->p->i_lines = info->h;

    return VLC_SUCCESS;
}
Пример #7
0
/**
 * Create an Android native window.
 */
static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
{
    vout_window_sys_t *p_sys = malloc(sizeof (*p_sys));
    if (p_sys == NULL)
        return VLC_ENOMEM;

    p_sys->p_library = LoadNativeWindowAPI(&p_sys->native_window);
    if (p_sys->p_library == NULL)
    {
        free(p_sys);
        return VLC_EGENERIC;
    }

    // Create the native window by first getting the Java surface.
    jobject javaSurface = jni_LockAndGetAndroidJavaSurface();
    if (javaSurface == NULL)
        goto error;

    JNIEnv *p_env;
    (*myVm)->AttachCurrentThread(myVm, &p_env, NULL);
    p_sys->window = p_sys->native_window.winFromSurface(p_env, javaSurface); // ANativeWindow_fromSurface call.
    (*myVm)->DetachCurrentThread(myVm);

    jni_UnlockAndroidSurface();

    if (p_sys->window == NULL)
        goto error;

    wnd->handle.anativewindow = p_sys->window;
    wnd->control = Control;
    wnd->sys = p_sys;

    // Set the Java surface size.
    jni_SetAndroidSurfaceSize(cfg->width, cfg->height, cfg->width, cfg->height, 1, 1);

    return VLC_SUCCESS;

error:
    dlclose(p_sys->p_library);
    free(p_sys);
    return VLC_EGENERIC;
}
Пример #8
0
static int  AndroidLockSurface(picture_t *picture)
{
    picture_sys_t *picsys = picture->p_sys;
    vout_display_sys_t *sys = picsys->sys;
    SurfaceInfo *info;
    uint32_t sw, sh;
    void *surf;

    sw = sys->fmt.i_width;
    sh = sys->fmt.i_height;

    if (sys->native_window.winFromSurface) {
        jobject jsurf = jni_LockAndGetAndroidJavaSurface();
        if (unlikely(!jsurf)) {
            jni_UnlockAndroidSurface();
            return VLC_EGENERIC;
        }
        if (sys->window && jsurf != sys->jsurf) {
            sys->native_window.winRelease(sys->window);
            sys->window = NULL;
        }
        sys->jsurf = jsurf;
        if (!sys->window) {
            JNIEnv *p_env;
            (*myVm)->AttachCurrentThread(myVm, &p_env, NULL);
            sys->window = sys->native_window.winFromSurface(p_env, jsurf);
            (*myVm)->DetachCurrentThread(myVm);
        }
        // Using sys->window instead of the native surface object
        // as parameter to the unlock function
        picsys->surf = surf = sys->window;
    } else {
        picsys->surf = surf = jni_LockAndGetAndroidSurface();
        if (unlikely(!surf)) {
            jni_UnlockAndroidSurface();
            return VLC_EGENERIC;
        }
    }
    info = &picsys->info;

    if (sys->native_window.winLock) {
        ANativeWindow_Buffer buf = { 0 };
        sys->native_window.winLock(sys->window, &buf, NULL);
        info->w      = buf.width;
        info->h      = buf.height;
        info->bits   = buf.bits;
        info->s      = buf.stride;
        info->format = buf.format;
    } else if (sys->s_lock)
        sys->s_lock(surf, info, 1);
    else
        sys->s_lock2(surf, info, NULL);

    // For RGB (32 or 16) we need to align on 8 or 4 pixels, 16 pixels for YUV
    int align_pixels = (16 / picture->p[0].i_pixel_pitch) - 1;
    uint32_t aligned_width = (sw + align_pixels) & ~align_pixels;

    if (info->w != aligned_width || info->h != sh || sys->b_changed_crop) {
        // input size doesn't match the surface size -> request a resize
        jni_SetAndroidSurfaceSize(aligned_width, sh, sys->fmt.i_visible_width, sys->fmt.i_visible_height, sys->i_sar_num, sys->i_sar_den);
        // When using ANativeWindow, one should use ANativeWindow_setBuffersGeometry
        // to set the size and format. In our case, these are set via the SurfaceHolder
        // in Java, so we seem to manage without calling this ANativeWindow function.
        sys->s_unlockAndPost(surf);
        jni_UnlockAndroidSurface();
        sys->b_changed_crop = false;
        return VLC_EGENERIC;
    }

    picture->p[0].p_pixels = (uint8_t*)info->bits;
    picture->p[0].i_lines = info->h;
    picture->p[0].i_pitch = picture->p[0].i_pixel_pitch * info->s;

    if (info->format == 0x32315659 /*ANDROID_IMAGE_FORMAT_YV12*/)
        SetupPictureYV12(info, picture);

    return VLC_SUCCESS;
}
Пример #9
0
static void DisplaySubpicture(vout_display_t *vd, subpicture_t *subpicture)
{
    vout_display_sys_t *sys = vd->sys;

    struct md5_s hash;
    InitMD5(&hash);
    if (subpicture) {
        for (subpicture_region_t *r = subpicture->p_region; r != NULL; r = r->p_next) {
            AddMD5(&hash, &r->i_x, sizeof(r->i_x));
            AddMD5(&hash, &r->i_y, sizeof(r->i_y));
            AddMD5(&hash, &r->fmt.i_visible_width, sizeof(r->fmt.i_visible_width));
            AddMD5(&hash, &r->fmt.i_visible_height, sizeof(r->fmt.i_visible_height));
            AddMD5(&hash, &r->fmt.i_x_offset, sizeof(r->fmt.i_x_offset));
            AddMD5(&hash, &r->fmt.i_y_offset, sizeof(r->fmt.i_y_offset));
            const int pixels_offset = r->fmt.i_y_offset * r->p_picture->p->i_pitch +
                                      r->fmt.i_x_offset * r->p_picture->p->i_pixel_pitch;

            for (int y = 0; y < r->fmt.i_visible_height; y++)
                AddMD5(&hash, &r->p_picture->p->p_pixels[pixels_offset + y*r->p_picture->p->i_pitch], r->fmt.i_visible_width);
        }
    }
    EndMD5(&hash);
    if (!memcmp(hash.buf, sys->hash, 16))
        return;
    memcpy(sys->hash, hash.buf, 16);

    jobject jsurf = jni_LockAndGetSubtitlesSurface();
    if (sys->window && jsurf != sys->jsurf)
    {
        sys->native_window.winRelease(sys->window);
        sys->window = NULL;
    }
    sys->jsurf = jsurf;
    if (!sys->window)
    {
        JNIEnv *p_env;
        jni_attach_thread(&p_env, THREAD_NAME);
        sys->window = sys->native_window.winFromSurface(p_env, jsurf);
        jni_detach_thread();
    }

    ANativeWindow_Buffer buf = { 0 };
    int32_t err = sys->native_window.winLock(sys->window, &buf, NULL);
    if (err) {
        jni_UnlockAndroidSurface();
        return;
    }

    if (buf.width >= sys->fmt.i_width && buf.height >= sys->fmt.i_height)
    {
        /* Wrap the NativeWindow corresponding to the subtitles surface in a picture_t */
        picture_t *picture = sys->subtitles_picture;
        picture->p[0].p_pixels = (uint8_t*)buf.bits;
        picture->p[0].i_lines = buf.height;
        picture->p[0].i_pitch = picture->p[0].i_pixel_pitch * buf.stride;
        /* Clear the subtitles surface. */
        memset(picture->p[0].p_pixels, 0, picture->p[0].i_pitch * picture->p[0].i_lines);
        if (subpicture)
        {
            /* Allocate a blending filter if needed. */
            if (unlikely(!sys->p_spu_blend))
                sys->p_spu_blend = filter_NewBlend(VLC_OBJECT(vd), &picture->format);
            picture_BlendSubpicture(picture, sys->p_spu_blend, subpicture);
        }
    }

    sys->native_window.unlockAndPost(sys->window);
    jni_UnlockAndroidSurface();
}