bool video_format_IsSimilar( const video_format_t *p_fmt1, const video_format_t *p_fmt2 ) { video_format_t v1 = *p_fmt1; video_format_t v2 = *p_fmt2; if( v1.i_chroma != v2.i_chroma ) return false; if( v1.i_width != v2.i_width || v1.i_height != v2.i_height || v1.i_visible_width != v2.i_visible_width || v1.i_visible_height != v2.i_visible_height || v1.i_x_offset != v2.i_x_offset || v1.i_y_offset != v2.i_y_offset ) return false; if( v1.i_sar_num * v2.i_sar_den != v2.i_sar_num * v1.i_sar_den ) return false; if( v1.i_chroma == VLC_CODEC_RGB15 || v1.i_chroma == VLC_CODEC_RGB16 || v1.i_chroma == VLC_CODEC_RGB24 || v1.i_chroma == VLC_CODEC_RGB32 ) { video_format_FixRgb( &v1 ); video_format_FixRgb( &v2 ); if( v1.i_rmask != v2.i_rmask || v1.i_gmask != v2.i_gmask || v1.i_bmask != v2.i_bmask ) return false; } return true; }
static int BuildChromaChain( filter_t *p_filter ) { es_format_t fmt_mid; int i_ret = VLC_EGENERIC; /* Now try chroma format list */ const vlc_fourcc_t *pi_allowed_chromas = get_allowed_chromas( p_filter ); for( int i = 0; pi_allowed_chromas[i]; i++ ) { const vlc_fourcc_t i_chroma = pi_allowed_chromas[i]; if( i_chroma == p_filter->fmt_in.i_codec || i_chroma == p_filter->fmt_out.i_codec ) continue; msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man", (char*)&i_chroma ); es_format_Copy( &fmt_mid, &p_filter->fmt_in ); fmt_mid.i_codec = fmt_mid.video.i_chroma = i_chroma; fmt_mid.video.i_rmask = 0; fmt_mid.video.i_gmask = 0; fmt_mid.video.i_bmask = 0; video_format_FixRgb(&fmt_mid.video); i_ret = CreateChain( p_filter, &fmt_mid ); es_format_Clean( &fmt_mid ); if( i_ret == VLC_SUCCESS ) break; } return i_ret; }
static int BuildFilterChain( filter_t *p_filter ) { es_format_t fmt_mid; int i_ret = VLC_EGENERIC; filter_sys_t *p_sys = p_filter->p_sys; /* Now try chroma format list */ const vlc_fourcc_t *pi_allowed_chromas = get_allowed_chromas( p_filter ); for( int i = 0; pi_allowed_chromas[i]; i++ ) { filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out ); const vlc_fourcc_t i_chroma = pi_allowed_chromas[i]; if( i_chroma == p_filter->fmt_in.i_codec || i_chroma == p_filter->fmt_out.i_codec ) continue; msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man", (char*)&i_chroma ); es_format_Copy( &fmt_mid, &p_filter->fmt_in ); fmt_mid.i_codec = fmt_mid.video.i_chroma = i_chroma; fmt_mid.video.i_rmask = 0; fmt_mid.video.i_gmask = 0; fmt_mid.video.i_bmask = 0; video_format_FixRgb(&fmt_mid.video); if( filter_chain_AppendConverter( p_sys->p_chain, NULL, &fmt_mid ) == VLC_SUCCESS ) { p_sys->p_video_filter = filter_chain_AppendFilter( p_sys->p_chain, p_filter->psz_name, p_filter->p_cfg, &fmt_mid, &fmt_mid ); if( p_sys->p_video_filter ) { filter_AddProxyCallbacks( p_filter, p_sys->p_video_filter, RestartFilterCallback ); if (p_sys->p_video_filter->pf_video_mouse != NULL) p_filter->pf_video_mouse = ChainMouse; es_format_Clean( &fmt_mid ); i_ret = VLC_SUCCESS; break; } } es_format_Clean( &fmt_mid ); } if( i_ret != VLC_SUCCESS ) filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out ); return i_ret; }
static int Open(vlc_object_t *p_this) { vout_display_t *vd = (vout_display_t *)p_this; vout_display_t *p_dec = vd; char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE]; picture_t** pictures = NULL; OMX_PARAM_PORTDEFINITIONTYPE *def; static OMX_CALLBACKTYPE callbacks = { OmxEventHandler, OmxEmptyBufferDone, OmxFillBufferDone }; if (InitOmxCore(p_this) != VLC_SUCCESS) return VLC_EGENERIC; int components = CreateComponentsList(p_this, "iv_renderer", ppsz_components); if (components <= 0) { DeinitOmxCore(); return VLC_EGENERIC; } /* Allocate structure */ vout_display_sys_t *p_sys = (struct vout_display_sys_t*) calloc(1, sizeof(*p_sys)); if (!p_sys) { DeinitOmxCore(); return VLC_ENOMEM; } vd->sys = p_sys; strcpy(p_sys->psz_component, ppsz_components[0]); /* Load component */ OMX_ERRORTYPE omx_error = pf_get_handle(&p_sys->omx_handle, p_sys->psz_component, vd, &callbacks); CHECK_ERROR(omx_error, "OMX_GetHandle(%s) failed (%x: %s)", p_sys->psz_component, omx_error, ErrorToString(omx_error)); InitOmxEventQueue(&p_sys->event_queue); OMX_FIFO_INIT(&p_sys->port.fifo, pOutputPortPrivate); p_sys->port.b_direct = false; p_sys->port.b_flushed = true; OMX_PORT_PARAM_TYPE param; OMX_INIT_STRUCTURE(param); omx_error = OMX_GetParameter(p_sys->omx_handle, OMX_IndexParamVideoInit, ¶m); CHECK_ERROR(omx_error, "OMX_GetParameter(OMX_IndexParamVideoInit) failed (%x: %s)", omx_error, ErrorToString(omx_error)); p_sys->port.i_port_index = param.nStartPortNumber; p_sys->port.b_valid = true; p_sys->port.omx_handle = p_sys->omx_handle; def = &p_sys->port.definition; OMX_INIT_STRUCTURE(*def); def->nPortIndex = p_sys->port.i_port_index; omx_error = OMX_GetParameter(p_sys->omx_handle, OMX_IndexParamPortDefinition, def); CHECK_ERROR(omx_error, "OMX_GetParameter(OMX_IndexParamPortDefinition) failed (%x: %s)", omx_error, ErrorToString(omx_error)); #define ALIGN(x, y) (((x) + ((y) - 1)) & ~((y) - 1)) def->format.video.nFrameWidth = vd->fmt.i_width; def->format.video.nFrameHeight = vd->fmt.i_height; def->format.video.nStride = 0; def->format.video.nSliceHeight = 0; p_sys->port.definition.format.video.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; if (!strcmp(p_sys->psz_component, "OMX.broadcom.video_render")) { def->format.video.nSliceHeight = ALIGN(def->format.video.nFrameHeight, 16); } omx_error = OMX_SetParameter(p_sys->omx_handle, OMX_IndexParamPortDefinition, &p_sys->port.definition); CHECK_ERROR(omx_error, "OMX_SetParameter(OMX_IndexParamPortDefinition) failed (%x: %s)", omx_error, ErrorToString(omx_error)); OMX_GetParameter(p_sys->omx_handle, OMX_IndexParamPortDefinition, &p_sys->port.definition); if (def->format.video.nStride < (int) def->format.video.nFrameWidth) def->format.video.nStride = def->format.video.nFrameWidth; if (def->format.video.nSliceHeight < def->format.video.nFrameHeight) def->format.video.nSliceHeight = def->format.video.nFrameHeight; p_sys->port.pp_buffers = malloc(p_sys->port.definition.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE*)); p_sys->port.i_buffers = p_sys->port.definition.nBufferCountActual; omx_error = OMX_SendCommand(p_sys->omx_handle, OMX_CommandStateSet, OMX_StateIdle, 0); CHECK_ERROR(omx_error, "OMX_CommandStateSet Idle failed (%x: %s)", omx_error, ErrorToString(omx_error)); unsigned int i; for (i = 0; i < p_sys->port.i_buffers; i++) { omx_error = OMX_AllocateBuffer(p_sys->omx_handle, &p_sys->port.pp_buffers[i], p_sys->port.i_port_index, 0, p_sys->port.definition.nBufferSize); if (omx_error != OMX_ErrorNone) break; OMX_FIFO_PUT(&p_sys->port.fifo, p_sys->port.pp_buffers[i]); } if (omx_error != OMX_ErrorNone) { p_sys->port.i_buffers = i; for (i = 0; i < p_sys->port.i_buffers; i++) OMX_FreeBuffer(p_sys->omx_handle, p_sys->port.i_port_index, p_sys->port.pp_buffers[i]); msg_Err(vd, "OMX_AllocateBuffer failed (%x: %s)", omx_error, ErrorToString(omx_error)); goto error; } omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0); CHECK_ERROR(omx_error, "Wait for Idle failed (%x: %s)", omx_error, ErrorToString(omx_error)); omx_error = OMX_SendCommand(p_sys->omx_handle, OMX_CommandStateSet, OMX_StateExecuting, 0); CHECK_ERROR(omx_error, "OMX_CommandStateSet Executing failed (%x: %s)", omx_error, ErrorToString(omx_error)); omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0); CHECK_ERROR(omx_error, "Wait for Executing failed (%x: %s)", omx_error, ErrorToString(omx_error)); if (!strcmp(p_sys->psz_component, "OMX.broadcom.video_render")) { OMX_CONFIG_DISPLAYREGIONTYPE config_display; OMX_INIT_STRUCTURE(config_display); config_display.nPortIndex = p_sys->port.i_port_index; config_display.set = OMX_DISPLAY_SET_SRC_RECT; config_display.src_rect.width = vd->cfg->display.width; config_display.src_rect.height = vd->cfg->display.height; OMX_SetConfig(p_sys->omx_handle, OMX_IndexConfigDisplayRegion, &config_display); config_display.set = OMX_DISPLAY_SET_FULLSCREEN; config_display.fullscreen = OMX_TRUE; OMX_SetConfig(p_sys->omx_handle, OMX_IndexConfigDisplayRegion, &config_display); UpdateDisplaySize(vd, vd->cfg); } /* Setup chroma */ video_format_t fmt = vd->fmt; fmt.i_chroma = VLC_CODEC_I420; video_format_FixRgb(&fmt); /* Setup vout_display */ vd->fmt = fmt; vd->pool = Pool; vd->display = Display; vd->control = Control; vd->prepare = NULL; vd->manage = NULL; /* Create the associated picture */ pictures = calloc(p_sys->port.i_buffers, sizeof(*pictures)); if (!pictures) goto error; for (unsigned int i = 0; i < p_sys->port.i_buffers; i++) { picture_sys_t *picsys = malloc(sizeof(*picsys)); if (unlikely(picsys == NULL)) goto error; picsys->sys = p_sys; picture_resource_t resource = { .p_sys = picsys }; picture_t *picture = picture_NewFromResource(&fmt, &resource); if (unlikely(picture == NULL)) { free(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 = p_sys->port.i_buffers; pool_cfg.picture = pictures; pool_cfg.lock = LockSurface; pool_cfg.unlock = UnlockSurface; p_sys->pool = picture_pool_NewExtended(&pool_cfg); if (!p_sys->pool) { for (unsigned int i = 0; i < p_sys->port.i_buffers; i++) picture_Release(pictures[i]); goto error; } /* Fix initial state */ vout_display_SendEventFullscreen(vd, true); free(pictures); return VLC_SUCCESS; error: free(pictures); Close(p_this); return VLC_EGENERIC; }
/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with a complete image. ****************************************************************************/ static int DecodeBlock( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = (decoder_sys_t *) p_dec->p_sys; picture_t *p_pic = NULL; int32_t i_width, i_height; RsvgHandle *rsvg = NULL; cairo_surface_t *surface = NULL; cairo_t *cr = NULL; if( p_block == NULL ) /* No Drain */ return VLCDEC_SUCCESS; if( p_block->i_flags & BLOCK_FLAG_CORRUPTED) { block_Release( p_block ); return VLCDEC_SUCCESS; } rsvg = rsvg_handle_new_from_data( p_block->p_buffer, p_block->i_buffer, NULL ); if( !rsvg ) goto done; RsvgDimensionData dim; rsvg_handle_get_dimensions( rsvg, &dim ); if( p_sys->f_scale > 0.0 ) { i_width = (int32_t)(p_sys->f_scale * dim.width); i_height = (int32_t)(p_sys->f_scale * dim.height); } else { /* Keep aspect */ if( p_sys->i_width < 0 && p_sys->i_height > 0 ) { i_width = dim.width * p_sys->i_height / dim.height; i_height = p_sys->i_height; } else if( p_sys->i_width > 0 && p_sys->i_height < 0 ) { i_width = p_sys->i_width; i_height = dim.height * p_sys->i_width / dim.height; } else if( p_sys->i_width > 0 && p_sys->i_height > 0 ) { i_width = dim.width * p_sys->i_height / dim.height; i_height = p_sys->i_height; } else { i_width = dim.width; i_height = dim.height; } } p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma = VLC_CODEC_BGRA; p_dec->fmt_out.video.i_width = i_width; p_dec->fmt_out.video.i_height = i_height; p_dec->fmt_out.video.i_visible_width = i_width; p_dec->fmt_out.video.i_visible_height = i_height; p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; p_dec->fmt_out.video.i_rmask = 0x80800000; /* Since librsvg v1.0 */ p_dec->fmt_out.video.i_gmask = 0x0000ff00; p_dec->fmt_out.video.i_bmask = 0x000000ff; video_format_FixRgb(&p_dec->fmt_out.video); /* Get a new picture */ if( decoder_UpdateVideoFormat( p_dec ) ) goto done; p_pic = decoder_NewPicture( p_dec ); if( !p_pic ) goto done; /* NOTE: Do not use the stride calculation from cairo, because it is wrong: * stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, dim.width); * Use the stride from VLC its picture_t::p[0].i_pitch, which is correct. */ memset(p_pic->p[0].p_pixels, 0, p_pic->p[0].i_pitch * p_pic->p[0].i_lines); surface = cairo_image_surface_create_for_data( p_pic->p->p_pixels, CAIRO_FORMAT_ARGB32, i_width, i_height, p_pic->p[0].i_pitch ); if( !surface ) { picture_Release( p_pic ); p_pic = NULL; goto done; } /* Decode picture */ cr = cairo_create( surface ); if( !cr ) { picture_Release( p_pic ); p_pic = NULL; goto done; } if ( i_width != dim.width || i_height != dim.height ) { double sw, sh; if ( p_sys->f_scale > 0.0 && !(p_sys->i_width > 0 || p_sys->i_height > 0) ) sw = sh = p_sys->f_scale; else { double aspect = (double) (dim.width * p_dec->fmt_out.video.i_sar_num) / (dim.height * p_dec->fmt_out.video.i_sar_den); sw = aspect * i_width / dim.width; sh = aspect * i_height / dim.height; } cairo_scale(cr, sw, sh); } if( !rsvg_handle_render_cairo( rsvg, cr ) ) { picture_Release( p_pic ); p_pic = NULL; goto done; } p_pic->date = p_block->i_pts != VLC_TICK_INVALID ? p_block->i_pts : p_block->i_dts; done: if( rsvg ) g_object_unref( G_OBJECT( rsvg ) ); if( cr ) cairo_destroy( cr ); if( surface ) cairo_surface_destroy( surface ); block_Release( p_block ); if( p_pic != NULL ) decoder_QueueVideo( p_dec, p_pic ); return VLCDEC_SUCCESS; }
static int OpenCommon(vout_display_t *vd, const vout_display_cfg_t *cfg, video_format_t *fmtp) { vout_display_sys_t *sys; video_format_t fmt, sub_fmt; vout_window_t *embed = cfg->window; if (embed->type != VOUT_WINDOW_TYPE_ANDROID_NATIVE) return VLC_EGENERIC; fmt = *fmtp; if (embed == NULL) return VLC_EGENERIC; assert(embed->handle.anativewindow); AWindowHandler *p_awh = embed->handle.anativewindow; if (!AWindowHandler_canSetVideoLayout(p_awh)) { /* It's better to use gles2 if we are not able to change the video * layout */ return VLC_EGENERIC; } /* Allocate structure */ vd->sys = sys = (struct vout_display_sys_t*)calloc(1, sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->embed = embed; sys->p_awh = p_awh; sys->anw = AWindowHandler_getANativeWindowAPI(sys->p_awh); sys->i_display_width = cfg->display.width; sys->i_display_height = cfg->display.height; if (fmt.i_chroma != VLC_CODEC_ANDROID_OPAQUE) { /* Setup chroma */ 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: case VLC_CODEC_RGB32: case VLC_CODEC_RGBA: SetRGBMask(&fmt); video_format_FixRgb(&fmt); break; default: goto error; } } sys->p_window = AndroidWindow_New(vd, &fmt, AWindow_Video); if (!sys->p_window) goto error; if (AndroidWindow_Setup(sys, sys->p_window, 0) != 0) goto error; /* use software rotation if we don't do opaque */ if (!sys->p_window->b_opaque) video_format_TransformTo(&fmt, ORIENT_NORMAL); msg_Dbg(vd, "using %s", sys->p_window->b_opaque ? "opaque" : "ANW"); video_format_ApplyRotation(&sub_fmt, &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); 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; } else if (!vd->obj.force && sys->p_window->b_opaque) { msg_Warn(vd, "cannot blend subtitles with an opaque surface, " "trying next vout"); goto error; } *fmtp = fmt; /* Setup vout_display */ vd->pool = Pool; vd->prepare = Prepare; vd->display = Display; vd->control = Control; vd->info.is_slow = !sys->p_window->b_opaque; return VLC_SUCCESS; error: Close(vd); return VLC_EGENERIC; }
static int BuildChromaChain( filter_t *p_filter ) { filter_sys_t *p_sys = p_filter->p_sys; es_format_t fmt_mid; /* We have to protect ourself against a too high recursion */ const char *psz_option = MODULE_STRING"-level"; int i_level = 0; for( const config_chain_t *c = p_filter->p_cfg; c != NULL; c = c->p_next) { if( c->psz_name && c->psz_value && !strcmp(c->psz_name, psz_option) ) { i_level = atoi(c->psz_value); if( i_level < 0 || i_level > CHAIN_LEVEL_MAX ) { msg_Err( p_filter, "Too high level of recursion (%d)", i_level ); return VLC_EGENERIC; } break; } } /* */ int i_ret = VLC_EGENERIC; /* */ config_chain_t cfg_level; memset(&cfg_level, 0, sizeof(cfg_level)); cfg_level.psz_name = strdup(psz_option); if( asprintf( &cfg_level.psz_value, "%d", i_level + 1) < 0 ) cfg_level.psz_value = NULL; if( !cfg_level.psz_name || !cfg_level.psz_value ) goto exit; /* Now try chroma format list */ for( int i = 0; pi_allowed_chromas[i]; i++ ) { const vlc_fourcc_t i_chroma = pi_allowed_chromas[i]; if( i_chroma == p_filter->fmt_in.i_codec || i_chroma == p_filter->fmt_out.i_codec ) continue; msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man", (char*)&i_chroma ); es_format_Copy( &fmt_mid, &p_filter->fmt_in ); fmt_mid.i_codec = fmt_mid.video.i_chroma = i_chroma; fmt_mid.video.i_rmask = 0; fmt_mid.video.i_gmask = 0; fmt_mid.video.i_bmask = 0; video_format_FixRgb(&fmt_mid.video); filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out ); i_ret = CreateChain( p_sys->p_chain, &fmt_mid, &cfg_level ); es_format_Clean( &fmt_mid ); if( i_ret == VLC_SUCCESS ) break; } exit: free( cfg_level.psz_name ); free( cfg_level.psz_value ); return i_ret; }
static int Open(vlc_object_t *object) { vout_display_t *vd = (vout_display_t *)object; vout_display_sys_t *sys; /* Allocate instance and initialize some members */ vd->sys = sys = malloc(sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->is_first = false; sys->is_yuv4mpeg2 = var_CreateGetBool(vd, CFG_PREFIX "yuv4mpeg2"); sys->pool = NULL; /* */ char *psz_fcc = var_CreateGetNonEmptyString(vd, CFG_PREFIX "chroma"); const vlc_fourcc_t requested_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_fcc); free(psz_fcc); const vlc_fourcc_t chroma = requested_chroma ? requested_chroma : VLC_CODEC_I420; if (sys->is_yuv4mpeg2) { switch (chroma) { case VLC_CODEC_YV12: case VLC_CODEC_I420: case VLC_CODEC_J420: break; default: msg_Err(vd, "YUV4MPEG2 mode needs chroma YV12 not %4.4s as requested", (char *)&chroma); free(sys); return VLC_EGENERIC; } } msg_Dbg(vd, "Using chroma %4.4s", (char *)&chroma); /* */ char *name = var_CreateGetNonEmptyString(vd, CFG_PREFIX "file"); if (!name) { msg_Err(vd, "Empty file name"); free(sys); return VLC_EGENERIC; } sys->f = vlc_fopen(name, "wb"); if (!sys->f) { msg_Err(vd, "Failed to open %s", name); free(name); free(sys); return VLC_EGENERIC; } msg_Dbg(vd, "Writing data to %s", name); free(name); /* */ video_format_t fmt = vd->fmt; fmt.i_chroma = chroma; video_format_FixRgb(&fmt); /* */ vout_display_info_t info = vd->info; info.has_hide_mouse = true; /* */ vd->fmt = fmt; vd->info = info; vd->pool = Pool; vd->prepare = NULL; vd->display = Display; vd->control = Control; vd->manage = Manage; vout_display_SendEventFullscreen(vd, false); return VLC_SUCCESS; }
static int Open(vlc_object_t *p_this) { vout_display_t *vd = (vout_display_t *)p_this; vout_display_sys_t *sys; void *p_library; /* */ 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 */ sys = (struct vout_display_sys_t*) calloc(1, sizeof(*sys)); if (!sys) { vlc_mutex_unlock(&single_instance); return VLC_ENOMEM; } /* */ sys->p_library = p_library = InitLibrary(sys); if (!p_library) { free(sys); msg_Err(vd, "Could not initialize libui.so/libgui.so/libsurfaceflinger_client.so!"); vlc_mutex_unlock(&single_instance); return VLC_EGENERIC; } /* Setup chroma */ video_format_t fmt = vd->fmt; fmt.i_chroma = VLC_CODEC_RGB32; fmt.i_rmask = 0x000000ff; fmt.i_gmask = 0x0000ff00; fmt.i_bmask = 0x00ff0000; video_format_FixRgb(&fmt); /* Create the associated picture */ picture_resource_t *rsc = &sys->resource; rsc->p_sys = malloc(sizeof(*rsc->p_sys)); if (!rsc->p_sys) goto enomem; rsc->p_sys->sys = sys; for (int i = 0; i < PICTURE_PLANE_MAX; i++) { rsc->p[i].p_pixels = NULL; rsc->p[i].i_pitch = 0; rsc->p[i].i_lines = 0; } picture_t *picture = picture_NewFromResource(&fmt, rsc); if (!picture) 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: free(rsc->p_sys); free(sys); dlclose(p_library); 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; vout_display_sys_t *sys; void *p_library; /* */ 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 */ sys = (struct vout_display_sys_t*) calloc(1, sizeof(*sys)); if (!sys) { vlc_mutex_unlock(&single_instance); return VLC_ENOMEM; } /* */ sys->p_library = p_library = InitLibrary(sys); if (!p_library) { free(sys); msg_Err(vd, "Could not initialize 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); /* Create the associated picture */ picture_resource_t *rsc = &sys->resource; rsc->p_sys = malloc(sizeof(*rsc->p_sys)); if (!rsc->p_sys) goto enomem; rsc->p_sys->sys = sys; for (int i = 0; i < PICTURE_PLANE_MAX; i++) { rsc->p[i].p_pixels = NULL; rsc->p[i].i_pitch = 0; rsc->p[i].i_lines = 0; } picture_t *picture = picture_NewFromResource(&fmt, rsc); if (!picture) 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: free(rsc->p_sys); free(sys); dlclose(p_library); 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; 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; 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; }
static int Open(vlc_object_t *p_this) { vout_display_t *vd = (vout_display_t *)p_this; video_format_t fmt; video_format_ApplyRotation(&fmt, &vd->fmt); if (fmt.i_chroma == VLC_CODEC_ANDROID_OPAQUE) return VLC_EGENERIC; if (vout_display_IsWindowed(vd)) return VLC_EGENERIC; /* Allocate structure */ vout_display_sys_t *sys = (struct vout_display_sys_t*) calloc(1, sizeof(*sys)); if (!sys) goto error; /* */ sys->p_library = InitLibrary(sys); if (!sys->p_library) { msg_Err(vd, "Could not initialize libandroid.so/libui.so/libgui.so/libsurfaceflinger_client.so!"); goto error; } /* Setup chroma */ 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_RGB16: fmt.i_bmask = 0x0000001f; fmt.i_gmask = 0x000007e0; fmt.i_rmask = 0x0000f800; break; case VLC_CODEC_YV12: case VLC_CODEC_I420: fmt.i_chroma = VLC_CODEC_RGB32; 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->i_android_hal = ChromaToAndroidHal(fmt.i_chroma); if (sys->i_android_hal == -1) goto error; sys->fmt = fmt; UpdateLayout(sys); /* Create the associated picture */ picture_sys_t *picsys = calloc(1, sizeof(picture_sys_t)); if (unlikely(picsys == NULL)) goto error; picsys->sys = sys; picture_resource_t resource = { .p_sys = picsys }; picture_t *picture = picture_NewFromResource(&fmt, &resource); if (!picture) { free(picsys); goto error; } /* 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 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: Close(p_this); return VLC_ENOMEM; }
static int Open( vlc_object_t *p_this ) { vout_display_t *vd = (vout_display_t*)p_this; vout_display_sys_t *sys; Evas_Object *p_evas; if( vout_display_IsWindowed( vd ) ) return VLC_EGENERIC; p_evas = var_InheritAddress( p_this, "drawable-evasobject" ); if( !p_evas ) return VLC_EGENERIC; vd->sys = sys = (struct vout_display_sys_t *) calloc( 1, sizeof(*sys) ); if( !sys ) return VLC_ENOMEM; vlc_mutex_init( &sys->cb_lock ); vlc_cond_init( &sys->cb_wait ); fifo_init( &sys->buffer_fifo ); fifo_init( &sys->event_fifo ); sys->p_evas = p_evas; msg_Dbg( vd, "request video format: %4.4s", (const char *)&vd->fmt.i_chroma ); /* Evas Initialisation must be done from the Mainloop */ if( EcoreMainLoopCallSync( vd, EvasInitMainloopCb ) ) { msg_Err( vd, "EvasInitMainloopCb failed" ); Close( p_this ); return VLC_EGENERIC; } for( unsigned int i = 0; i < PICTURE_PLANE_MAX; ++i ) sys->i_planes_order[i] = i; switch( vd->fmt.i_chroma ) { case VLC_CODEC_RGB32: case VLC_CODEC_RGB16: video_format_FixRgb(&vd->fmt); break; case VLC_CODEC_YV12: sys->i_planes_order[1] = 2; sys->i_planes_order[2] = 1; default: break; } msg_Dbg( vd, "got video format: %4.4s, size: %dx%d", (const char *)&vd->fmt.i_chroma, sys->i_width, sys->i_height ); /* Setup vout_display */ vd->pool = Pool; vd->prepare = NULL; vd->display = Display; vd->control = Control; vd->manage = Manage; return VLC_SUCCESS; }