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; }
/** * Return a direct buffer */ static picture_t *Get(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; if (!sys->pool) { picture_resource_t rsc; memset(&rsc, 0, sizeof(rsc)); if (sys->overlay) { SDL_Overlay *ol = sys->overlay; for (int i = 0; i < ol->planes; i++) { rsc.p[i].p_pixels = ol->pixels[ i > 0 && sys->is_uv_swapped ? (3-i) : i]; rsc.p[i].i_pitch = ol->pitches[i > 0 && sys->is_uv_swapped ? (3-i) : i]; rsc.p[i].i_lines = ol->h; if (ol->format == SDL_YV12_OVERLAY || ol->format == SDL_IYUV_OVERLAY) rsc.p[i].i_lines /= 2; } } else { const int x = sys->place.x; const int y = sys->place.y; SDL_Surface *sf = sys->display; SDL_FillRect(sf, NULL, 0); assert(x >= 0 && y >= 0); rsc.p[0].p_pixels = (uint8_t*)sf->pixels + y * sf->pitch + x * ((sf->format->BitsPerPixel + 7) / 8); rsc.p[0].i_pitch = sf->pitch; rsc.p[0].i_lines = vd->fmt.i_height; } picture_t *picture = picture_NewFromResource(&vd->fmt, &rsc);; if (!picture) return NULL; sys->pool = picture_pool_New(1, &picture); if (!sys->pool) return NULL; } return picture_pool_Get(sys->pool); }
static picture_t *DxAllocPicture(vlc_va_t *va, const video_format_t *fmt, unsigned index) { video_format_t src_fmt = *fmt; src_fmt.i_chroma = VLC_CODEC_D3D9_OPAQUE; picture_sys_t *pic_sys = calloc(1, sizeof(*pic_sys)); if (unlikely(pic_sys == NULL)) return NULL; pic_sys->surface = (LPDIRECT3DSURFACE9) va->sys->dx_sys.hw_surface[index]; picture_resource_t res = { .p_sys = pic_sys, }; picture_t *pic = picture_NewFromResource(&src_fmt, &res); if (unlikely(pic == NULL)) { free(pic_sys); return NULL; } return pic; }
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; }
/** * Return a pool of direct buffers */ static picture_pool_t *Pool(vout_display_t *vd, unsigned count) { vout_display_sys_t *sys = vd->sys; VLC_UNUSED(count); if (!sys->pool) { picture_resource_t rsc; memset(&rsc, 0, sizeof(rsc)); rsc.p[0].p_pixels = aa_image(sys->aa_context); rsc.p[0].i_pitch = aa_imgwidth(sys->aa_context); rsc.p[0].i_lines = aa_imgheight(sys->aa_context); picture_t *p_picture = picture_NewFromResource(&vd->fmt, &rsc); if (!p_picture) return NULL; sys->pool = picture_pool_New(1, &p_picture); } return sys->pool; }
static picture_t *PictureAlloc(vout_display_sys_t *sys, video_format_t *fmt) { picture_t *p_pic; picture_resource_t rsc; picture_sys_t *p_picsys = calloc(1, sizeof(*p_picsys)); if (unlikely(p_picsys == NULL)) return NULL; p_picsys->p_vd_sys = sys; memset(&rsc, 0, sizeof(picture_resource_t)); rsc.p_sys = p_picsys, p_pic = picture_NewFromResource(fmt, &rsc); if (!p_pic) { free(p_picsys); return NULL; } return p_pic; }
static picture_t *PictureAlloc(vout_display_sys_t *sys, video_format_t *fmt, bool b_opaque) { picture_t *p_pic; picture_resource_t rsc; picture_sys_t *p_picsys = calloc(1, sizeof(*p_picsys)); if (unlikely(p_picsys == NULL)) return NULL; memset(&rsc, 0, sizeof(picture_resource_t)); rsc.p_sys = p_picsys; if (b_opaque) { p_picsys->hw.b_vd_ref = true; p_picsys->hw.p_surface = sys->p_window->p_surface; p_picsys->hw.p_jsurface = sys->p_window->p_jsurface; p_picsys->hw.i_index = -1; vlc_mutex_init(&p_picsys->hw.lock); rsc.pf_destroy = AndroidOpaquePicture_DetachVout; } else { p_picsys->sw.p_vd_sys = sys; rsc.pf_destroy = AndroidPicture_Destroy; } p_pic = picture_NewFromResource(fmt, &rsc); if (!p_pic) { free(p_picsys); return NULL; } return p_pic; }
static picture_t *DxAllocPicture(vlc_va_t *va, const video_format_t *fmt, unsigned index) { video_format_t src_fmt = *fmt; src_fmt.i_chroma = VLC_CODEC_D3D11_OPAQUE; picture_sys_t *pic_sys = calloc(1, sizeof(*pic_sys)); if (unlikely(pic_sys == NULL)) return NULL; pic_sys->decoder = (ID3D11VideoDecoderOutputView*) va->sys->dx_sys.hw_surface[index]; ID3D11VideoDecoderOutputView_GetResource(pic_sys->decoder, (ID3D11Resource**) &pic_sys->texture); pic_sys->context = va->sys->d3dctx; picture_resource_t res = { .p_sys = pic_sys, .pf_destroy = DestroyPicture, }; picture_t *pic = picture_NewFromResource(&src_fmt, &res); if (unlikely(pic == NULL)) { free(pic_sys); return NULL; } return pic; }
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; }
/** * 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; }
picture_t *picture_NewFromFormat( const video_format_t *p_fmt ) { return picture_NewFromResource( p_fmt, NULL ); }
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; }
/***************************************************************************** * 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; }
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 Init(vout_display_t *vd, video_format_t *fmt) { vout_display_sys_t *sys = vd->sys; /* */ RECT *display = &sys->sys.rect_display; display->left = 0; display->top = 0; display->right = GetSystemMetrics(SM_CXSCREEN);; display->bottom = GetSystemMetrics(SM_CYSCREEN);; /* Initialize an offscreen bitmap for direct buffer operations. */ /* */ HDC window_dc = GetDC(sys->sys.hvideownd); /* */ sys->i_depth = GetDeviceCaps(window_dc, PLANES) * GetDeviceCaps(window_dc, BITSPIXEL); /* */ 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; } void *p_pic_buffer; int i_pic_pitch; /* 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->sys.hvideownd, window_dc); if (!sys->sys.b_windowless) EventThreadUpdateTitle(sys->sys.event, VOUT_TITLE " (WinGDI output)"); /* */ picture_resource_t rsc; memset(&rsc, 0, sizeof(rsc)); 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 != NULL) sys->sys.pool = picture_pool_New(1, &picture); else sys->sys.pool = NULL; UpdateRects(vd, 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; }
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 EvasImageBuffersAlloc( vout_display_t *vd, video_format_t *p_fmt ) { vout_display_sys_t *sys = vd->sys; picture_t *p_pic = NULL; picture_resource_t rsc; size_t i_bytes = 0; memset(&rsc, 0, sizeof(picture_resource_t)); if( !( p_pic = picture_NewFromResource( p_fmt, &rsc ) ) ) return -1; if( picture_Setup( p_pic, p_fmt ) ) { picture_Release( p_pic ); return -1; } for( int i = 0; i < p_pic->i_planes; ++i ) memcpy( &sys->p_planes[i], &p_pic->p[i], sizeof(plane_t)); sys->i_nb_planes = p_pic->i_planes; picture_Release( p_pic ); if( !( sys->p_buffers = calloc( sys->i_nb_buffers, sizeof(struct buffer) ) ) ) goto error; /* Calculate how big the new image should be */ for( unsigned int i = 0; i < sys->i_nb_planes; i++ ) { const plane_t *p = &sys->p_planes[i]; if( p->i_pitch < 0 || p->i_lines <= 0 || (size_t)p->i_pitch > (SIZE_MAX - i_bytes)/p->i_lines ) goto error; i_bytes += p->i_pitch * p->i_lines; } if( !i_bytes ) goto error; for( unsigned int i = 0; i < sys->i_nb_buffers; ++i ) { struct buffer *p_buffer = &sys->p_buffers[i]; p_buffer->p[0] = aligned_alloc( 16, i_bytes ); if( !p_buffer->p[0] ) { sys->i_nb_buffers = i; break; } for( unsigned int j = 1; j < sys->i_nb_planes; j++ ) p_buffer->p[j] = &p_buffer->p[j-1][ sys->p_planes[j-1].i_lines * sys->p_planes[j-1].i_pitch ]; } return 0; error: if( sys->p_buffers ) EvasImageBuffersFree( vd ); return -1; }