Example #1
0
        /*!\brief Control algorithm
         *
         * This function is used to exchange algorithm specific data with the codec
         * instance. This can be used to implement features specific to a particular
         * algorithm.
         *
         * This wrapper function dispatches the request to the helper function
         * associated with the given ctrl_id. It tries to call this function
         * transparently, but will return #VPX_CODEC_ERROR if the request could not
         * be dispatched.
         *
         * Note that this function should not be used directly. Call the
         * #vpx_codec_control wrapper macro instead.
         *
         * \param[in]     ctx              Pointer to this instance's context
         * \param[in]     ctrl_id          Algorithm specific control identifier
         *
         * \retval #VPX_CODEC_OK
         *     The control request was processed.
         * \retval #VPX_CODEC_ERROR
         *     The control request was not processed.
         * \retval #VPX_CODEC_INVALID_PARAM
         *     The data was not valid.
         */
        //vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t* ctx, int ctrl_id, ...)
        //public static vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t ctx, int ctrl_id, List<Object> valist)
        //{
        //    vpx_codec_err_t res;

        //    if (ctx == null || ctrl_id == 0)
        //    {
        //        res = vpx_codec_err_t.VPX_CODEC_INVALID_PARAM;
        //    }
        //    else if (ctx.iface == null || ctx.priv == null || ctx.iface.ctrl_maps == null)
        //    {
        //        res = vpx_codec_err_t.VPX_CODEC_ERROR;
        //    }
        //    else
        //    {
        //        vpx_codec_ctrl_fn_map_t entry;

        //        res = vpx_codec_err_t.VPX_CODEC_INCAPABLE;

        //        for (entry = ctx.iface.ctrl_maps; entry.fn; entry++)
        //        {
        //            if (entry.ctrl_id == 0 || entry.ctrl_id == ctrl_id)
        //            {
        //                va_list ap;

        //                va_start(ap, ctrl_id);
        //                res = entry.fn((vpx_codec_alg_priv_t)ctx->priv, ap);
        //                va_end(ap);
        //                break;
        //            }
        //        }
        //    }

        //    //return SAVE_STATUS(ctx, res);
        //    return ctx != null ? (ctx.err = res) : res;
        //}

        /*!\brief vpx_codec_control wrapper macro
         *
         * This macro allows for type safe conversions across the variadic parameter
         * to vpx_codec_control_().
         *
         * \internal
         * It works by dispatching the call to the control function through a wrapper
         * function named with the id parameter.
         */
        //#define vpx_codec_control(ctx, id, data) \
        //   vpx_codec_control_##id(ctx, id, data) /**<\hideinitializer*/

        /*!\brief vpx_codec_control type definition macro
         *
         * This macro allows for type safe conversions across the variadic parameter
         * to vpx_codec_control_(). It defines the type of the argument for a given
         * control identifier.
         *
         * \internal
         * It defines a static function with
         * the correctly typed arguments as a wrapper to the type-unsafe internal
         * function.
         */
        //#define VPX_CTRL_USE_TYPE(id, typ)                                           \
        //    static vpx_codec_err_t vpx_codec_control_##id(vpx_codec_ctx_t *, int, typ) \
        //        VPX_UNUSED;                                                            \
        //                                                                                \
        //    static vpx_codec_err_t vpx_codec_control_##id(vpx_codec_ctx_t *ctx,        \
        //                                                int ctrl_id, typ data) {     \
        //    return vpx_codec_control_(ctx, ctrl_id, data);                           \
        //    } /**<\hideinitializer*/

        //public static vpx_codec_err_t vpx_codec_control_hhid(vpx_codec_ctx_t ctx, int ctrl_id, typ data)
        //{
        //    return vpx_codec_control_(ctx, ctrl_id, data);
        //}

        /*!\brief vpx_codec_control deprecated type definition macro
         *
         * Like #VPX_CTRL_USE_TYPE, but indicates that the specified control is
         * deprecated and should not be used. Consult the documentation for your
         * codec for more information.
         *
         * \internal
         * It defines a static function with the correctly typed arguments as a
         * wrapper to the type-unsafe internal function.
         */
        //#define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ)                            \
        //VPX_DECLSPEC_DEPRECATED static vpx_codec_err_t vpx_codec_control_##id( \
        //      vpx_codec_ctx_t *, int, typ) VPX_DEPRECATED VPX_UNUSED;            \
        //                                                                         \
        //  VPX_DECLSPEC_DEPRECATED static vpx_codec_err_t vpx_codec_control_##id( \
        //      vpx_codec_ctx_t *ctx, int ctrl_id, typ data) {                     \
        //    return vpx_codec_control_(ctx, ctrl_id, data);                       \
        //  } /**<\hideinitializer*/

        /*!\brief vpx_codec_control void type definition macro
         *
         * This macro allows for type safe conversions across the variadic parameter
         * to vpx_codec_control_(). It indicates that a given control identifier takes
         * no argument.
         *
         * \internal
         * It defines a static function without a data argument as a wrapper to the
         * type-unsafe internal function.
         */
        //#define VPX_CTRL_VOID(id)                                               \
        //static vpx_codec_err_t vpx_codec_control_##id(vpx_codec_ctx_t *, int) \
        //      VPX_UNUSED;                                                       \
        //                                                                        \
        //  static vpx_codec_err_t vpx_codec_control_##id(vpx_codec_ctx_t *ctx,   \
        //                                                int ctrl_id) {          \
        //    return vpx_codec_control_(ctx, ctrl_id);                            \
        //  } /**<\hideinitializer*/

        //#endif

        //public static vpx_codec_err_t vpx_codec_control<T>(vpx_codec_ctx_t ctx, int ctrl_id)
        //{
        //    return vpx_codec_control_(ctx, ctrl_id);
        //}

        /// <remarks>
        /// Original defintion:
        /// void vpx_internal_error(struct vpx_internal_error_info *info,
        ///  vpx_codec_err_t error, const char* fmt, ...)
        /// The use of the "va_list" parameter when calling this function was minimal.
        /// That left the "fmt" parameter being used as a descriptive error message rather than
        /// a format string.
        /// </remarks>
        public static void vpx_internal_error(ref vpx_internal_error_info info, vpx_codec_err_t error, string fmt)
        {
            //va_list ap;

            info.error_code = error;
            info.has_detail = 0;
            info.detail     = fmt;

            //if (fmt)
            //{
            //    size_t sz = sizeof(info->detail);

            //    info->has_detail = 1;
            //    va_start(ap, fmt);
            //    vsnprintf(info->detail, sz - 1, fmt, ap);
            //    va_end(ap);
            //    info->detail[sz - 1] = '\0';
            //}

            //if (info->setjmp) longjmp(info->jmp, info->error_code);

            VpxException vpxExcp = new VpxException(error, fmt);

            throw vpxExcp;
        }
Example #2
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);
        }
Example #3
0
        /*!\brief Convert error number to printable string
         *
         * 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]    err     Error number.
         *
         */
        // const char *vpx_codec_err_to_string(vpx_codec_err_t err);

        public static string vpx_codec_err_to_string(vpx_codec_err_t err)
        {
            switch (err)
            {
            case vpx_codec_err_t.VPX_CODEC_ERROR: return("Unspecified internal error");

            case vpx_codec_err_t.VPX_CODEC_MEM_ERROR: return("Memory allocation error");

            case vpx_codec_err_t.VPX_CODEC_ABI_MISMATCH: return("ABI version mismatch");

            case vpx_codec_err_t.VPX_CODEC_INCAPABLE:
                return("Codec does not implement requested capability");

            case vpx_codec_err_t.VPX_CODEC_UNSUP_BITSTREAM:
                return("Bitstream not supported by this decoder");

            case vpx_codec_err_t.VPX_CODEC_UNSUP_FEATURE:
                return("Bitstream required feature not supported by this decoder");

            case vpx_codec_err_t.VPX_CODEC_CORRUPT_FRAME: return("Corrupt frame detected");

            case vpx_codec_err_t.VPX_CODEC_INVALID_PARAM: return("Invalid parameter");

            case vpx_codec_err_t.VPX_CODEC_LIST_END: return("End of iterated list");
            }

            return("Unrecognized error code");
        }
        public unsafe void DecodeKeyFrame()
        {
            string hexKeyFrame = "5043009d012a8002e00102c7088585889984880f0201d807f007f4040d6d4a7c9ee0d02c93ed7b7364e70f64e70f64e70c84f70681649f6bdb9b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387900fefc1bddffff15ac3ace2ffc56fffffc56b0eb38bff153dd80";

            byte[] keyFrame = HexStr.ParseHexStr(hexKeyFrame);

            Assert.Equal(573, keyFrame.Length);

            vpx_codec_ctx_t     decoder = 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 = 4
            };
            vpx_codec_err_t res = vpx_decoder.vpx_codec_dec_init(decoder, algo, cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            fixed(byte *pKeyFrame = keyFrame)
            {
                var result = vpx_decoder.vpx_codec_decode(decoder, pKeyFrame, (uint)keyFrame.Length, IntPtr.Zero, 0);

                Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, result);
            }

            IntPtr iter = IntPtr.Zero;
            var    img  = vpx_decoder.vpx_codec_get_frame(decoder, iter);

            Assert.NotNull(img);
            Assert.Equal(640U, img.d_w);
            Assert.Equal(480U, img.d_h);

            byte[] yPlane = new byte[img.stride[0]];
            byte[] uPlane = new byte[img.stride[1]];
            byte[] vPlane = new byte[img.stride[2]];

            Marshal.Copy((IntPtr)img.planes[0], yPlane, 0, yPlane.Length);
            Marshal.Copy((IntPtr)img.planes[1], uPlane, 0, uPlane.Length);
            Marshal.Copy((IntPtr)img.planes[2], vPlane, 0, vPlane.Length);

            logger.LogDebug(HexStr.ToHexStr(yPlane));
            logger.LogDebug(HexStr.ToHexStr(uPlane));
            logger.LogDebug(HexStr.ToHexStr(vPlane));

            string expectedYPlaneHexStr = "0101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101010101010101010101010101010101010101010101010101010101010101";
            string expectedUPlaneHexStr = "02020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202";
            string expectedVPlaneHexStr = "02020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202";

            Assert.Equal(704, yPlane.Length);
            Assert.Equal(352, uPlane.Length);
            Assert.Equal(352, vPlane.Length);
            Assert.Equal(expectedYPlaneHexStr, HexStr.ToHexStr(yPlane));
            Assert.Equal(expectedUPlaneHexStr, HexStr.ToHexStr(uPlane));
            Assert.Equal(expectedVPlaneHexStr, HexStr.ToHexStr(vPlane));
        }
        public unsafe void DecodeKeyFrameSmallTest()
        {
            string hexKeyFrame = "9019009d012a2000180000070885858899848802020275ba24f8de73c58dbdeeeb752712ff80fc8ee701f51cfee1f8e5c007f80ff0dfe73c003fa21e881d603fc07f8e7a287fa3ff25f023fab9fe6bfc4fc00ff1cfe65f3ff800ff46f00fbc5f6f3d5bfdb9cbc7f27fc6dfc88e101fc01f51bfca3f103f29f3817e19fd0ff1d3f243900fa07fe03fc6ff18bf93ed02ff2dfebdfcdff557fa07ba3fecdf8abeb97e10fe9bf8ddf403fc1ff8bff33feaffae5fd73ff9f801fd33f606fd1ff6c52ce5c70fb5b31d19c4d1585982a1d52c92d5044bc6aa90fef98e25c70b5cf745c149e105a557265f8bc910ddd4cb886b7cab7d10d34adb33e89d81e79b23b3a3ff957ee062251d2a350da030f3835bc63663210934f752180ffb727ff1ac46176ff32907dd7e3136e783b35efaa7942bfd44dd8a235af1bffe17985fffecf7417c6a03bfc1a1ff1e474a5479d36a984997847937cf7de46dc9d8424924a7dc90824d92568e635ab5c4cab28adeee56ffca4b7028431c57bf29ffd0701a77d57d889e00cdf4246f94c7b8194e9ad794bf04e08f5e8dfd8e3ba85c9a53b79e07c0a6d522e450d2ba59615f4f32eec7ae529aa1a871fffda4ab9f0eb584bb38392ba87671a35de7973c05c29fff88a95de247f6655a0f2e8797ffd68abf90d359fcde42b78024fce7892f06dd5575f4aa219675afcc85394428ebbbf936ebb3d81f450fab8eef7b81ef5d6227a3b407ffc14c75532c8d63acc8dcdf9b3a1ffedf5b100dab2fd860df7d26843529006b70dacfc8268965c55bf618fc8ff4f04fe10332828dc085ff0aab9895f725562063dda67442d6b9ca8be8c3b70f554050da944adfe1cc2376c6281e4fff013f0f100955110987a750de86d1fb7fe1aba62217c31dda0724eea48372f9e61f8838a080ee4e1bd3233ea3afefabf5cf05f77fe410622f9ef87d3d537ff8a73b22787a00542a940442bfad80c41fb5d46080bba901d21ade640c613c61ad4b15f8a0f91da42ccfa575ee4957adff967140aff4a206acf3c9ab3782d143b9466924de898db1c9cbd5b63736ffc89bda8a44f6f1082f8517a52ad728935e1f0c34927f73600b6dab38ff1e6608ed9b15428092f08bb3e62955bd4bd5513f624fb5ae3618e8dbfeaf992bbc3282ad97653164983f4f2438fad2f7f683b5d6fc6175bb07d3a65ea3483b32fe2125349d3a92c79c011b6c15056ad73bd3620402d301057a904ab755692eb271d2475b6f48acf2538ef6f637d65dfe3f8b70d4603bad4b837def9978d193795afe313bb7ffca3bfcc1aa3dfdf3e325249c59e8b81868f080801ecc7824bb0f0e50ecb3c86ca7e0487fff85bee14ad77c104158879fd1cddd63327ef8fff9b5f84c597dd4723025d87f1dd79bdcd6b7d62625b45f6de1ecb49739363d3ed99fe0fd4d62898af987fc2cda27c6b4bd6816557338d93ddc25632b668fe7fffd70e1027eb39241eb02077844bb7888a09659b1508601742cbdc438ac3bd51130a3fc7caab667259a10914a1743685e196f66df1f4ec0365e69dbab16259d65cb406275c560664079ffd4779362e1f875d3ffe440dd4fe464d64800";

            byte[] keyFrame = HexStr.ParseHexStr(hexKeyFrame);

            Assert.Equal(1134, keyFrame.Length);

            vpx_codec_ctx_t     decoder = 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 = 4
            };
            vpx_codec_err_t res = vpx_decoder.vpx_codec_dec_init(decoder, algo, cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            fixed(byte *pKeyFrame = keyFrame)
            {
                var result = vpx_decoder.vpx_codec_decode(decoder, pKeyFrame, (uint)keyFrame.Length, IntPtr.Zero, 0);

                Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, result);
            }

            IntPtr iter = IntPtr.Zero;
            var    img  = vpx_decoder.vpx_codec_get_frame(decoder, iter);

            Assert.NotNull(img);
            Assert.Equal(32U, img.d_w);
            Assert.Equal(24U, img.d_h);

            byte[] yPlane = new byte[img.stride[0]];
            byte[] uPlane = new byte[img.stride[1]];
            byte[] vPlane = new byte[img.stride[2]];

            Marshal.Copy((IntPtr)img.planes[0], yPlane, 0, yPlane.Length);
            Marshal.Copy((IntPtr)img.planes[1], uPlane, 0, uPlane.Length);
            Marshal.Copy((IntPtr)img.planes[2], vPlane, 0, vPlane.Length);

            logger.LogDebug(HexStr.ToHexStr(yPlane));
            logger.LogDebug(HexStr.ToHexStr(uPlane));
            logger.LogDebug(HexStr.ToHexStr(vPlane));

            string expectedYPlaneHexStr = "c45f65eab237b7e95864ebb034b8e45257e0ae33c3e85764eab536bae95863c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c10202020202020202020202020202020202020202020202020202020202020202";
            string expectedUPlaneHexStr = "81817f7f7d80817e7f80818181827f808080808080808080808080808080808082828282828282828282828282828282";
            string expectedVPlaneHexStr = "7e85837e7f837f8081807d7f81837f818181818181818181818181818181818180808080808080808080808080808080";

            Assert.Equal(96, yPlane.Length);
            Assert.Equal(48, uPlane.Length);
            Assert.Equal(48, vPlane.Length);
            Assert.Equal(expectedYPlaneHexStr, HexStr.ToHexStr(yPlane));
            Assert.Equal(expectedUPlaneHexStr, HexStr.ToHexStr(uPlane));
            Assert.Equal(expectedVPlaneHexStr, HexStr.ToHexStr(vPlane));
        }
Example #6
0
        public static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t ctx, vpx_internal_error_info error)
        {
            vpx_codec_err_t res = error.error_code;

            if (res != vpx_codec_err_t.VPX_CODEC_OK)
            {
                [email protected]_detail = error.has_detail > 0 ? error.detail : null;
            }

            return(res);
        }
        public unsafe void InitialiseDecoderTest()
        {
            vpx_codec_ctx_t     decoder = new vpx_codec_ctx_t();
            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(decoder, vp8_dx.vpx_codec_vp8_dx(), cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            vpx_codec.vpx_codec_destroy(decoder);
        }
        public unsafe void DecodeIntraFrame()
        {
            string hexKeyFrame   = "5043009d012a8002e00102c7088585889984880f0201d807f007f4040d6d4a7c9ee0d02c93ed7b7364e70f64e70f64e70c84f70681649f6bdb9b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387b27387900fefc1bddffff15ac3ace2ffc56fffffc56b0eb38bff153dd80";
            string hexIntraFrame = "b103000f11fc001809d69ffc0d19f9868cfcc343467ffe6001f87fbbbbbbb940fee8d71f8deba446c5ff1bd7488d3c00";

            byte[] keyFrame   = HexStr.ParseHexStr(hexKeyFrame);
            byte[] intraFrame = HexStr.ParseHexStr(hexIntraFrame);

            Assert.Equal(573, keyFrame.Length);

            vpx_codec_ctx_t     decoder = 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 = 4
            };
            vpx_codec_err_t res = vpx_decoder.vpx_codec_dec_init(decoder, algo, cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            fixed(byte *pKeyFrame = keyFrame)
            {
                var result = vpx_decoder.vpx_codec_decode(decoder, pKeyFrame, (uint)keyFrame.Length, IntPtr.Zero, 0);

                Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, result);
            }

            IntPtr iter = IntPtr.Zero;
            var    img  = vpx_decoder.vpx_codec_get_frame(decoder, iter);

            Assert.NotNull(img);
            Assert.Equal(640U, img.d_w);
            Assert.Equal(480U, img.d_h);

            img.Dispose();
            img = null;

            fixed(byte *pIntraFrame = intraFrame)
            {
                var result = vpx_decoder.vpx_codec_decode(decoder, pIntraFrame, (uint)intraFrame.Length, IntPtr.Zero, 0);

                Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, result);
            }

            img = vpx_decoder.vpx_codec_get_frame(decoder, iter);

            Assert.NotNull(img);
            Assert.Equal(640U, img.d_w);
            Assert.Equal(480U, img.d_h);
        }
        public unsafe void DecodeTestPatternSequence()
        {
            vpx_codec_ctx_t     decoder = 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(decoder, algo, cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            FileStream fs = new FileStream("capture.stm", FileMode.Open, FileAccess.Read);

            int count = 0;

            byte[] buffer = new byte[100000];

            while (fs.Position < fs.Length)
            {
                string lenStr = null;
                char   c      = (char)fs.ReadByte();
                while (c != ',')
                {
                    lenStr += c;
                    c       = (char)fs.ReadByte();
                }

                int len = Convert.ToInt32(lenStr);
                logger.LogDebug($"Reading frame of length {len}.");
                fs.Read(buffer, 0, len);

                logger.LogDebug($"DECODING FRAME {count++}:");

                fixed(byte *pBuffer = buffer)
                {
                    var result = vpx_decoder.vpx_codec_decode(decoder, pBuffer, (uint)len, IntPtr.Zero, 0);

                    Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, result);
                }

                IntPtr iter = IntPtr.Zero;
                var    img  = vpx_decoder.vpx_codec_get_frame(decoder, iter);

                Assert.NotNull(img);
                Assert.Equal(640U, img.d_w);
                Assert.Equal(480U, img.d_h);
            }
        }
        public unsafe void DecodeNullDataTest()
        {
            vpx_codec_ctx_t     decoder = 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 = 4
            };
            vpx_codec_err_t res = vpx_decoder.vpx_codec_dec_init(decoder, algo, cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            var result = vpx_decoder.vpx_codec_decode(decoder, null, 0, IntPtr.Zero, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_INVALID_PARAM, result);
        }
        public unsafe void DecodeKeyFrameFromFileTest()
        {
            byte[] kfBytes = HexStr.ParseHexStr(File.ReadAllText("testpattern_keyframe.vp8"));

            Assert.Equal(15399, kfBytes.Length);

            vpx_codec_ctx_t     decoder = 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 = 4
            };
            vpx_codec_err_t res = vpx_decoder.vpx_codec_dec_init(decoder, algo, cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            fixed(byte *pKeyFrame = kfBytes)
            {
                var result = vpx_decoder.vpx_codec_decode(decoder, pKeyFrame, (uint)kfBytes.Length, IntPtr.Zero, 0);

                Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, result);
            }

            IntPtr iter = IntPtr.Zero;
            var    img  = vpx_decoder.vpx_codec_get_frame(decoder, iter);

            Assert.NotNull(img);
            Assert.Equal(640U, img.d_w);
            Assert.Equal(480U, img.d_h);

            byte[] bgr = ImgHelper.I420toBGR(img.planes[0], img.stride[0],
                                             img.planes[1], img.stride[1],
                                             img.planes[2], img.stride[2],
                                             640, 480);

            Assert.Equal(921600, bgr.Length);

            fixed(byte *bmpPtr = bgr)
            {
                Bitmap bmp = new Bitmap((int)img.d_w, (int)img.d_h, (int)img.d_w * 3, System.Drawing.Imaging.PixelFormat.Format24bppRgb, new IntPtr(bmpPtr));

                bmp.Save("decodekeyframe.bmp");
                bmp.Dispose();
            }
        }
Example #12
0
        /// <summary>
        /// Update the input fragment data.
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="data"></param>
        /// <param name="data_sz"></param>
        /// <param name="res"></param>
        /// <returns>
        /// <=0: Error.
        /// 1: OK.
        /// </returns>
        public unsafe static int update_fragments(vpx_codec_alg_priv_t ctx, byte *data,
                                                  uint data_sz, out vpx_codec_err_t res)
        {
            res = vpx_codec_err_t.VPX_CODEC_OK;

            if (ctx.fragments.count == 0)
            {
                /* New frame, reset fragment pointers and sizes */
                //memset((void*)ctx.fragments.ptrs, 0, sizeof(ctx.fragments.ptrs));
                //memset(ctx.fragments.sizes, 0, sizeof(ctx.fragments.sizes));
                Array.Clear(ctx.fragments.ptrs, 0, ctx.fragments.ptrs.Length);
                Array.Clear(ctx.fragments.sizes, 0, ctx.fragments.sizes.Length);
            }
            if (ctx.fragments.enabled > 0 && !(data == null && data_sz == 0))
            {
                /* Store a pointer to this fragment and return. We haven't
                 * received the complete frame yet, so we will wait with decoding.
                 */
                ctx.fragments.ptrs[ctx.fragments.count]  = data;
                ctx.fragments.sizes[ctx.fragments.count] = data_sz;
                ctx.fragments.count++;
                if (ctx.fragments.count > (1 << (int)TOKEN_PARTITION.EIGHT_PARTITION) + 1)
                {
                    ctx.fragments.count = 0;
                    res = vpx_codec_err_t.VPX_CODEC_INVALID_PARAM;
                    return(-1);
                }
                return(0);
            }

            if (ctx.fragments.enabled == 0 && (data == null && data_sz == 0))
            {
                return(0);
            }

            if (ctx.fragments.enabled == 0)
            {
                ctx.fragments.ptrs[0]  = data;
                ctx.fragments.sizes[0] = data_sz;
                ctx.fragments.count    = 1;
            }

            return(1);
        }
        /// <summary>
        /// Attempts to decode a series of VP8 encoded frames that were captured from a Chrome WebRTC session.
        /// </summary>
        //[Fact(Skip ="TODO")]
        public unsafe void DecodeChromeFrameSequence()
        {
            string[] frames =
            {
                "D04C009D012A4001F000392F00171C221616226612205C0EEE032AD4822069ADD34F6945BA7BAD9C443224B9CD25E10FF73B7A373746523EC2614922EF8F2819E93B7F2FECBF4A1C3F2915AA529E7F947A50B36C68301E5208B5DE5DD4A3A64354BEA6E010FFED6154A9DDBD77CCE4B3396FFD4EC3E38A083249F04EC98F87B56B3289A6FBC1997DDE229C526EA2C7A91BE61F9589FD205FCDE191995AA93621015FA1C6679956314F6C8A9A81C2905A4BDC53B68337E4FC166C79EC227A45D8F37EA52D9607A6340522F947E9D5B99002A2BFB2F986922913B2A1DA73EE858E2B731987BE6A642998FCE34C440CF5CACF29BAB6C665534004CA1429A4E91E8A6E8B489460182F2AC9ADFF1061E95DBE522B2345E5722E82379FF15863076D6DF51EA02BDD3B9CB2226275E58D102757C02361D893E79A41A7D982B78DFD1EFF10C4E8D3AA75DB266FFD33DE10AFD2F42100F6D6CDA6670998468C1A84008B1B27E7AE0D5546CC3351251FE10D2A95A36EF374AC00D2B4DB02E2A9D8D5506B3A2B859627C459F23718B23ED7E3073454984E843FE096ABF787B8699AB21F0D7BFCEB028DF98161B3A06ADAE6C9726EB56B00758A9AF43479DB0AA565955C64F1964916B107CC860E19A1DB4FB4E9DC4FF37C7AB5E800DCF05AC09A16E89BF0E85B515441BE088567188FB8200D59AB7834562D56C8175EF174F5D9925520359486C16898494C25347588F31BEF2C9E3211B5FA4A17E2000F0CADFC94C6CCED4A9F1CC0F56F0FAD946D8FA443F047224360604446F2A5090BC26A2FB2F658598570D8D8CC3AC2C4317547168A6CB3C93DD3B96D0AE94C239340505B92C20119869383AAE24805EA489C4FF842BA720C00FEE1132760711868527B241870C7DB03F4DB232BD52546B417C2321245BDDF22501528699248E06A1233742E6004CD169062D95EFE821E71854E1EBEBB8F132FC791B7FD1AB56CD8A77705C653BDA1415510C25A0F1EB6A78A0C61EB8B9D8BAC149D09E0A1671EC88E487D136487B6F2976FE86BA477B10C30BA432DAAF8F5AAF907E1082943B473DCF8F9DD1E3165B4A74A7CDCD7CA8780BA11FA9A74CF29BB5753B7172EAC589C2A59697C6A66BD26BE179A66C1452F49A4ACF67FD970856CA837FBB47F51FEDFCCE321CC9E5742FB4746641074630DE9EEC51409FD4B740CEE6D5D087E4DECCAE982889AB9E1C7D2F75461A7EF712044734948D9BD1A9A9F7E111CAA17532CA00990B2E9E7CCF393839D97743A423EDA8D81A0E51C5D17CE9120B73E60BA5B42BB64C92FC9BE2DE96995BCC20934633EC78B486520B10C31AF7941FA3D5E0F67689410521130196A3078390476A8A93DB77DE64E645D8408591F5FFD0D5A18A72ADD5B2AB7C5FA344CF2544AA228FB0B9256CE8E38D5E6F9D44D30F9886ACF3A220D6C126160E2FC3A9D68A269219124B3CABE0E529098A87D31C7B1C13B65A4A65690EFAE6B5C810C52D3EB77392855823803579F2A2996E61061074F5F6E380E7E4AE16994428E776202BCFB52868C475458D172056379DA7FC7150C4124186E3641181EAD32D02018A70EAA9D46587307F35A8CE6EC81B96C809166EE28FB9B962759E9D33EF3B82C4AD4B56C5F76B726503A1EF93DF6500228D26B6BA163C9263D8F5533EF2AF23DB79967001F9DCC7A9FBC6FBF130FF3810C7C76337ABF17475CFF85951F19F1A5AA6A5B09C3EAABEC8577D3CD4D0175A40866644C08C6A5A91E174A785A41D5FCFFA37BCFA70C7B353BF759D1F2C9451DA028FF9FD698546D47593E591A82312F78252E16269FC1797FCDA441D5D0E00926F6D3C0CCF1E1611907B7D588F2566BE8E5C0B0EF1DFEBBBCF6CEA9C500EB192F885823D6D6CA2EB344B0E35EC0809827E6346BF7E4F332A765CF845F9312793FEE9E7C55D5ECF869CBAAF4C244AE2EDB0AFAB1D134440A36F96D36115E4F469B6A648F9FF96CF84CEA639C4F74540520A1A7694DA1661BABBEB75BD52458A239A1F191DB9E99BF38EC71F4763EE0A27ED159713A9CBE0FCA4659FB89C685E12DF293F149CAAB7F8C99FD54A581CA68EF5850D3A1E5B1A801719EAB0DF39CD5FBEAE6E7149B8AB4801CF1668313903E0B1CD82770B3D753F31B2122536CB99CA9F2EB529DE0C7F4BB67520E950E27D3ECAD85B0DA3780646C1E3BDED4D44189D44725087F4F5E4CCE56ADD4265C6C919A437A0BFE574314B25F993DAE21E522E3946B0129180F90966CD1A1777DD30C7856298DA87ECA2884E70B75F2ADA5EFE2B44B9443C8AF254EF94E113B5EC012E93A881E5236181CF7C0E80250FC0AA4ADC5DD57357322B80551616CABAFF276DEADB2FBE3DE2BD07D0471CE56EEEAC23BF4A0D2861ED1548AA4E66A10B9FFFE0DF78BB9F5609DDFAEFB50935E6D8F0BD2266BFFA953D7049517FECDD917196AB32FA5BBFDDED0201C535E1B92F9B8BB054932B61F24422E1C2D0E7FCA8319A1E9C70E7E7060E2C7D1D5BAA4E5E555DD6B365EB22650E4AD116C2E5A97A82F7D86CC39ED66BE73559EF861D67869FD7989D9FC2DE1A32D23DA9355011102BD0D99069A3F2E7D9CFBCBFF3A31CD56F0E526CD9E846DA8A460A24BD51FC2EF55AB33864BAE4F877D0DD7734AF2FA50673EC337DE0FFD75A322E0CFBF511373AC0DEF8CC4AE73724E82E6F9D783198F57095980F219791F83862313BE813D387EF3F6430542FDE1776018737CD29F3535A67AFBB4D096BCF5E4792340DE78ED9A34A2A802FF3F997023FE1E9C1AFE8CABC5D06088E17B6A6A1077F56666AA2882176487D218415359742297A2F14F0838D6207D2DB4C34DF9717673F0B81D24E1EAACCF64F22556BCA10E876D32CDF11117FFC91A9923CC8B62666294E270E32413C33438B0B2A08A7731B1056C8451663DE58BB4C166E8F7C20D8A2CEDB2FA613DF9471844C1CBCAC6A3A69432518D6E172F313C6DB21C554E8EB2B930BF0FB5F69F2A327D34C83078F08C48E84D614746579E6641F3DB6D97477D0B5A7ADB49F7918506C9161405B9681E39005BE66015DFD506382BBD6F8B85B080BDE5A3D5D8DF118B67676C7FAA8B420A934569449EFA346794B0B6F896899B7436CF16750E7E7EB4BC9139687497E7A99EFEC430284E2EB55EF47B4F8AA1AF927523D56B87AA01A3207785051612A8A0200125ABF36E49D0F6603973577396B152AAA050FEC2C9B14328808330CC14709EAF06043256742605D36F6D7572B0B51894ABBB30D48AD64B0B3041B1D50845B8D82311ACB988E4D9B868A25F0E5C9383A1D8A3542450F6E3FB84DB1634105F16CFC8ECCE5C9F333E265B871593F835AAFD59F4AA0F37944876BE53F0BE52BFD2E377E868A04CFB043CFCA36A1CDCB5903C76CCF5FC43BF0B0551F3B3F287D5F995E82BDE433894346AA15DBFF6231339503980008367B819607407EF8580B1F0E95D63D0E4CFE0B77C5D9C3951A44C6A0756CD8D14E747BC54312E47B85F70C9E43FA66728A1C221B56BBE22A4F56505EBA91116A7E4C9939C418FD32A797ADBC9C73DC6F7AA5761F78D7BBA50F722D4323BFA65396F9C50CE01F3A6BE884525CA2A41A85B4315BC1F27D9C6E13BA6073439B186D775CD3B26A2A2E5447A0E4F19535640B30BDB51E4A6655E4ACC0C5CFD5A5C198E560FEF437AC7691CF23A9700068CED10C74A54BFF713255D79465A7C7FCCF36FFACA58CF54F9B818344A3F3B3DE5A897E1F7142C5BBC8A60D76C476B8CE16DC63242E037215A305F004C94B13B297741BE9E1ED8253D1B0CC88EED1F90685D20F6400FA5EBFAD0AEA66F41223EA9DB8E06FFF24BA372612804856DAF7546E33C69FBAC05BE53554F383E531AF3F098",
                "310700E4E0AFB8BFCFA747A7D88517F2496030B237169B9086BE506176B28BBABE2B28BBABB83A05847F7440814B175022108FAEAE06A36B717221400F908385A6CC9620E39E0700",
                "510600E4E0AFB8D37E12C05F406760BFD000CA3831ABD68CE9EEDCDBA87A6BAC7740EEDA37A587D7F6A8A75F01661AE8A0EB0F7AE007EA2C9E68955E3F791BDC80",
                "F10500E4A91FB8CB8D24A05F406520BFD0009744A8E87FAF48851B25992CC6001D462EFE16F778938D8B15FD06AD580B9140B160963AB2CE2A615840",
                "310700E4797FB8B3BC6620604FDC0F1A1AF9402FF8730DE0342C11FAB3BB3BABF557EAB7F7D04AE308CDAC073D56F4526572EA0EE83997538725ECC08B3E15FB7ACE8CD77AA858F0B31DC438",
                "910800E441EFB8C39B87E061714813CD2077E0613810C867FEEE55AF44B1EB89E2B300D3C565D030A3D7061E7D6C1C4529520505E8D74EECA8B1D5AE9A2CE73D5FB22E89752A00CF90F497929B8C7417E6AE749C6116B4C8D1602D7F590889C1D90D339A53ED97C3323893D80DCC04C138E162A10944813D00",
                "510900E41A3FB8CF82F9007ABE51A4CAFB4E6AB4A3D702AC3DE01A0AE1109C07AFBF27D04103D4CAB08583E81EE72301FEB39962440C225D348D2C0E348F426BCA8EF0B6B24B83D928737BDA584951AD6F81F9115EC83C6B54ED083D9B71DB8F0A4F0BF13017D583B32532179668D4B7D78B7908125F98136C2ACE8C70B26C7522A7D422D5BF229B5E165B387AE70258AC6CFF72DCB8FAE84B0201AF72F28F61FC81CE1FC7B9F9AD154CA78092310FA213230AE8A8A555C59BB87DF540988E466D50017F723620D5D821945D6C1A1F8FEB3A4400"
            };

            vpx_codec_ctx_t     decoder = 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(decoder, algo, cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            foreach (var frame in frames)
            {
                byte[] buffer = HexStr.ParseHexStr(frame);

                fixed(byte *pBuffer = buffer)
                {
                    var result = vpx_decoder.vpx_codec_decode(decoder, pBuffer, (uint)buffer.Length, IntPtr.Zero, 0);

                    Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, result);
                }

                IntPtr iter = IntPtr.Zero;
                var    img  = vpx_decoder.vpx_codec_get_frame(decoder, iter);

                Assert.NotNull(img);
                Assert.Equal(320U, img.d_w);
                Assert.Equal(240U, img.d_h);
            }
        }
        public unsafe void DecodeEmptyFrameDataTest()
        {
            vpx_codec_ctx_t     decoder = 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 = 4
            };
            vpx_codec_err_t res = vpx_decoder.vpx_codec_dec_init(decoder, algo, cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            byte[] dummyData = new byte[1024];
            fixed(byte *dummy = dummyData)
            {
                var result = vpx_decoder.vpx_codec_decode(decoder, dummy, (uint)dummyData.Length, IntPtr.Zero, 0);

                Assert.Equal(vpx_codec_err_t.VPX_CODEC_UNSUP_BITSTREAM, result);
            }
        }
Example #15
0
        //public unsafe static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t ctx,
        //                          ref vpx_codec_stream_info_t si)
        //{
        //    uint sz;

        //    if (si.sz >= sizeof(vp8_stream_info_t))
        //    {
        //        sz = sizeof(vp8_stream_info_t);
        //    }
        //    else
        //    {
        //        sz = sizeof(vpx_codec_stream_info_t);
        //    }

        //    memcpy(si, &ctx->si, sz);
        //    si->sz = sz;

        //    return VPX_CODEC_OK;
        //}

        public unsafe static vpx_codec_err_t vp8_peek_si_internal(byte *data,
                                                                  uint data_sz,
                                                                  ref vpx_codec_stream_info_t si,
                                                                  vpx_decrypt_cb decrypt_cb,
                                                                  IntPtr decrypt_state)
        {
            vpx_codec_err_t res = vpx_codec_err_t.VPX_CODEC_OK;

            //assert(data != NULL);
            if (data == null)
            {
                return(vpx_codec_err_t.VPX_CODEC_INVALID_PARAM);
            }

            if (data + data_sz <= data)
            {
                res = vpx_codec_err_t.VPX_CODEC_INVALID_PARAM;
            }
            else
            {
                /* Parse uncompresssed part of key frame header.
                 * 3 bytes:- including version, frame type and an offset
                 * 3 bytes:- sync code (0x9d, 0x01, 0x2a)
                 * 4 bytes:- including image width and height in the lowest 14 bits
                 *           of each 2-byte value.
                 */
                byte[] clear_buffer = new byte[10];
                byte * clear        = data;
                //if (decrypt_cb)
                //{
                //    int n = VPXMIN(sizeof(clear_buffer), data_sz);
                //    decrypt_cb(decrypt_state, data, clear_buffer, n);
                //    clear = clear_buffer;
                //}
                si.is_kf = 0;

                if (data_sz >= 10 && (clear[0] & 0x01) == 0)
                { /* I-Frame */
                    si.is_kf = 1;

                    /* vet via sync code */
                    if (clear[3] != 0x9d || clear[4] != 0x01 || clear[5] != 0x2a)
                    {
                        return(vpx_codec_err_t.VPX_CODEC_UNSUP_BITSTREAM);
                    }

                    si.w = (uint)(clear[6] | (clear[7] << 8)) & 0x3fff;
                    si.h = (uint)(clear[8] | (clear[9] << 8)) & 0x3fff;

                    /*printf("w=%d, h=%d\n", si->w, si->h);*/
                    if (si.h == 0 || si.w == 0)
                    {
                        res = vpx_codec_err_t.VPX_CODEC_CORRUPT_FRAME;
                    }
                }
                else
                {
                    res = vpx_codec_err_t.VPX_CODEC_UNSUP_BITSTREAM;
                }
            }

            return(res);
        }
Example #16
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>());
            }
        }
Example #17
0
 public VpxException(vpx_codec_err_t errorCode, string errorMessage) :
     base(errorMessage)
 {
     ErrorCode = errorCode;
 }
Example #18
0
        public unsafe static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t ctx,
                                                        byte *data, uint data_sz,
                                                        IntPtr user_priv, long deadline)
        {
            try
            {
                vpx_codec_err_t res = vpx_codec_err_t.VPX_CODEC_OK;
                uint            resolution_change = 0;
                uint            w, h;

                if (ctx.fragments.enabled == 0 && data == null && data_sz == 0)
                {
                    return(0);
                }

                /* Update the input fragment data */
                if (update_fragments(ctx, data, data_sz, out res) <= 0)
                {
                    return(res);
                }

                /* Determine the stream parameters. Note that we rely on peek_si to
                 * validate that we have a buffer that does not wrap around the top
                 * of the heap.
                 */
                w = ctx.si.w;
                h = ctx.si.h;

                //res = vp8_peek_si_internal(ctx.fragments.ptrs[0], ctx.fragments.sizes[0],
                //                           ctx.si, ctx.decrypt_cb, ctx.decrypt_state);

                res = vp8_peek_si_internal(ctx.fragments.ptrs[0], ctx.fragments.sizes[0],
                                           ref ctx.si, null, IntPtr.Zero);

                if (res == vpx_codec_err_t.VPX_CODEC_UNSUP_BITSTREAM && ctx.si.is_kf == 0)
                {
                    /* the peek function returns an error for non keyframes, however for
                     * this case, it is not an error */
                    res = vpx_codec_err_t.VPX_CODEC_OK;
                }

                if (ctx.decoder_init == 0 && ctx.si.is_kf == 0)
                {
                    res = vpx_codec_err_t.VPX_CODEC_UNSUP_BITSTREAM;
                }

                if ((ctx.si.h != h) || (ctx.si.w != w))
                {
                    resolution_change = 1;
                }

                /* Initialize the decoder instance on the first frame*/
                if (res == vpx_codec_err_t.VPX_CODEC_OK && ctx.decoder_init == 0)
                {
                    VP8D_CONFIG oxcf = new VP8D_CONFIG();

                    oxcf.Width             = (int)ctx.si.w;
                    oxcf.Height            = (int)ctx.si.h;
                    oxcf.Version           = 9;
                    oxcf.postprocess       = 0;
                    oxcf.max_threads       = (int)ctx.cfg.threads;
                    oxcf.error_concealment = (int)([email protected]_flags & vpx_decoder.VPX_CODEC_USE_ERROR_CONCEALMENT);

                    res = onyxd.vp8_create_decoder_instances(ctx.yv12_frame_buffers, oxcf);
                    if (res == vpx_codec_err_t.VPX_CODEC_OK)
                    {
                        ctx.decoder_init = 1;
                    }
                }

                if (res == vpx_codec_err_t.VPX_CODEC_OK)
                {
                    VP8D_COMP  pbi = ctx.yv12_frame_buffers.pbi[0];
                    VP8_COMMON pc  = pbi.common;
                    if (resolution_change > 0)
                    {
                        MACROBLOCKD xd = pbi.mb;

                        pc.Width  = (int)ctx.si.w;
                        pc.Height = (int)ctx.si.h;
                        {
                            int prev_mb_rows = pc.mb_rows;

                            // Port AC: TODO identify alternative error mechanism.
                            //if (setjmp(pbi.common.error.jmp))
                            //{
                            //    pbi.common.error.setjmp = 0;
                            //    /* on failure clear the cached resolution to ensure a full
                            //     * reallocation is attempted on resync. */
                            //    ctx.si.w = 0;
                            //    ctx.si.h = 0;
                            //    vpx_clear_system_state();
                            //    /* same return value as used in vp8dx_receive_compressed_data */
                            //    return -1;
                            //}

                            //pbi.common.error.setjmp = 1;

                            if (pc.Width <= 0)
                            {
                                pc.Width = (int)w;
                                vpx_codec.vpx_internal_error(ref pc.error, vpx_codec_err_t.VPX_CODEC_CORRUPT_FRAME,
                                                             "Invalid frame width");
                            }

                            if (pc.Height <= 0)
                            {
                                pc.Height = (int)h;
                                vpx_codec.vpx_internal_error(ref pc.error, vpx_codec_err_t.VPX_CODEC_CORRUPT_FRAME,
                                                             "Invalid frame height");
                            }

                            if (alloccommon.vp8_alloc_frame_buffers(pc, pc.Width, pc.Height) != 0)
                            {
                                vpx_codec.vpx_internal_error(ref pc.error, vpx_codec_err_t.VPX_CODEC_MEM_ERROR,
                                                             "Failed to allocate frame buffers");
                            }

                            xd.pre = pc.yv12_fb[pc.lst_fb_idx];
                            xd.dst = pc.yv12_fb[pc.new_fb_idx];

                            mbpitch.vp8_build_block_doffsets(pbi.mb);

                            // Port AC: Assume this cast was a noop to remove compiler warning.
                            //(void)prev_mb_rows;
                        }

                        // Port AC: TODO identify alternative error mechanism.
                        //pbi.common.error.setjmp = 0;

                        /* required to get past the first get_free_fb() call */
                        pbi.common.fb_idx_ref_cnt[0] = 0;
                    }

                    // Port AC: TODO identify alternative error mechanism.
                    //if (setjmp(pbi.common.error.jmp))
                    //{
                    //    vpx_clear_system_state();
                    //    /* We do not know if the missing frame(s) was supposed to update
                    //     * any of the reference buffers, but we act conservative and
                    //     * mark only the last buffer as corrupted.
                    //     */
                    //    pc.yv12_fb[pc.lst_fb_idx].corrupted = 1;

                    //    if (pc.fb_idx_ref_cnt[pc.new_fb_idx] > 0)
                    //    {
                    //        pc.fb_idx_ref_cnt[pc.new_fb_idx]--;
                    //    }
                    //    pc.error.setjmp = 0;

                    //    res = update_error_state(ctx, pbi.common.error);
                    //    return res;
                    //}

                    //pbi.common.error.setjmp = 1;

                    /* update the pbi fragment data */
                    pbi.fragments = ctx.fragments;

                    ctx.user_priv = user_priv;
                    if (onyxd.vp8dx_receive_compressed_data(pbi, deadline) != 0)
                    {
                        res = update_error_state(ctx, pbi.common.error);
                    }

                    /* get ready for the next series of fragments */
                    ctx.fragments.count = 0;
                }

                return(res);
            }
            catch (VpxException vpxExcp)
            {
                return(vpxExcp.ErrorCode);
            }
        }
        public unsafe void DecodeFrameSequenceSmallTest()
        {
            string[] frames =
            {
                "9018009d012a2000180000470885858899848802020275bb8dd4fecdf8abcb8dbdfdb9da24247d35fd47f22bfc96f16ff49fc80e003fa61fd8bd527a807f49bac07d007f80ff2bf475fd8cf817fd77ff6bfe9be02ff927f30bb05fa37807e13fafbea2e4a2f9f7e44fe336a1afe59f8b1f8e59c0bf0cfe6bf8e9f913c667f881f01bf837f2efcb8feb3b417fc8ffa8ff2bfd80fe4fef13f9bfe0bfab5f8d7f9d7e35fd00ff0cfe31fd1ffb07ec8ff5cfff1f481d41bfa65ed8a59cb8e130f4aaac8d3237adbeeb1ca3bcb6680e00fef3affe087e767c16538572fceece4e3be74dfe581641891a620517c648d8f556486cdf342c8ab7e431c1ed50fabb6aee29dad8fa9fd73e931b20ff6a5db9b92de9dfffe062047b5022cf6522bb9e2e2383db3e90ffb7c8874a31d2e3c3ffff72192ffff59cf5363370485d0d87c9087179763da106e0955bd9bc772eb1badfe823ee272f1038b3db2b091578a623fe9ee9c508f981838d9744ee15ce2d1508075e661abc305925d21fd4e2849526d803c5a4acb1ba9d2f05448d9b165d93216507c8cd24e1caf4dffc551b2f9b2d847598ef771140626fc52150726b1c3f361b737814de3b1c26222194ff42fbcd3da5fd1ece1facb53d668f625d5db3db0646f7592ef9d3018ceb0ec9ca139a4a544fa225dc3fe4375c94df25b2ba998dcf82c7ffaff1478a50778a7a0312557c3b9326e745faa0a09aed2f574acc75a24fb2f4591096691f31aac45bfab0d3e4766feacae7e04faed37eafbed8276bfdf41445feb297fe244905702f7a09fd823c97127d29ccb9048122d490662b6405ea984d4eddad68afccceaa8a96c095cffff365b88872e17efd9b2b1de34623c03164d3ab5fb083f2c8ff84e51b1231b7e1738bfcfbf52b2f38eb762e79f02c5fb8617f8b7be85142f1a94f806be88770976826015e752fffe152dd2d240fa7dcbb69e55710c843077da93892ece44333754274e77b3fe136f8a82e0812bcbfe15a60cb8b17b200790074788313b7fedb2669dd917ce79898ecc1706ae0ac5da2e0eb79e5bd9cd433d2a36b2a4f571f4f735acfe03aefaaff20ae0c69ba591a00bfc322f987f7f2db529662c86c2395b63a68c8384b4327450c2d6217d87fff619fd96f9ae910bd720096bcbd48a81dbc5c9149c4d2e2f9ad10ddfe059fbaf769e714454a1fdd2e39587eadfbd9a7e1926c3e311c724bcd963bc6280a7ba05eb193c176868bcba10d8dc7fc2193c3ef19d560e08ec555e657fe9032ce3db6a3a1ad2b5782812a13718ecdb53216bee4e2a658d90bd147b23f2ab1869b9d24eaf3aa08df38825798cfe0f4f4096d4acad4cea1cf2b10b8fe83dc977f7efbc83f471aad72bb8163f71a4753ff818e1ea4ef674c6ffb74bd57f487c74610eff459b43bd06304035deab41d00bd4b0c3be41f7c024d01d1ba7fd5785bb3d06eec5f1391ffd976d9031374bbaf527187fd2188d1b3034bfd5005fd3f70e9462ef684e000",
                "110300011010001e7d6793bb0281476fb1cd5fe1f905f7820021c0c501fd15cddaf31b35cf70ec386f714c008dc01b8d38e79c55214387a3c3aca44c018d8004273408fda90175befca1ae4f24b72bb2f575792a216bfeaa80",
                "d1010001101000180d2ad1b731bb900214c78b0fff015a1c0015db3e51ac3e40090a6f9f48fa9b8018409f80",
                "d10100011010001ee7401595557aa0021c76001db5973accd2fa004a207000",
                "b1010001101000180030282ff400043876002495973accd2fa0012a08740",
                "b1010001101000180030282ff400043876001db5973accd2fa004a207000"
            };

            vpx_codec_ctx_t     decoder = 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(decoder, algo, cfg, 0);

            Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, res);
            Assert.NotNull(decoder);

            int count = 0;

            foreach (var frame in frames)
            {
                logger.LogDebug($"DECODING FRAME {count}:");

                byte[] buffer = HexStr.ParseHexStr(frame);

                fixed(byte *pBuffer = buffer)
                {
                    var result = vpx_decoder.vpx_codec_decode(decoder, pBuffer, (uint)buffer.Length, IntPtr.Zero, 0);

                    Assert.Equal(vpx_codec_err_t.VPX_CODEC_OK, result);
                }

                IntPtr iter = IntPtr.Zero;
                var    img  = vpx_decoder.vpx_codec_get_frame(decoder, iter);

                Assert.NotNull(img);
                Assert.Equal(32U, img.d_w);
                Assert.Equal(24U, img.d_h);

                byte[] yPlane = new byte[img.stride[0]];
                byte[] uPlane = new byte[img.stride[1]];
                byte[] vPlane = new byte[img.stride[2]];

                Marshal.Copy((IntPtr)img.planes[0], yPlane, 0, yPlane.Length);
                Marshal.Copy((IntPtr)img.planes[1], uPlane, 0, uPlane.Length);
                Marshal.Copy((IntPtr)img.planes[2], vPlane, 0, vPlane.Length);

                switch (count)
                {
                case 0:
                    Assert.Equal("b66065dbaa3dafd75b65dba939afcf575ad2a63db6d85a68d8ab3cafda5a67b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b51010101010101010101010101010101010101010101010101010101010101010",
                                 HexStr.ToHexStr(yPlane));
                    Assert.Equal("817e7f7e7f817d7e7f7e7e7f807e82a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a284848484848484848484848484848484",
                                 HexStr.ToHexStr(uPlane));
                    Assert.Equal("807e7f7f7f807f7e7f807e7f7f7e6163636363636363636363636363636363637d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d",
                                 HexStr.ToHexStr(vPlane));
                    break;

                case 1:
                    Assert.Equal("b86165dba93db0d85b65dba93aaed15659d1a53cb6d85a68d8ab3cafda5a67b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b51010101010101010101010101010101010101010101010101010101010101010",
                                 HexStr.ToHexStr(yPlane));
                    Assert.Equal("817e7f7e7f807e7e807e7e7e7f7f83a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a184848484848484848484848484848484",
                                 HexStr.ToHexStr(uPlane));
                    Assert.Equal("7f7f807e7f807f7e7f807e7f807f6162626262626262626262626262626262627e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e",
                                 HexStr.ToHexStr(vPlane));
                    break;

                case 2:
                    Assert.Equal("b86165dba93db0d85b65dba93bafd15559d1a53cb6d85a68d8ab3cafda5a67b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b51010101010101010101010101010101010101010101010101010101010101010",
                                 HexStr.ToHexStr(yPlane));
                    Assert.Equal("817e7f7e7f817d7e807e7e7e7f7f83a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a184848484848484848484848484848484",
                                 HexStr.ToHexStr(uPlane));
                    Assert.Equal("7f7f807e7f807f7e7f807e7f817e6063636363636363636363636363636363637e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e",
                                 HexStr.ToHexStr(vPlane));
                    break;

                case 3:
                    Assert.Equal("b86165dba93db0d85b65dba93bafd15559d1a53cb6d85a68d8ab3cafda5a67b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b51010101010101010101010101010101010101010101010101010101010101010",
                                 HexStr.ToHexStr(yPlane));
                    Assert.Equal("817e7f7e7f807e7e807e7e7e7f7f83a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a184848484848484848484848484848484",
                                 HexStr.ToHexStr(uPlane));
                    Assert.Equal("7f7f807e7f807f7e7f807e7f817e6063636363636363636363636363636363637e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e",
                                 HexStr.ToHexStr(vPlane));
                    break;

                case 4:
                    Assert.Equal("b86165dba93db0d85b65dba93bafd15559d1a53cb6d85a68d8ab3cafda5a67b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b51010101010101010101010101010101010101010101010101010101010101010",
                                 HexStr.ToHexStr(yPlane));
                    Assert.Equal("817e7f7e7f817d7e807e7e7e7f7f83a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a184848484848484848484848484848484",
                                 HexStr.ToHexStr(uPlane));
                    Assert.Equal("7f7f807e7f807f7e7f807e7f817e6063636363636363636363636363636363637e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e",
                                 HexStr.ToHexStr(vPlane));
                    break;

                case 5:
                    Assert.Equal("b86165dba93db0d85b65dba93bafd15559d1a53cb6d85a68d8ab3cafda5a67b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b51010101010101010101010101010101010101010101010101010101010101010",
                                 HexStr.ToHexStr(yPlane));
                    Assert.Equal("817e7f7e7f807e7e807e7e7e7f7f83a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a184848484848484848484848484848484",
                                 HexStr.ToHexStr(uPlane));
                    Assert.Equal("7f7f807e7f807f7e7f807e7f817e6063636363636363636363636363636363637e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e",
                                 HexStr.ToHexStr(vPlane));
                    break;

                default:
                    break;
                }

                count++;
            }
        }