/** * Allocate a new picture in the heap. * * This function allocates a fake direct buffer in memory, which can be * used exactly like a video buffer. The video output thread then manages * how it gets displayed. */ static int AllocatePicture( picture_t *p_pic ) { /* Calculate how big the new image should be */ size_t i_bytes = 0; for( int i = 0; i < p_pic->i_planes; i++ ) { const plane_t *p = &p_pic->p[i]; if( p->i_pitch < 0 || p->i_lines <= 0 || (size_t)p->i_pitch > (SIZE_MAX - i_bytes)/p->i_lines ) { p_pic->i_planes = 0; return VLC_ENOMEM; } i_bytes += p->i_pitch * p->i_lines; } uint8_t *p_data = vlc_memalign( 16, i_bytes ); if( i_bytes > 0 && p_data == NULL ) { p_pic->i_planes = 0; return VLC_EGENERIC; } p_pic->gc.p_sys = (void *)p_data; /* Fill the p_pixels field for each plane */ p_pic->p[0].p_pixels = p_data; for( int i = 1; i < p_pic->i_planes; i++ ) { p_pic->p[i].p_pixels = &p_pic->p[i-1].p_pixels[ p_pic->p[i-1].i_lines * p_pic->p[i-1].i_pitch ]; } return VLC_SUCCESS; }
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); }
static picture_t *Filter(filter_t *filter, picture_t *src) { filter_sys_t *sys = filter->p_sys; picture_t *dst = filter_NewPicture(filter); if (!dst) { picture_Release(src); return NULL; } vlc_mutex_lock(&sys->lock); float strength = VLC_CLIP(sys->strength, STRENGTH_MIN, STRENGTH_MAX); int radius = VLC_CLIP((sys->radius + 1) & ~1, RADIUS_MIN, RADIUS_MAX); vlc_mutex_unlock(&sys->lock); const video_format_t *fmt = &filter->fmt_in.video; struct vf_priv_s *cfg = &sys->cfg; cfg->thresh = (1 << 15) / strength; if (cfg->radius != radius) { cfg->radius = radius; cfg->buf = (uint16_t *)vlc_memalign(16, (((fmt->i_width + 15) & ~15) * (cfg->radius + 1) / 2 + 32) * sizeof(*cfg->buf)); // sunqueen modify } for (int i = 0; i < dst->i_planes; i++) { const plane_t *srcp = &src->p[i]; plane_t *dstp = &dst->p[i]; const vlc_chroma_description_t *chroma = sys->chroma; int w = fmt->i_width * chroma->p[i].w.num / chroma->p[i].w.den; int h = fmt->i_height * chroma->p[i].h.num / chroma->p[i].h.den; int r = (cfg->radius * chroma->p[i].w.num / chroma->p[i].w.den + cfg->radius * chroma->p[i].h.num / chroma->p[i].h.den) / 2; r = VLC_CLIP((r + 1) & ~1, RADIUS_MIN, RADIUS_MAX); if (__MIN(w, h) > 2 * r && cfg->buf) { filter_plane(cfg, dstp->p_pixels, srcp->p_pixels, w, h, dstp->i_pitch, srcp->i_pitch, r); } else { plane_CopyPixels(dstp, srcp); } } picture_CopyProperties(dst, src); picture_Release(src); return dst; }
/** * Allocate a new picture in the heap. * * This function allocates a fake direct buffer in memory, which can be * used exactly like a video buffer. The video output thread then manages * how it gets displayed. */ static int vout_AllocatePicture( picture_t *p_pic, vlc_fourcc_t i_chroma, int i_width, int i_height, int i_sar_num, int i_sar_den ) { /* Make sure the real dimensions are a multiple of 16 */ if( picture_Setup( p_pic, i_chroma, i_width, i_height, i_sar_num, i_sar_den ) != VLC_SUCCESS ) return VLC_EGENERIC; /* Calculate how big the new image should be */ size_t i_bytes = 0; for( int i = 0; i < p_pic->i_planes; i++ ) { const plane_t *p = &p_pic->p[i]; if( p->i_pitch <= 0 || p->i_lines <= 0 || p->i_pitch > (SIZE_MAX - i_bytes)/p->i_lines ) { p_pic->i_planes = 0; return VLC_ENOMEM; } i_bytes += p->i_pitch * p->i_lines; } uint8_t *p_data = vlc_memalign( &p_pic->p_data_orig, 16, i_bytes ); if( !p_data ) { p_pic->i_planes = 0; return VLC_EGENERIC; } /* Fill the p_pixels field for each plane */ p_pic->p[0].p_pixels = p_data; for( int i = 1; i < p_pic->i_planes; i++ ) { p_pic->p[i].p_pixels = &p_pic->p[i-1].p_pixels[ p_pic->p[i-1].i_lines * p_pic->p[i-1].i_pitch ]; } return VLC_SUCCESS; }