static picture_pool_t *Pool(vout_display_t *vd, unsigned count) { vout_display_sys_t *sys = vd->sys; if (sys->pool) return sys->pool; if (count > sys->count) count = sys->count; // sunqueen modify start // picture_t *pictures[count]; picture_t **pictures; pictures = (picture_t **)malloc(sizeof(picture_t *) * count); // sunqueen modify end for (unsigned i = 0; i < count; i++) { picture_sys_t *picsys = (picture_sys_t *)malloc(sizeof (*picsys)); // sunqueen modify if (unlikely(picsys == NULL)) { count = i; break; } picsys->sys = sys; picsys->id = NULL; picture_resource_t rsc = { /*.p_sys =*/ picsys }; // sunqueen modify for (unsigned i = 0; i < PICTURE_PLANE_MAX; i++) { /* vmem-lock is responsible for the allocation */ rsc.p[i].p_pixels = NULL; rsc.p[i].i_lines = sys->lines[i]; rsc.p[i].i_pitch = sys->pitches[i]; } pictures[i] = picture_NewFromResource(&vd->fmt, &rsc); if (!pictures[i]) { free(rsc.p_sys); count = i; break; } } /* */ picture_pool_configuration_t pool; memset(&pool, 0, sizeof(pool)); pool.picture_count = count; pool.picture = pictures; pool.lock = Lock; pool.unlock = Unlock; sys->pool = picture_pool_NewExtended(&pool); if (!sys->pool) { for (unsigned i = 0; i < count; i++) picture_Release(pictures[i]); } free(pictures); // sunqueen add return sys->pool; }
static picture_pool_t * tc_anop_get_pool(const opengl_tex_converter_t *tc, const video_format_t *fmt, unsigned requested_count, const GLuint *textures) { struct priv *priv = tc->priv; priv->stex = SurfaceTexture_create(tc->parent, textures[0]); if (priv->stex == NULL) { msg_Err(tc->parent, "tc_anop_get_pool: SurfaceTexture_create failed"); return NULL; } #define FORCED_COUNT 31 requested_count = FORCED_COUNT; picture_t *picture[FORCED_COUNT] = {NULL, }; unsigned count; for (count = 0; count < requested_count; count++) { picture_sys_t *p_picsys = calloc(1, sizeof(*p_picsys)); if (unlikely(p_picsys == NULL)) break; picture_resource_t rsc = { .p_sys = p_picsys, .pf_destroy = AndroidOpaquePicture_DetachVout, }; p_picsys->hw.b_vd_ref = true; p_picsys->hw.p_surface = SurfaceTexture_getANativeWindow(priv->stex); p_picsys->hw.p_jsurface = SurfaceTexture_getSurface(priv->stex); p_picsys->hw.i_index = -1; vlc_mutex_init(&p_picsys->hw.lock); picture[count] = picture_NewFromResource(fmt, &rsc); if (!picture[count]) { free(p_picsys); break; } } if (count <= 0) goto error; /* Wrap the pictures into a pool */ picture_pool_configuration_t pool_cfg = { .picture_count = requested_count, .picture = picture, .lock = pool_lock_pic, .unlock = pool_unlock_pic, }; picture_pool_t *pool = picture_pool_NewExtended(&pool_cfg); if (!pool) goto error; return pool; error: SurfaceTexture_release(priv->stex); return NULL; }
static picture_pool_t * PoolAlloc( vout_display_t *vd, unsigned i_requested_count ) { picture_t **pp_pics = NULL; picture_pool_t *p_pool; picture_pool_configuration_t pool_cfg; msg_Dbg(vd, "PoolAlloc, requested_count: %d", i_requested_count); i_requested_count++; /* picture owned by evas */ if( BuffersSetup( vd, &vd->fmt, &i_requested_count) ) { msg_Err( vd, "BuffersSetup failed" ); return NULL; } if( i_requested_count <= 1 ) { msg_Err( vd, "not enough buffers allocated" ); goto error; } i_requested_count--; msg_Dbg( vd, "PoolAlloc, got: %d", i_requested_count ); if( !( pp_pics = calloc( i_requested_count, sizeof(picture_t) ) ) ) goto error; for( unsigned int i = 0; i < i_requested_count; ++i ) { if( !( pp_pics[i] = PictureAlloc( vd ) ) ) { i_requested_count = i; msg_Err( vd, "PictureAlloc failed" ); goto error; } } memset( &pool_cfg, 0, sizeof(pool_cfg) ); pool_cfg.picture_count = i_requested_count; pool_cfg.picture = pp_pics; pool_cfg.lock = PoolLockPicture; pool_cfg.unlock = PoolUnlockPicture; p_pool = picture_pool_NewExtended( &pool_cfg ); if( p_pool ) return p_pool; error: if( pp_pics ) { for( unsigned int i = 0; i < i_requested_count; ++i ) picture_Release( pp_pics[i] ); free( pp_pics ); } BuffersClean( vd ); return NULL; }
static picture_pool_t *Pool(vout_display_t *vd, unsigned count) { unsigned i; vout_display_sys_t *sys = vd->sys; if (!sys->pool) { if (!sys->picture) { picture_resource_t rsc; memset(&rsc, 0, sizeof(rsc)); rsc.p[0].i_pitch = PIXEL_ALIGN(vd->fmt.i_width); rsc.p[0].i_lines = PIXEL_ALIGN(vd->fmt.i_height); rsc.p[1].i_pitch = PIXEL_ALIGN(vd->fmt.i_width); switch (vd->fmt.i_chroma) { case VLC_CODEC_MV12: rsc.p[1].i_lines = PIXEL_ALIGN(vd->fmt.i_height / 2); break; case VLC_CODEC_MV16: rsc.p[1].i_lines = PIXEL_ALIGN(vd->fmt.i_height); break; default: return NULL; } sys->picture = malloc(count * sizeof(picture_t *)); if (!sys->picture) return NULL; for (i = 0; i < count; i ++) { sys->picture[i] = picture_NewFromResource(&vd->fmt, &rsc); if (!sys->picture[i]) { sys->picture_count = i; break; } } sys->picture_count = i; } /* */ picture_pool_configuration_t pool; memset(&pool, 0, sizeof(pool)); pool.picture_count = sys->picture_count; pool.picture = sys->picture; pool.lock = Lock; sys->pool = picture_pool_NewExtended(&pool); if (!sys->pool) { for (i = 0; i < sys->picture_count; i++) { picture_Release(sys->picture[i]); } free(sys->picture); sys->picture = NULL; sys->picture_count = 0; } } return sys->pool; }
static picture_t *picture_pool_ClonePicture(picture_pool_t *pool, unsigned offset) { picture_t *picture = pool->picture[offset]; uintptr_t sys = ((uintptr_t)pool) + offset; picture_resource_t res = { .p_sys = picture->p_sys, .pf_destroy = picture_pool_ReleasePicture, }; for (int i = 0; i < picture->i_planes; i++) { res.p[i].p_pixels = picture->p[i].p_pixels; res.p[i].i_lines = picture->p[i].i_lines; res.p[i].i_pitch = picture->p[i].i_pitch; } picture_t *clone = picture_NewFromResource(&picture->format, &res); if (likely(clone != NULL)) { ((picture_priv_t *)clone)->gc.opaque = (void *)sys; picture_Hold(picture); } return clone; } picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg) { if (unlikely(cfg->picture_count > pool_max)) return NULL; picture_pool_t *pool = vlc_memalign(pool_max, sizeof (*pool) + cfg->picture_count * sizeof (picture_t *)); if (unlikely(pool == NULL)) return NULL; pool->pic_lock = cfg->lock; pool->pic_unlock = cfg->unlock; vlc_mutex_init(&pool->lock); vlc_cond_init(&pool->wait); pool->available = (1ULL << cfg->picture_count) - 1; atomic_init(&pool->refs, 1); pool->picture_count = cfg->picture_count; memcpy(pool->picture, cfg->picture, cfg->picture_count * sizeof (picture_t *)); pool->canceled = false; return pool; } picture_pool_t *picture_pool_New(unsigned count, picture_t *const *tab) { picture_pool_configuration_t cfg = { .picture_count = count, .picture = tab, }; return picture_pool_NewExtended(&cfg); }
picture_pool_t *picture_pool_New(int picture_count, picture_t *picture[]) { picture_pool_configuration_t cfg; memset(&cfg, 0, sizeof(cfg)); cfg.picture_count = picture_count; cfg.picture = picture; return picture_pool_NewExtended(&cfg); }
static picture_pool_t *PoolAlloc(vout_display_t *vd, unsigned requested_count) { vout_display_sys_t *sys = vd->sys; picture_pool_t *pool = NULL; picture_t **pp_pics = NULL; unsigned int i = 0; msg_Dbg(vd, "PoolAlloc: request %d frames", requested_count); if (AndroidWindow_Setup(sys, sys->p_window, requested_count) != 0) goto error; requested_count = sys->p_window->i_pic_count; msg_Dbg(vd, "PoolAlloc: got %d frames", requested_count); UpdateVideoSize(sys, &sys->p_window->fmt); pp_pics = calloc(requested_count, sizeof(picture_t)); for (i = 0; i < requested_count; i++) { picture_t *p_pic = PictureAlloc(sys, &sys->p_window->fmt, sys->p_window->b_opaque); if (!p_pic) goto error; pp_pics[i] = p_pic; } picture_pool_configuration_t pool_cfg; memset(&pool_cfg, 0, sizeof(pool_cfg)); pool_cfg.picture_count = requested_count; pool_cfg.picture = pp_pics; if (sys->p_window->b_opaque) { pool_cfg.lock = PoolLockOpaquePicture; pool_cfg.unlock = PoolUnlockOpaquePicture; } else { pool_cfg.lock = PoolLockPicture; pool_cfg.unlock = PoolUnlockPicture; } pool = picture_pool_NewExtended(&pool_cfg); error: if (!pool && pp_pics) { for (unsigned j = 0; j < i; j++) picture_Release(pp_pics[j]); } free(pp_pics); return pool; }
static int DirectXCreatePool(vout_display_t *vd, bool *use_overlay, video_format_t *fmt) { vout_display_sys_t *sys = vd->sys; /* */ *fmt = vd->source; if (DirectXCreatePictureResource(vd, use_overlay, fmt)) return VLC_EGENERIC; /* Create the associated picture */ picture_resource_t resource = { .p_sys = sys->picsys }; picture_t *picture = picture_NewFromResource(fmt, &resource); if (!picture) { DirectXDestroyPictureResource(vd); free(sys->picsys); return VLC_ENOMEM; } /* Wrap it into a picture pool */ picture_pool_configuration_t cfg; memset(&cfg, 0, sizeof(cfg)); cfg.picture_count = 1; cfg.picture = &picture; cfg.lock = DirectXLock; cfg.unlock = DirectXUnlock; sys->pool = picture_pool_NewExtended(&cfg); if (!sys->pool) { picture_Release(picture); DirectXDestroyPictureResource(vd); return VLC_ENOMEM; } return VLC_SUCCESS; } static void DirectXDestroyPool(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; if (sys->pool) { DirectXDestroyPictureResource(vd); picture_pool_Release(sys->pool); } sys->pool = NULL; }
static int DirectXCreatePool(vout_display_t *vd, bool *use_overlay, video_format_t *fmt) { vout_display_sys_t *sys = vd->sys; /* */ *fmt = vd->source; if (DirectXCreatePictureResource(vd, use_overlay, fmt)) return VLC_EGENERIC; /* Create the associated picture */ picture_resource_t *rsc = &sys->resource; 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) { DirectXDestroyPictureResource(vd); free(rsc->p_sys); return VLC_ENOMEM; } /* Wrap it into a picture pool */ picture_pool_configuration_t cfg; memset(&cfg, 0, sizeof(cfg)); cfg.picture_count = 1; cfg.picture = &picture; cfg.lock = DirectXLock; cfg.unlock = DirectXUnlock; sys->pool = picture_pool_NewExtended(&cfg); if (!sys->pool) { picture_Release(picture); DirectXDestroyPictureResource(vd); return VLC_ENOMEM; } return VLC_SUCCESS; }
/***************************************************************************** * OpenDisplay: open and initialize KVA device ***************************************************************************** * Open and initialize display according to preferences specified in the vout * thread fields. *****************************************************************************/ static int OpenDisplay( vout_display_t *vd, video_format_t *fmt ) { vout_display_sys_t * sys = vd->sys; const vlc_fourcc_t *fallback; bool b_hw_accel = 0; FOURCC i_kva_fourcc; int i_chroma_shift; char sz_title[ 256 ]; RECTL rcl; int w, h; msg_Dbg( vd, "render chroma = %4.4s", ( const char * )&fmt->i_chroma ); for( int pass = 0; pass < 2 && !b_hw_accel; pass++ ) { fallback = ( pass == 0 ) ? vlc_fourcc_GetYUVFallback( fmt->i_chroma ) : vlc_fourcc_GetRGBFallback( fmt->i_chroma ); for( int i = 0; fallback[ i ]; i++ ) { switch( fallback[ i ]) { case VLC_CODEC_YV12: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YV12; i_kva_fourcc = FOURCC_YV12; i_chroma_shift = 1; break; case VLC_CODEC_YUYV: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YUY2; i_kva_fourcc = FOURCC_Y422; i_chroma_shift = 0; break; case VLC_CODEC_YV9: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YVU9; i_kva_fourcc = FOURCC_YVU9; i_chroma_shift = 2; break; case VLC_CODEC_RGB32: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR32; i_kva_fourcc = FOURCC_BGR4; i_chroma_shift = 0; break; case VLC_CODEC_RGB24: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR24; i_kva_fourcc = FOURCC_BGR3; i_chroma_shift = 0; break; case VLC_CODEC_RGB16: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR16; i_kva_fourcc = FOURCC_R565; i_chroma_shift = 0; break; case VLC_CODEC_RGB15: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR15; i_kva_fourcc = FOURCC_R555; i_chroma_shift = 0; break; } if( b_hw_accel ) { fmt->i_chroma = fallback[ i ]; break; } } } if( !b_hw_accel ) { msg_Err( vd, "Ooops. There is no fourcc supported by KVA at all."); return VLC_EGENERIC; } /* Set the RGB masks */ fmt->i_rmask = sys->kvac.ulRMask; fmt->i_gmask = sys->kvac.ulGMask; fmt->i_bmask = sys->kvac.ulBMask; msg_Dbg( vd, "output chroma = %4.4s", ( const char * )&fmt->i_chroma ); msg_Dbg( vd, "KVA chroma = %4.4s", ( const char * )&i_kva_fourcc ); w = vd->source.i_width; h = vd->source.i_height; sys->kvas.ulLength = sizeof( KVASETUP ); sys->kvas.szlSrcSize.cx = w; sys->kvas.szlSrcSize.cy = h; sys->kvas.rclSrcRect.xLeft = 0; sys->kvas.rclSrcRect.yTop = 0; sys->kvas.rclSrcRect.xRight = w; sys->kvas.rclSrcRect.yBottom = h; sys->kvas.ulRatio = KVAR_FORCEANY; sys->kvas.ulAspectWidth = w; sys->kvas.ulAspectHeight = h; sys->kvas.fccSrcColor = i_kva_fourcc; sys->kvas.fDither = TRUE; if( kvaSetup( &sys->kvas )) { msg_Err( vd, "cannot set up KVA"); return VLC_EGENERIC; } /* Create the associated picture */ picture_resource_t *rsc = &sys->resource; rsc->p_sys = malloc( sizeof( *rsc->p_sys )); if( !rsc->p_sys ) return VLC_EGENERIC; rsc->p_sys->i_chroma_shift = i_chroma_shift; 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 exit_picture; /* 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 = KVALock; pool_cfg.unlock = KVAUnlock; sys->pool = picture_pool_NewExtended( &pool_cfg ); if( !sys->pool ) { picture_Release( picture ); goto exit_picture; } if (vd->cfg->display.title) snprintf( sz_title, sizeof( sz_title ), "%s", vd->cfg->display.title ); else snprintf( sz_title, sizeof( sz_title ), "%s (%4.4s to %4.4s - %s mode KVA output)", VOUT_TITLE, ( char * )&vd->fmt.i_chroma, ( char * )&sys->kvas.fccSrcColor, psz_video_mode[ sys->kvac.ulMode - 1 ]); WinSetWindowText( sys->frame, sz_title ); sys->i_screen_width = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ); sys->i_screen_height = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ); if( sys->parent_window ) WinQueryWindowRect( sys->parent, &sys->client_rect ); else { sys->client_rect.xLeft = ( sys->i_screen_width - w ) / 2; sys->client_rect.yBottom = ( sys->i_screen_height - h ) / 2 ; sys->client_rect.xRight = sys->client_rect.xLeft + w; sys->client_rect.yTop = sys->client_rect.yBottom + h; } rcl = sys->client_rect; WinCalcFrameRect( sys->frame, &rcl, FALSE); WinSetWindowPos( sys->frame, HWND_TOP, rcl.xLeft, rcl.yBottom, rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE ); return VLC_SUCCESS; exit_picture: free( rsc->p_sys ); return VLC_EGENERIC; }
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_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; }
/** * It creates the pool of picture (only 1). * * Each picture has an associated offscreen surface in video memory * depending on hardware capabilities the picture chroma will be as close * as possible to the orginal render chroma to reduce CPU conversion overhead * and delegate this work to video card GPU */ static int Direct3DCreatePool(vout_display_t *vd, video_format_t *fmt) { vout_display_sys_t *sys = vd->sys; LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev; /* */ *fmt = vd->source; /* Find the appropriate D3DFORMAT for the render chroma, the format will be the closest to * the requested chroma which is usable by the hardware in an offscreen surface, as they * typically support more formats than textures */ const d3d_format_t *d3dfmt = Direct3DFindFormat(vd, fmt->i_chroma, sys->d3dpp.BackBufferFormat); if (!d3dfmt) { msg_Err(vd, "surface pixel format is not supported."); return VLC_EGENERIC; } fmt->i_chroma = d3dfmt->fourcc; fmt->i_rmask = d3dfmt->rmask; fmt->i_gmask = d3dfmt->gmask; fmt->i_bmask = d3dfmt->bmask; /* We create one picture. * It is useless to create more as we can't be used for direct rendering */ /* Create a surface */ LPDIRECT3DSURFACE9 surface; HRESULT hr = IDirect3DDevice9_CreateOffscreenPlainSurface(d3ddev, fmt->i_width, fmt->i_height, d3dfmt->format, D3DPOOL_DEFAULT, &surface, NULL); if (FAILED(hr)) { msg_Err(vd, "Failed to create picture surface. (hr=0x%lx)", hr); return VLC_EGENERIC; } /* fill surface with black color */ IDirect3DDevice9_ColorFill(d3ddev, surface, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0)); /* Create the associated picture */ picture_resource_t *rsc = &sys->resource; rsc->p_sys = malloc(sizeof(*rsc->p_sys)); if (!rsc->p_sys) { IDirect3DSurface9_Release(surface); return VLC_ENOMEM; } rsc->p_sys->surface = surface; rsc->p_sys->fallback = NULL; 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 = fmt->i_height / (i > 0 ? 2 : 1); } picture_t *picture = picture_NewFromResource(fmt, rsc); if (!picture) { IDirect3DSurface9_Release(surface); free(rsc->p_sys); return VLC_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 = Direct3DLockSurface; pool_cfg.unlock = Direct3DUnlockSurface; sys->pool = picture_pool_NewExtended(&pool_cfg); if (!sys->pool) { picture_Release(picture); IDirect3DSurface9_Release(surface); return VLC_ENOMEM; } return VLC_SUCCESS; }
static picture_pool_t *vd_pool(vout_display_t *vd, unsigned count) { vout_display_sys_t *sys = vd->sys; picture_resource_t picture_res; picture_pool_configuration_t picture_pool_cfg; video_format_t fmt = vd->fmt; MMAL_STATUS_T status; unsigned i; if (sys->picture_pool) { if (sys->num_buffers < count) msg_Warn(vd, "Picture pool with %u pictures requested, but we already have one with %u pictures", count, sys->num_buffers); goto out; } if (sys->opaque) { if (count <= NUM_ACTUAL_OPAQUE_BUFFERS) count = NUM_ACTUAL_OPAQUE_BUFFERS; } if (count < sys->input->buffer_num_recommended) count = sys->input->buffer_num_recommended; #ifndef NDEBUG msg_Dbg(vd, "Creating picture pool with %u pictures", count); #endif sys->input->buffer_num = count; status = mmal_port_enable(sys->input, input_port_cb); if (status != MMAL_SUCCESS) { msg_Err(vd, "Failed to enable input port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); goto out; } status = mmal_component_enable(sys->component); if (status != MMAL_SUCCESS) { msg_Err(vd, "Failed to enable component %s (status=%"PRIx32" %s)", sys->component->name, status, mmal_status_to_string(status)); goto out; } sys->num_buffers = count; sys->pool = mmal_pool_create(sys->num_buffers, sys->input->buffer_size); if (!sys->pool) { msg_Err(vd, "Failed to create MMAL pool for %u buffers of size %"PRIu32, count, sys->input->buffer_size); goto out; } memset(&picture_res, 0, sizeof(picture_resource_t)); sys->pictures = calloc(sys->num_buffers, sizeof(picture_t *)); for (i = 0; i < sys->num_buffers; ++i) { picture_res.p_sys = calloc(1, sizeof(picture_sys_t)); picture_res.p_sys->owner = (vlc_object_t *)vd; picture_res.p_sys->queue = sys->pool->queue; sys->pictures[i] = picture_NewFromResource(&fmt, &picture_res); if (!sys->pictures[i]) { msg_Err(vd, "Failed to create picture"); free(picture_res.p_sys); goto out; } sys->pictures[i]->i_planes = sys->i_planes; memcpy(sys->pictures[i]->p, sys->planes, sys->i_planes * sizeof(plane_t)); } memset(&picture_pool_cfg, 0, sizeof(picture_pool_configuration_t)); picture_pool_cfg.picture_count = sys->num_buffers; picture_pool_cfg.picture = sys->pictures; picture_pool_cfg.lock = mmal_picture_lock; picture_pool_cfg.unlock = mmal_picture_unlock; sys->picture_pool = picture_pool_NewExtended(&picture_pool_cfg); if (!sys->picture_pool) { msg_Err(vd, "Failed to create picture pool"); goto out; } out: return sys->picture_pool; }
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; }
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 Init(vout_display_t *vd, video_format_t *fmt, int width, int height) { vout_display_sys_t *sys = vd->sys; /* */ RECT *display = &sys->rect_display; display->left = 0; display->top = 0; #ifdef MODULE_NAME_IS_wingapi display->right = GXGetDisplayProperties().cxWidth; display->bottom = GXGetDisplayProperties().cyHeight; #else display->right = GetSystemMetrics(SM_CXSCREEN);; display->bottom = GetSystemMetrics(SM_CYSCREEN);; #endif /* Initialize an offscreen bitmap for direct buffer operations. */ /* */ HDC window_dc = GetDC(sys->hvideownd); /* */ #ifdef MODULE_NAME_IS_wingapi GXDisplayProperties gx_displayprop = GXGetDisplayProperties(); sys->i_depth = gx_displayprop.cBPP; #else sys->i_depth = GetDeviceCaps(window_dc, PLANES) * GetDeviceCaps(window_dc, BITSPIXEL); #endif /* */ msg_Dbg(vd, "GDI depth is %i", sys->i_depth); switch (sys->i_depth) { case 8: fmt->i_chroma = VLC_CODEC_RGB8; break; case 15: fmt->i_chroma = VLC_CODEC_RGB15; fmt->i_rmask = 0x7c00; fmt->i_gmask = 0x03e0; fmt->i_bmask = 0x001f; break; case 16: fmt->i_chroma = VLC_CODEC_RGB16; fmt->i_rmask = 0xf800; fmt->i_gmask = 0x07e0; fmt->i_bmask = 0x001f; break; case 24: fmt->i_chroma = VLC_CODEC_RGB24; fmt->i_rmask = 0x00ff0000; fmt->i_gmask = 0x0000ff00; fmt->i_bmask = 0x000000ff; break; case 32: fmt->i_chroma = VLC_CODEC_RGB32; fmt->i_rmask = 0x00ff0000; fmt->i_gmask = 0x0000ff00; fmt->i_bmask = 0x000000ff; break; default: msg_Err(vd, "screen depth %i not supported", sys->i_depth); return VLC_EGENERIC; } fmt->i_width = width; fmt->i_height = height; uint8_t *p_pic_buffer; int i_pic_pitch; #ifdef MODULE_NAME_IS_wingapi GXOpenDisplay(sys->hvideownd, GX_FULLSCREEN); EventThreadUpdateTitle(sys->event, VOUT_TITLE " (WinGAPI output)"); /* Filled by pool::lock() */ p_pic_buffer = NULL; i_pic_pitch = 0; #else /* Initialize offscreen bitmap */ BITMAPINFO *bi = &sys->bitmapinfo; memset(bi, 0, sizeof(BITMAPINFO) + 3 * sizeof(RGBQUAD)); if (sys->i_depth > 8) { ((DWORD*)bi->bmiColors)[0] = fmt->i_rmask; ((DWORD*)bi->bmiColors)[1] = fmt->i_gmask; ((DWORD*)bi->bmiColors)[2] = fmt->i_bmask;; } BITMAPINFOHEADER *bih = &sys->bitmapinfo.bmiHeader; bih->biSize = sizeof(BITMAPINFOHEADER); bih->biSizeImage = 0; bih->biPlanes = 1; bih->biCompression = (sys->i_depth == 15 || sys->i_depth == 16) ? BI_BITFIELDS : BI_RGB; bih->biBitCount = sys->i_depth; bih->biWidth = fmt->i_width; bih->biHeight = -fmt->i_height; bih->biClrImportant = 0; bih->biClrUsed = 0; bih->biXPelsPerMeter = 0; bih->biYPelsPerMeter = 0; i_pic_pitch = bih->biBitCount * bih->biWidth / 8; sys->off_bitmap = CreateDIBSection(window_dc, (BITMAPINFO *)bih, DIB_RGB_COLORS, &p_pic_buffer, NULL, 0); sys->off_dc = CreateCompatibleDC(window_dc); SelectObject(sys->off_dc, sys->off_bitmap); ReleaseDC(sys->hvideownd, window_dc); EventThreadUpdateTitle(sys->event, VOUT_TITLE " (WinGDI output)"); #endif /* */ picture_resource_t rsc; memset(&rsc, 0, sizeof(rsc)); #ifdef MODULE_NAME_IS_wingapi rsc.p_sys = malloc(sizeof(*rsc.p_sys)); if (!rsc.p_sys) return VLC_EGENERIC; rsc.p_sys->vd = vd; #endif rsc.p[0].p_pixels = p_pic_buffer; rsc.p[0].i_lines = fmt->i_height; rsc.p[0].i_pitch = i_pic_pitch;; picture_t *picture = picture_NewFromResource(fmt, &rsc); if (picture) { picture_pool_configuration_t cfg; memset(&cfg, 0, sizeof(cfg)); cfg.picture_count = 1; cfg.picture = &picture; #ifdef MODULE_NAME_IS_wingapi cfg.lock = Lock; cfg.unlock = Unlock; #endif sys->pool = picture_pool_NewExtended(&cfg); } else { free(rsc.p_sys); sys->pool = NULL; } UpdateRects(vd, NULL, NULL, true); 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; 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; }