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; }
/** * 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; }
/** * Window control. */ static int Control(vout_window_t *wnd, int cmd, va_list ap) { switch (cmd) { case VOUT_WINDOW_SET_SIZE: { unsigned width = va_arg(ap, unsigned); unsigned height = va_arg(ap, unsigned); jni_SetAndroidSurfaceSize(width, height, width, height, 1, 1); break; } case VOUT_WINDOW_SET_STATE: case VOUT_WINDOW_SET_FULLSCREEN: return VLC_EGENERIC; default: msg_Err (wnd, "request %d not implemented", cmd); return VLC_EGENERIC; } return VLC_SUCCESS; }
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; }
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; }