static vpx_image_t vp8_get_frame(vpx_codec_alg_priv_t ctx, vpx_codec_iter_t iter) { vpx_image_t img = null; /* iter acts as a flip flop, so an image is only returned on the first * call to get_frame. */ if (iter == IntPtr.Zero && ctx.yv12_frame_buffers.pbi[0] != null) { YV12_BUFFER_CONFIG sd = new YV12_BUFFER_CONFIG(); long time_stamp = 0, time_end_stamp = 0; vp8_ppflags_t flags = new vp8_ppflags_t(); // Port AC: ppflags struct will be initialised to zero by default. //vp8_zero(flags); //if ([email protected]_flags & VPX_CODEC_USE_POSTPROC) { // flags.post_proc_flag = ctx->postproc_cfg.post_proc_flag; // flags.deblocking_level = ctx->postproc_cfg.deblocking_level; // flags.noise_level = ctx->postproc_cfg.noise_level; //} if (0 == onyxd.vp8dx_get_raw_frame(ctx.yv12_frame_buffers.pbi[0], ref sd, out time_stamp, out time_end_stamp, ref flags)) { yuvconfig2image(ctx.img, sd, ctx.user_priv); img = ctx.img; //*iter = img; } } return(img); }
/*!\brief Open a descriptor, using existing storage for the underlying image * * Returns a descriptor for storing an image of the given format. The * storage for descriptor has been allocated elsewhere, and a descriptor is * desired to "wrap" that storage. * * \param[in] img Pointer to storage for descriptor. If this * parameter is NULL, the storage for the descriptor * will be allocated on the heap. * \param[in] fmt Format for the image * \param[in] d_w Width of the image * \param[in] d_h Height of the image * \param[in] stride_align Alignment, in bytes, of each row in the image. * \param[in] img_data Storage to use for the image * * \return Returns a pointer to the initialized image descriptor. If the img * parameter is non-null, the value of the img parameter will be * returned. */ //vpx_image_t* vpx_img_wrap(vpx_image_t* img, vpx_img_fmt_t fmt, unsigned int d_w, // unsigned int d_h, unsigned int stride_align, // unsigned char* img_data); public vpx_image_t vpx_img_wrap(vpx_image_t img, vpx_img_fmt_t fmt, uint d_w, uint d_h, uint stride_align, byte *img_data) { /* By setting buf_align = 1, we don't change buffer alignment in this * function. */ return(img_alloc_helper(img, fmt, d_w, d_h, 1, stride_align, img_data)); }
/*!\brief Flip the image vertically (top for bottom) * * Adjusts the image descriptor's pointers and strides to make the image * be referenced upside-down. * * \param[in] img Image descriptor */ //void vpx_img_flip(vpx_image_t* img); public static void vpx_img_flip(vpx_image_t img) { /* Note: In the calculation pointer adjustment calculation, we want the * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99 * standard indicates that if the adjustment parameter is unsigned, the * stride parameter will be promoted to unsigned, causing errors when * the lhs is a larger type than the rhs. */ img.planes[vpx_image_t.VPX_PLANE_Y] += (int)(img.d_h - 1) * img.stride[vpx_image_t.VPX_PLANE_Y]; img.stride[vpx_image_t.VPX_PLANE_Y] = -img.stride[vpx_image_t.VPX_PLANE_Y]; img.planes[vpx_image_t.VPX_PLANE_U] += (int)((img.d_h >> (int)img.y_chroma_shift) - 1) * img.stride[vpx_image_t.VPX_PLANE_U]; img.stride[vpx_image_t.VPX_PLANE_U] = -img.stride[vpx_image_t.VPX_PLANE_U]; img.planes[vpx_image_t.VPX_PLANE_V] += (int)((img.d_h >> (int)img.y_chroma_shift) - 1) * img.stride[vpx_image_t.VPX_PLANE_V]; img.stride[vpx_image_t.VPX_PLANE_V] = -img.stride[vpx_image_t.VPX_PLANE_V]; img.planes[vpx_image_t.VPX_PLANE_ALPHA] += (int)(img.d_h - 1) * img.stride[vpx_image_t.VPX_PLANE_ALPHA]; img.stride[vpx_image_t.VPX_PLANE_ALPHA] = -img.stride[vpx_image_t.VPX_PLANE_ALPHA]; }
public static unsafe void yuvconfig2image(vpx_image_t img, in YV12_BUFFER_CONFIG yv12, IntPtr user_priv)
private static vpx_image_t img_alloc_helper(vpx_image_t img, vpx_img_fmt_t fmt, uint d_w, uint d_h, uint buf_align, uint stride_align, byte *img_data) { uint h, w, s, xcs, ycs, bps; uint stride_in_bytes; int align; /* Treat align==0 like align==1 */ if (buf_align == 0) { buf_align = 1; } /* Validate alignment (must be power of 2) */ if ((buf_align & (buf_align - 1)) != 0) { goto fail; } /* Treat align==0 like align==1 */ if (stride_align == 0) { stride_align = 1; } /* Validate alignment (must be power of 2) */ if ((stride_align & (stride_align - 1)) != 0) { goto fail; } /* Get sample size for this format */ switch (fmt) { case vpx_img_fmt_t.VPX_IMG_FMT_I420: case vpx_img_fmt_t.VPX_IMG_FMT_YV12: case vpx_img_fmt_t.VPX_IMG_FMT_NV12: bps = 12; break; case vpx_img_fmt_t.VPX_IMG_FMT_I422: case vpx_img_fmt_t.VPX_IMG_FMT_I440: bps = 16; break; case vpx_img_fmt_t.VPX_IMG_FMT_I444: bps = 24; break; case vpx_img_fmt_t.VPX_IMG_FMT_I42016: bps = 24; break; case vpx_img_fmt_t.VPX_IMG_FMT_I42216: case vpx_img_fmt_t.VPX_IMG_FMT_I44016: bps = 32; break; case vpx_img_fmt_t.VPX_IMG_FMT_I44416: bps = 48; break; default: bps = 16; break; } /* Get chroma shift values for this format */ // For VPX_IMG_FMT_NV12, xcs needs to be 0 such that UV data is all read at // one time. switch (fmt) { case vpx_img_fmt_t.VPX_IMG_FMT_I420: case vpx_img_fmt_t.VPX_IMG_FMT_YV12: case vpx_img_fmt_t.VPX_IMG_FMT_I422: case vpx_img_fmt_t.VPX_IMG_FMT_I42016: case vpx_img_fmt_t.VPX_IMG_FMT_I42216: xcs = 1; break; default: xcs = 0; break; } switch (fmt) { case vpx_img_fmt_t.VPX_IMG_FMT_I420: case vpx_img_fmt_t.VPX_IMG_FMT_NV12: case vpx_img_fmt_t.VPX_IMG_FMT_I440: case vpx_img_fmt_t.VPX_IMG_FMT_YV12: case vpx_img_fmt_t.VPX_IMG_FMT_I42016: case vpx_img_fmt_t.VPX_IMG_FMT_I44016: ycs = 1; break; default: ycs = 0; break; } /* Calculate storage sizes. If the buffer was allocated externally, the width * and height shouldn't be adjusted. */ w = d_w; h = d_h; s = (((int)fmt & vpx_image_t.VPX_IMG_FMT_PLANAR) > 0) ? w : bps * w / 8; s = (s + stride_align - 1) & ~(stride_align - 1); stride_in_bytes = (((int)fmt & vpx_image_t.VPX_IMG_FMT_HIGHBITDEPTH) > 0) ? s * 2 : s; /* Allocate the new image */ if (img == null) { //img = (vpx_image_t*)calloc(1, sizeof(vpx_image_t)); //if (!img) goto fail; img = new vpx_image_t(); img.self_allocd = 1; } else { //memset(img, 0, sizeof(vpx_image_t)); } img.img_data = img_data; if (img_data == null) { ulong alloc_size; /* Calculate storage sizes given the chroma subsampling */ align = (1 << (int)xcs) - 1; w = (uint)((d_w + align) & ~align); align = (1 << (int)ycs) - 1; h = (uint)((d_h + align) & ~align); s = (((int)fmt & vpx_image_t.VPX_IMG_FMT_PLANAR) > 0) ? w : bps * w / 8; s = (s + stride_align - 1) & ~(stride_align - 1); stride_in_bytes = (((int)fmt & vpx_image_t.VPX_IMG_FMT_HIGHBITDEPTH) > 0) ? s * 2 : s; alloc_size = (((int)fmt & vpx_image_t.VPX_IMG_FMT_PLANAR) > 0) ? (ulong)h * s * bps / 8 : (ulong)h * s; //if (alloc_size != (size_t)alloc_size) goto fail; //img.img_data = (byte*)vpx_memalign(buf_align, (size_t)alloc_size); img.img_data = (byte *)Marshal.AllocHGlobal((int)alloc_size); img.img_data_owner = 1; } if (img.img_data == null) { goto fail; } img.fmt = fmt; img.bit_depth = (((int)fmt & vpx_image_t.VPX_IMG_FMT_HIGHBITDEPTH) > 0) ? 16U : 8U; img.w = w; img.h = h; img.x_chroma_shift = xcs; img.y_chroma_shift = ycs; img.bps = (int)bps; /* Calculate strides */ img.stride[vpx_image_t.VPX_PLANE_Y] = img.stride[vpx_image_t.VPX_PLANE_ALPHA] = (int)stride_in_bytes; img.stride[vpx_image_t.VPX_PLANE_U] = img.stride[vpx_image_t.VPX_PLANE_V] = (int)(stride_in_bytes >> (int)xcs); /* Default viewport to entire image */ if (vpx_img_set_rect(img, 0, 0, d_w, d_h) == 0) { return(img); } fail: vpx_img_free(img); return(null); }
/*!\brief Close an image descriptor * * Frees all allocated storage associated with an image descriptor. * * \param[in] img Image descriptor */ //void vpx_img_free(vpx_image_t* img); public static void vpx_img_free(vpx_image_t img) { img?.Dispose(); }
/*!\brief Set the rectangle identifying the displayed portion of the image * * Updates the displayed rectangle (aka viewport) on the image surface to * match the specified coordinates and size. * * \param[in] img Image descriptor * \param[in] x leftmost column * \param[in] y topmost row * \param[in] w width * \param[in] h height * * \return 0 if the requested rectangle is valid, nonzero otherwise. */ //int vpx_img_set_rect(vpx_image_t* img, unsigned int x, unsigned int y, // unsigned int w, unsigned int h); public static int vpx_img_set_rect(vpx_image_t img, uint x, uint y, uint w, uint h) { byte *data; if (x + w <= img.w && y + h <= img.h) { img.d_w = w; img.d_h = h; /* Calculate plane pointers */ if (((int)img.fmt & (int)vpx_image_t.VPX_IMG_FMT_PLANAR) == 0) { img.planes[vpx_image_t.VPX_PLANE_PACKED] = img.img_data + x * img.bps / 8 + y * img.stride[vpx_image_t.VPX_PLANE_PACKED]; } else { int bytes_per_sample = (((int)img.fmt & (int)vpx_image_t.VPX_IMG_FMT_HIGHBITDEPTH) > 0) ? 2 : 1; data = img.img_data; if (((int)img.fmt & (int)vpx_image_t.VPX_IMG_FMT_HAS_ALPHA) > 0) { img.planes[vpx_image_t.VPX_PLANE_ALPHA] = data + x * bytes_per_sample + y * img.stride[vpx_image_t.VPX_PLANE_ALPHA]; data += img.h * img.stride[vpx_image_t.VPX_PLANE_ALPHA]; } img.planes[vpx_image_t.VPX_PLANE_Y] = data + x * bytes_per_sample + y * img.stride[vpx_image_t.VPX_PLANE_Y]; data += img.h * img.stride[vpx_image_t.VPX_PLANE_Y]; if (img.fmt == vpx_img_fmt_t.VPX_IMG_FMT_NV12) { img.planes[vpx_image_t.VPX_PLANE_U] = data + (x >> (int)img.x_chroma_shift) + (y >> (int)img.y_chroma_shift) * img.stride[vpx_image_t.VPX_PLANE_U]; img.planes[vpx_image_t.VPX_PLANE_V] = img.planes[vpx_image_t.VPX_PLANE_U] + 1; } else if (((int)img.fmt & vpx_image_t.VPX_IMG_FMT_UV_FLIP) == 0) { img.planes[vpx_image_t.VPX_PLANE_U] = data + (x >> (int)img.x_chroma_shift) * bytes_per_sample + (y >> (int)img.y_chroma_shift) * img.stride[vpx_image_t.VPX_PLANE_U]; data += (img.h >> (int)img.y_chroma_shift) * img.stride[vpx_image_t.VPX_PLANE_U]; img.planes[vpx_image_t.VPX_PLANE_V] = data + (x >> (int)img.x_chroma_shift) * bytes_per_sample + (y >> (int)img.y_chroma_shift) * img.stride[vpx_image_t.VPX_PLANE_V]; } else { img.planes[vpx_image_t.VPX_PLANE_V] = data + (x >> (int)img.x_chroma_shift) * bytes_per_sample + (y >> (int)img.y_chroma_shift) * img.stride[vpx_image_t.VPX_PLANE_V]; data += (img.h >> (int)img.y_chroma_shift) * img.stride[vpx_image_t.VPX_PLANE_V]; img.planes[vpx_image_t.VPX_PLANE_U] = data + (x >> (int)img.x_chroma_shift) * bytes_per_sample + (y >> (int)img.y_chroma_shift) * img.stride[vpx_image_t.VPX_PLANE_U]; } } return(0); } return(-1); }
/*!\brief Open a descriptor, allocating storage for the underlying image * * Returns a descriptor for storing an image of the given format. The * storage for the descriptor is allocated on the heap. * * \param[in] img Pointer to storage for descriptor. If this parameter * is NULL, the storage for the descriptor will be * allocated on the heap. * \param[in] fmt Format for the image * \param[in] d_w Width of the image * \param[in] d_h Height of the image * \param[in] align Alignment, in bytes, of the image buffer and * each row in the image(stride). * * \return Returns a pointer to the initialized image descriptor. If the img * parameter is non-null, the value of the img parameter will be * returned. */ //vpx_image_t* vpx_img_alloc(vpx_image_t* img, vpx_img_fmt_t fmt, // unsigned int d_w, unsigned int d_h, // unsigned int align); public static vpx_image_t vpx_img_alloc(vpx_image_t img, vpx_img_fmt_t fmt, uint d_w, uint d_h, uint align) { return(img_alloc_helper(img, fmt, d_w, d_h, align, align, null)); }