/** * 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; }
static int Open(vlc_object_t *p_this) { vout_display_t *vd = (vout_display_t*)p_this; vout_display_sys_t *sys; video_format_t sub_fmt; if (vout_display_IsWindowed(vd)) return VLC_EGENERIC; /* XXX: android_window use a surface created by VideoPlayerActivity to * alloc pictures. Don't try to open the vout if this activity is not * created. This need to be replaced by something like var_CreateGetAddress * (vd, "drawable-android") in the future. */ if (!jni_IsVideoPlayerActivityCreated()) return VLC_EGENERIC; /* Allocate structure */ vd->sys = sys = (struct vout_display_sys_t*)calloc(1, sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->p_library = LoadNativeWindowAPI(&sys->anw); if (!sys->p_library) { msg_Err(vd, "Could not initialize NativeWindow API."); goto error; } #ifdef USE_ANWP if (LoadNativeWindowPrivAPI(&sys->anwp) == 0) sys->b_has_anwp = true; else msg_Warn(vd, "Could not initialize NativeWindow Priv API."); #endif sys->i_display_width = vd->cfg->display.width; sys->i_display_height = vd->cfg->display.height; if (vd->fmt.i_chroma != VLC_CODEC_ANDROID_OPAQUE) { /* Setup chroma */ char *psz_fcc = var_InheritString(vd, CFG_PREFIX "chroma"); if (psz_fcc) { vd->fmt.i_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_fcc); free(psz_fcc); } else vd->fmt.i_chroma = VLC_CODEC_RGB32; switch(vd->fmt.i_chroma) { case VLC_CODEC_YV12: /* avoid swscale usage by asking for I420 instead since the * vout already has code to swap the buffers */ vd->fmt.i_chroma = VLC_CODEC_I420; case VLC_CODEC_I420: break; case VLC_CODEC_RGB16: case VLC_CODEC_RGB32: case VLC_CODEC_RGBA: SetRGBMask(&vd->fmt); video_format_FixRgb(&vd->fmt); break; default: goto error; } } sys->p_window = AndroidWindow_New(sys, &vd->fmt, true); if (!sys->p_window) goto error; if (SetupWindowSurface(sys, 0) != 0) goto error; /* use software rotation if we don't use private anw */ if (!sys->p_window->b_opaque && !sys->p_window->b_use_priv) video_format_ApplyRotation(&vd->fmt, &vd->fmt); msg_Dbg(vd, "using %s", sys->p_window->b_opaque ? "opaque" : (sys->p_window->b_use_priv ? "ANWP" : "ANW")); video_format_ApplyRotation(&sub_fmt, &vd->fmt); sub_fmt.i_chroma = subpicture_chromas[0]; SetRGBMask(&sub_fmt); video_format_FixRgb(&sub_fmt); sys->p_sub_window = AndroidWindow_New(sys, &sub_fmt, false); if (!sys->p_sub_window) goto error; FixSubtitleFormat(sys); sys->i_sub_last_order = -1; /* Export the subpicture capability of this vout. */ vd->info.subpicture_chromas = subpicture_chromas; /* Setup vout_display */ vd->pool = Pool; vd->prepare = Prepare; vd->display = Display; vd->control = Control; vd->manage = Manage; /* Fix initial state */ vout_display_SendEventFullscreen(vd, true); SendEventDisplaySize(vd); return VLC_SUCCESS; error: Close(p_this); return VLC_ENOMEM; }
static int Open(vlc_object_t *p_this) { vout_display_t *vd = (vout_display_t *)p_this; /* */ if (vlc_mutex_trylock(&single_instance) != 0) { msg_Err(vd, "Can't start more than one instance at a time"); return VLC_EGENERIC; } /* Allocate structure */ vout_display_sys_t *sys = (struct vout_display_sys_t*) calloc(1, sizeof(*sys)); if (!sys) { vlc_mutex_unlock(&single_instance); return VLC_ENOMEM; } /* */ sys->p_library = LoadNativeWindowAPI(&sys->native_window); sys->s_unlockAndPost = (Surface_unlockAndPost)sys->native_window.unlockAndPost; if (!sys->p_library) sys->p_library = InitLibrary(sys); if (!sys->p_library) { free(sys); msg_Err(vd, "Could not initialize libandroid.so/libui.so/libgui.so/libsurfaceflinger_client.so!"); vlc_mutex_unlock(&single_instance); return VLC_EGENERIC; } /* Setup chroma */ video_format_t fmt = vd->fmt; char *psz_fcc = var_InheritString(vd, CFG_PREFIX "chroma"); if( psz_fcc ) { fmt.i_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_fcc); free(psz_fcc); } else fmt.i_chroma = VLC_CODEC_RGB32; switch(fmt.i_chroma) { case VLC_CODEC_YV12: /* avoid swscale usage by asking for I420 instead since the * vout already has code to swap the buffers */ fmt.i_chroma = VLC_CODEC_I420; case VLC_CODEC_I420: break; case VLC_CODEC_RGB16: fmt.i_bmask = 0x0000001f; fmt.i_gmask = 0x000007e0; fmt.i_rmask = 0x0000f800; break; case VLC_CODEC_RGB32: fmt.i_rmask = 0x000000ff; fmt.i_gmask = 0x0000ff00; fmt.i_bmask = 0x00ff0000; break; default: return VLC_EGENERIC; } video_format_FixRgb(&fmt); msg_Dbg(vd, "Pixel format %4.4s", (char*)&fmt.i_chroma); sys->fmt = fmt; /* Create the associated picture */ picture_sys_t *picsys = malloc(sizeof(*picsys)); if (unlikely(picsys == NULL)) goto enomem; picsys->sys = sys; picture_resource_t resource = { .p_sys = picsys }; picture_t *picture = picture_NewFromResource(&fmt, &resource); if (!picture) { free(picsys); goto enomem; } /* Wrap it into a picture pool */ picture_pool_configuration_t pool_cfg; memset(&pool_cfg, 0, sizeof(pool_cfg)); pool_cfg.picture_count = 1; pool_cfg.picture = &picture; pool_cfg.lock = AndroidLockSurface; pool_cfg.unlock = AndroidUnlockSurface; sys->pool = picture_pool_NewExtended(&pool_cfg); if (!sys->pool) { picture_Release(picture); goto enomem; } /* Setup vout_display */ vd->sys = sys; vd->fmt = fmt; vd->pool = Pool; vd->display = Display; vd->control = Control; vd->prepare = NULL; vd->manage = NULL; /* Fix initial state */ vout_display_SendEventFullscreen(vd, false); sys->i_sar_num = vd->source.i_sar_num; sys->i_sar_den = vd->source.i_sar_den; return VLC_SUCCESS; enomem: dlclose(sys->p_library); free(sys); vlc_mutex_unlock(&single_instance); return VLC_ENOMEM; }
static int Open(vlc_object_t *p_this) { vout_display_t *vd = (vout_display_t*)p_this; video_format_t fmt = vd->fmt; if (fmt.i_chroma != VLC_CODEC_ANDROID_OPAQUE) return VLC_EGENERIC; /* Allocate structure */ vout_display_sys_t *sys = (struct vout_display_sys_t*)calloc(1, sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->p_library = LoadNativeWindowAPI(&sys->native_window); if (!sys->p_library) { free(sys); msg_Err(vd, "Could not initialize NativeWindow API."); return VLC_EGENERIC; } sys->fmt = fmt; video_format_t subpicture_format = sys->fmt; subpicture_format.i_chroma = VLC_CODEC_RGBA; /* Create a RGBA picture for rendering subtitles. */ sys->subtitles_picture = picture_NewFromFormat(&subpicture_format); /* Export the subpicture capability of this vout. */ vd->info.subpicture_chromas = subpicture_chromas; int i_pictures = POOL_SIZE; picture_t** pictures = calloc(sizeof(*pictures), i_pictures); if (!pictures) goto error; for (int i = 0; i < i_pictures; i++) { picture_sys_t *p_picsys = calloc(1, sizeof(*p_picsys)); if (unlikely(p_picsys == NULL)) goto error; picture_resource_t resource = { .p_sys = p_picsys }; picture_t *picture = picture_NewFromResource(&fmt, &resource); if (!picture) { free(p_picsys); goto error; } pictures[i] = picture; } /* Wrap it into a picture pool */ picture_pool_configuration_t pool_cfg; memset(&pool_cfg, 0, sizeof(pool_cfg)); pool_cfg.picture_count = i_pictures; pool_cfg.picture = pictures; pool_cfg.lock = LockSurface; pool_cfg.unlock = UnlockSurface; sys->pool = picture_pool_NewExtended(&pool_cfg); if (!sys->pool) { for (int i = 0; i < i_pictures; i++) picture_Release(pictures[i]); goto error; } /* Setup vout_display */ vd->sys = sys; vd->fmt = fmt; vd->pool = Pool; vd->display = Display; vd->control = Control; vd->prepare = NULL; vd->manage = Manage; /* Fix initial state */ vout_display_SendEventFullscreen(vd, false); return VLC_SUCCESS; error: free(pictures); Close(p_this); return VLC_ENOMEM; }