예제 #1
0
        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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
 /// <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));
 }
예제 #4
0
        /* 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);
        }
예제 #5
0
        /*!\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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
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);
        }
예제 #9
0
 public static vpx_codec_alg_priv_t get_alg_priv(vpx_codec_ctx_t ctx)
 {
     return(ctx.priv);
 }
예제 #10
0
        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>());
            }
        }
예제 #11
0
        /*!\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));
        }