/** * Create an Android native window. */ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg) { ANativeWindow *p_anw; if (cfg->type != VOUT_WINDOW_TYPE_INVALID && cfg->type != VOUT_WINDOW_TYPE_ANDROID_NATIVE) return VLC_EGENERIC; vout_window_sys_t *p_sys = malloc(sizeof (*p_sys)); if (p_sys == NULL) return VLC_ENOMEM; p_sys->p_awh = AWindowHandler_new(VLC_OBJECT(wnd)); if (!p_sys->p_awh) goto error; p_anw = AWindowHandler_getANativeWindow(p_sys->p_awh, AWindow_Video); if (!p_anw) goto error; wnd->type = VOUT_WINDOW_TYPE_ANDROID_NATIVE; wnd->handle.anativewindow = p_anw; wnd->control = Control; wnd->sys = p_sys; // Set the Java surface size. AWindowHandler_setWindowLayout(p_sys->p_awh, cfg->width, cfg->height, cfg->width, cfg->height, 1, 1); return VLC_SUCCESS; error: if (p_sys->p_awh) AWindowHandler_destroy(p_sys->p_awh); free(p_sys); return VLC_EGENERIC; }
/***************************************************************************** * StartMediaCodec: Create the mediacodec instance *****************************************************************************/ static int StartMediaCodec(decoder_t *p_dec) { decoder_sys_t *p_sys = p_dec->p_sys; int i_ret = 0; union mc_api_args args; if (p_dec->fmt_in.i_extra && !p_sys->p_csd) { /* Try first to configure specific Video CSD */ if (p_dec->fmt_in.i_cat == VIDEO_ES) i_ret = ParseVideoExtra(p_dec, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra); if (i_ret != VLC_SUCCESS) return i_ret; /* Set default CSD if ParseVideoExtra failed to configure one */ if (!p_sys->p_csd) { struct csd csd; csd.p_buf = p_dec->fmt_in.p_extra; csd.i_size = p_dec->fmt_in.i_extra; CSDDup(p_dec, &csd, 1); } p_sys->i_csd_send = 0; } if (p_dec->fmt_in.i_cat == VIDEO_ES) { if (!p_sys->u.video.i_width || !p_sys->u.video.i_height) { msg_Err(p_dec, "invalid size, abort MediaCodec"); return VLC_EGENERIC; } args.video.i_width = p_sys->u.video.i_width; args.video.i_height = p_sys->u.video.i_height; switch (p_dec->fmt_in.video.orientation) { case ORIENT_ROTATED_90: args.video.i_angle = 90; break; case ORIENT_ROTATED_180: args.video.i_angle = 180; break; case ORIENT_ROTATED_270: args.video.i_angle = 270; break; default: args.video.i_angle = 0; } /* Check again the codec name if h264 profile changed */ if (p_dec->fmt_in.i_codec == VLC_CODEC_H264 && !p_sys->u.video.i_h264_profile) { h264_get_profile_level(&p_dec->fmt_in, &p_sys->u.video.i_h264_profile, NULL, NULL); if (p_sys->u.video.i_h264_profile) { free(p_sys->psz_name); p_sys->psz_name = MediaCodec_GetName(VLC_OBJECT(p_dec), p_sys->mime, p_sys->u.video.i_h264_profile); if (!p_sys->psz_name) return VLC_EGENERIC; } } if (!p_sys->u.video.p_awh && var_InheritBool(p_dec, CFG_PREFIX "dr")) { if ((p_sys->u.video.p_awh = AWindowHandler_new(VLC_OBJECT(p_dec)))) { /* Direct rendering: * The surface must be released by the Vout before calling * start. Request a valid OPAQUE Vout to release any non-OPAQUE * Vout that will release the surface. */ p_dec->fmt_out.video.i_width = p_sys->u.video.i_width; p_dec->fmt_out.video.i_height = p_sys->u.video.i_height; p_dec->fmt_out.i_codec = VLC_CODEC_ANDROID_OPAQUE; decoder_UpdateVideoFormat(p_dec); } } args.video.p_awh = p_sys->u.video.p_awh; } else { date_Set(&p_sys->u.audio.i_end_date, VLC_TS_INVALID); args.audio.i_sample_rate = p_dec->fmt_in.audio.i_rate; args.audio.i_channel_count = p_dec->p_sys->u.audio.i_channels; } return p_sys->api->start(p_sys->api, p_sys->psz_name, p_sys->mime, &args); }
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; /* Allocate structure */ vd->sys = sys = (struct vout_display_sys_t*)calloc(1, sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->p_awh = AWindowHandler_new(p_this); if (!sys->p_awh) { free(sys); msg_Err(vd, "AWindowHandler_new failed"); return VLC_EGENERIC; } sys->anw = AWindowHandler_getANativeWindowAPI(sys->p_awh); #ifdef USE_ANWP sys->anwp = AWindowHandler_getANativeWindowPrivAPI(sys->p_awh); if (!sys->anwp) 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(vd, &vd->fmt, AWindow_Video, true); if (!sys->p_window) goto error; if (AndroidWindow_Setup(sys, sys->p_window, 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(vd, &sub_fmt, AWindow_Subtitles, false); if (sys->p_sub_window) { 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; }