internal static vpx_codec_err_t vp8_init(vpx_codec_ctx_t ctx, vpx_codec_priv_enc_mr_cfg_t data) { vpx_codec_err_t res = vpx_codec_err_t.VPX_CODEC_OK; //(void)data; //vp8_rtcd(); //vpx_dsp_rtcd(); //vpx_scale_rtcd(); /* This function only allocates space for the vpx_codec_alg_priv_t * structure. More memory may be required at the time the stream * information becomes known. */ if (ctx.priv == null) { if (vp8_init_ctx(ctx) != 0) { return(vpx_codec_err_t.VPX_CODEC_MEM_ERROR); } /* initialize number of fragments to zero */ ctx.priv.fragments.count = 0; /* is input fragments enabled? */ ctx.priv.fragments.enabled = (int)([email protected]_flags & vpx_decoder.VPX_CODEC_USE_INPUT_FRAGMENTS); /*post processing level initialized to do nothing */ } return(res); }
/// <summary> /// Initialize a decoder instance. /// /// Initializes a decoder context using the given interface. Applications /// should call the vpx_codec_dec_init convenience macro instead of this /// function directly, to ensure that the ABI version number parameter /// is properly initialized. /// /// If the library was configured with --disable-multithread, this call /// is not thread safe and should be guarded with a lock if being used /// in a multithreaded context. /// </summary> /// <param name="ctx">Pointer to this instance's context.</param> /// <param name="iface">Pointer to the algorithm interface to use.</param> /// <param name="cfg">Configuration to use, if known. May be NULL.</param> /// <param name="flags">Bitfield of VPX_CODEC_USE_* flags.</param> /// <param name="ver">ABI version number. Must be set to VPX_DECODER_ABI_VERSION.</param> /// <returns> /// VPX_CODEC_OK The decoder algorithm initialized. /// VPX_CODEC_MEM_ERROR Memory allocation failed. /// </returns> public static vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t ctx, vpx_codec_iface_t iface, vpx_codec_dec_cfg_t cfg, vpx_codec_flags_t flags, int ver = VPX_DECODER_ABI_VERSION) { vpx_codec_err_t res; if (ver != VPX_DECODER_ABI_VERSION) { res = vpx_codec_err_t.VPX_CODEC_ABI_MISMATCH; } else if (ctx == null || iface == null) { res = vpx_codec_err_t.VPX_CODEC_INVALID_PARAM; } else if (iface.abi_version != vpx_codec_internal.VPX_CODEC_INTERNAL_ABI_VERSION) { res = vpx_codec_err_t.VPX_CODEC_ABI_MISMATCH; } else if (((flags & VPX_CODEC_USE_POSTPROC) > 0) && ((iface.caps & VPX_CODEC_CAP_POSTPROC) == 0)) { res = vpx_codec_err_t.VPX_CODEC_INCAPABLE; } else if (((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) > 0) && ((iface.caps & VPX_CODEC_CAP_ERROR_CONCEALMENT) == 0)) { res = vpx_codec_err_t.VPX_CODEC_INCAPABLE; } else if (((flags & VPX_CODEC_USE_INPUT_FRAGMENTS) > 0) && ((iface.caps & VPX_CODEC_CAP_INPUT_FRAGMENTS) == 0)) { res = vpx_codec_err_t.VPX_CODEC_INCAPABLE; } else if ((iface.caps & vpx_codec.VPX_CODEC_CAP_DECODER) == 0) { res = vpx_codec_err_t.VPX_CODEC_INCAPABLE; } else { //memset(ctx, 0, sizeof(*ctx)); ctx.iface = iface; ctx.name = iface.name; ctx.priv = null; ctx.init_flags = flags; //ctx.config.dec = cfg; ctx.dec_cfg = cfg; res = ctx.iface.init(ctx, null); if (res != vpx_codec_err_t.VPX_CODEC_OK) { //ctx.err_detail = ctx.priv != null ? ctx.priv.err_detail : null; vpx_codec.vpx_codec_destroy(ctx); } } //return SAVE_STATUS(ctx, res); return(ctx != null ? (ctx.err = res) : res); }
/// <summary> /// Convenience macro for vpx_codec_dec_init_ver() /// /// Ensures the ABI version parameter is properly set. /// </summary> public static vpx_codec_err_t vpx_codec_dec_init(vpx_codec_ctx_t ctx, vpx_codec_iface_t iface, vpx_codec_dec_cfg_t cfg, vpx_codec_flags_t flags) { return(vpx_codec_dec_init_ver(ctx, iface, cfg, flags)); }
/* REQUIRED FUNCTIONS * * The following functions are required to be implemented for all codecs. * They represent the base case functionality expected of all codecs. */ /*!\brief Destroy a codec instance * * Destroys a codec context, freeing any associated memory buffers. * * \param[in] ctx Pointer to this instance's context * * \retval #VPX_CODEC_OK * The codec algorithm initialized. * \retval #VPX_CODEC_MEM_ERROR * Memory allocation failed. */ // vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx); public static vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t ctx) { vpx_codec_err_t res; if (ctx == null) { res = vpx_codec_err_t.VPX_CODEC_INVALID_PARAM; } else if (ctx.iface == null || ctx.priv == null) { res = vpx_codec_err_t.VPX_CODEC_ERROR; } else { //ctx.iface.destroy((vpx_codec_alg_priv_t)ctx.priv); ctx.iface = null; ctx.name = null; ctx.priv = null; res = vpx_codec_err_t.VPX_CODEC_OK; } // return SAVE_STATUS(ctx, res); return(ctx != null ? (ctx.err = res) : res); }
/*!\brief Retrieve detailed error information for codec context * * Returns a human readable string providing detailed information about * the last error. * * \param[in] ctx Pointer to this instance's context. * * \retval NULL * No detailed information is available. */ // const char *vpx_codec_error_detail(vpx_codec_ctx_t *ctx); public static string vpx_codec_error_detail(vpx_codec_ctx_t ctx) { if (ctx != null) { //return ctx.priv != null ? ctx.priv.err_detail : ctx.err_detail; return(ctx.err_detail); } return(null); }
public static vpx_image_t vpx_codec_get_frame(vpx_codec_ctx_t ctx, vpx_codec_iter_t iter) { vpx_image_t img; if (ctx == null || iter == null || ctx.iface == null || ctx.priv == null) { img = null; } else { img = ctx.iface.dec.get_frame(get_alg_priv(ctx), iter); } return(img); }
private static int vp8_init_ctx(vpx_codec_ctx_t ctx) { //vpx_codec_alg_priv_t priv = (vpx_codec_alg_priv_t)vpx_calloc(1, sizeof(*priv)); //if (!priv) return 1; vpx_codec_alg_priv_t priv = new vpx_codec_alg_priv_t(); //ctx.priv = new vpx_codec_priv_t(); ctx.priv = new vpx_codec_alg_priv_t(); //ctx.priv.init_flags = ctx.init_flags; //priv.si.sz = sizeof(priv->si); //priv.decrypt_cb = null; //priv.decrypt_state = IntPtr.Zero; //if (ctx.dec_cfg != null) { /* Update the reference to the config structure to an internal copy. */ //priv.cfg = *ctx->config.dec; ctx.dec_cfg = priv.cfg; //&priv->cfg; //} return(0); }
//vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t* iface, // const uint8_t* data, // unsigned int data_sz, // vpx_codec_stream_info_t* si) //{ // vpx_codec_err_t res; // if (!iface || !data || !data_sz || !si || // si->sz < sizeof(vpx_codec_stream_info_t)) // res = VPX_CODEC_INVALID_PARAM; // else // { // /* Set default/unknown values */ // si->w = 0; // si->h = 0; // res = iface->dec.peek_si(data, data_sz, si); // } // return res; //} //vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t* ctx, // vpx_codec_stream_info_t* si) //{ // vpx_codec_err_t res; // if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t)) // res = VPX_CODEC_INVALID_PARAM; // else if (!ctx->iface || !ctx->priv) // res = VPX_CODEC_ERROR; // else // { // /* Set default/unknown values */ // si->w = 0; // si->h = 0; // res = ctx->iface->dec.get_si(get_alg_priv(ctx), si); // } // return SAVE_STATUS(ctx, res); //} public unsafe static vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t ctx, byte *data, uint data_sz, IntPtr user_priv, long deadline) { vpx_codec_err_t res; /* Sanity checks */ /* NULL data ptr allowed if data_sz is 0 too */ if (ctx == null || data == null || data_sz == 0) { res = vpx_codec_err_t.VPX_CODEC_INVALID_PARAM; } else if (ctx.iface == null || ctx.priv == null) { res = vpx_codec_err_t.VPX_CODEC_ERROR; } else { res = ctx.iface.dec.decode(get_alg_priv(ctx), data, data_sz, user_priv, deadline); } return(ctx != null ? (ctx.err = res) : res); }
public static vpx_codec_alg_priv_t get_alg_priv(vpx_codec_ctx_t ctx) { return(ctx.priv); }
public unsafe IEnumerable <VideoSample> DecodeVideo(byte[] frame, VideoPixelFormatsEnum pixelFormat, VideoCodecsEnum codec) { lock (_decoderLock) { if (_vp8Decoder == null) { _vp8Decoder = new vpx_codec_ctx_t(); vpx_codec_iface_t algo = vp8_dx.vpx_codec_vp8_dx(); vpx_codec_dec_cfg_t cfg = new vpx_codec_dec_cfg_t { threads = 1 }; vpx_codec_err_t res = vpx_decoder.vpx_codec_dec_init(_vp8Decoder, algo, cfg, 0); } //logger.LogDebug($"Attempting to decode {frame.Length} bytes."); //Console.WriteLine(frame.HexStr()); fixed(byte *pFrame = frame) { var result = vpx_decoder.vpx_codec_decode(_vp8Decoder, pFrame, (uint)frame.Length, IntPtr.Zero, 0); //logger.LogDebug($"VP8 decode result {result}."); if (result != vpx_codec_err_t.VPX_CODEC_OK) { logger.LogWarning($"VP8 decode of video sample failed with {result}."); } } IntPtr iter = IntPtr.Zero; var img = vpx_decoder.vpx_codec_get_frame(_vp8Decoder, iter); if (img == null) { logger.LogWarning("Image could not be acquired from VP8 decoder stage."); } else { int dwidth = (int)img.d_w; int dheight = (int)img.d_h; int sz = dwidth * dheight; var yPlane = img.planes[0]; var uPlane = img.planes[1]; var vPlane = img.planes[2]; byte[] decodedBuffer = new byte[dwidth * dheight * 3 / 2]; for (uint row = 0; row < dheight; row++) { Marshal.Copy((IntPtr)(yPlane + row * img.stride[0]), decodedBuffer, (int)(row * dwidth), (int)dwidth); if (row < dheight / 2) { Marshal.Copy((IntPtr)(uPlane + row * img.stride[1]), decodedBuffer, (int)(sz + row * (dwidth / 2)), (int)dwidth / 2); Marshal.Copy((IntPtr)(vPlane + row * img.stride[2]), decodedBuffer, (int)(sz + sz / 4 + row * (dwidth / 2)), (int)dwidth / 2); } } byte[] rgb = PixelConverter.I420toBGR(decodedBuffer, dwidth, dheight, out _); return(new List <VideoSample> { new VideoSample { Width = img.d_w, Height = img.d_h, Sample = rgb } }); } return(new List <VideoSample>()); } }
/*!\brief Retrieve error synopsis for codec context * * Returns a human readable string for the last error returned by the * algorithm. The returned error will be one line and will not contain * any newline characters. * * * \param[in] ctx Pointer to this instance's context. * */ // const char *vpx_codec_error(vpx_codec_ctx_t *ctx); public static string vpx_codec_error(vpx_codec_ctx_t ctx) { return(ctx != null?vpx_codec_err_to_string(ctx.err) : vpx_codec_err_to_string(vpx_codec_err_t.VPX_CODEC_INVALID_PARAM)); }