示例#1
0
        unsafe static void Main(string[] args)
        {
            ConfirmQuickSyncReadiness.HaltIfNotReady();

            Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
            // keep ascending directories until 'media' folder is found
            for (int i = 0; i < 10 && !Directory.Exists("Media"); i++)
            {
                Directory.SetCurrentDirectory("..");
            }
            Directory.SetCurrentDirectory("Media");


            CodecId codecId = CodecId.MFX_CODEC_JPEG;
            FourCC  fourcc  = FourCC.UYVY;  // supported: RGB4, YUY2 NV12 [UYVY through tricks! see below]
            mfxIMPL impl    = mfxIMPL.MFX_IMPL_AUTO;


            int    width, height;
            string inFilename;

            //inFilename = "BigBuckBunny_320x180." + fourcc + ".yuv"; width = 320; height = 180;
            inFilename = "BigBuckBunny_1920x1080." + fourcc + ".yuv"; width = 1920; height = 1080;
            string outFilename = Path.ChangeExtension(inFilename, "enc.jpeg");


            Console.WriteLine("Working directory: {0}", Environment.CurrentDirectory);
            Console.WriteLine("Input filename: {0}", inFilename);
            Console.WriteLine("Input width: {0}  Input height: {1}", width, height);


            if (!File.Exists(inFilename))
            {
                Console.WriteLine("Input file not found.");
                Console.WriteLine("Please let Decoder1 run to completion to create input file");
                Console.WriteLine("Press any key to exit.");
                Console.ReadKey();
                return;
            }


            Stream         infs, outfs;
            BenchmarkTimer bt = null;


#if !ENABLE_BENCHMARK
            infs  = File.Open(inFilename, FileMode.Open);
            outfs = File.Open(outFilename, FileMode.Create);
#else       // delete this code for most simple example
            // * Benchmark Mode *
            // this block does a couple things:
            //   1. causes the file to be pre-read into memory so we are not timing disk reads.
            //   2. replaces the output stream with a NullStream so nothing gets written to disk.
            //   3. Starts the timer for benchmarking
            // this pre-reads file into memory for benchmarking
            long maximumMemoryToAllocate = (long)4L * 1024 * 1024 * 1024;
            Console.WriteLine("Pre-reading input");
            infs = new PreReadLargeMemoryStream(File.Open(inFilename, FileMode.Open), maximumMemoryToAllocate);
            Console.WriteLine("Input read");

            outfs = new NullStream();
            bt    = new BenchmarkTimer();
            bt.Start();

            int minimumFrames = 4000;
#endif

            Console.WriteLine("Output filename: {0}",
                              Path.GetFileName((outfs as FileStream)?.Name ?? "NO OUTPUT"));
            Console.WriteLine();

            // The encoder cannot encode UYVY, but if you are the only decoder of the JPEG
            // files, you can encode UYVY as YUY2 and everything is good.
            if (fourcc == FourCC.UYVY)
            {
                fourcc = FourCC.YUY2;
            }


            mfxVideoParam mfxEncParams = new mfxVideoParam();
            mfxEncParams.mfx.CodecId     = codecId;
            mfxEncParams.mfx.TargetUsage = TargetUsage.MFX_TARGETUSAGE_BALANCED;
            //mfxEncParams.mfx.TargetKbps = 2000;
            //mfxEncParams.mfx.RateControlMethod = RateControlMethod.MFX_RATECONTROL_VBR;
            mfxEncParams.mfx.Quality                 = 90;
            mfxEncParams.mfx.Interleaved             = 1;
            mfxEncParams.mfx.FrameInfo.FrameRateExtN = 30;
            mfxEncParams.mfx.FrameInfo.FrameRateExtD = 1;
            mfxEncParams.mfx.FrameInfo.FourCC        = fourcc;


            switch (fourcc)
            {
            case FourCC.NV12:
            case FourCC.YV12:
                mfxEncParams.mfx.FrameInfo.ChromaFormat = ChromaFormat.MFX_CHROMAFORMAT_YUV420;
                break;

            case FourCC.YUY2:
                mfxEncParams.mfx.FrameInfo.ChromaFormat = ChromaFormat.MFX_CHROMAFORMAT_YUV422V;     // fatal on SKYLAKE!
                mfxEncParams.mfx.FrameInfo.ChromaFormat = ChromaFormat.MFX_CHROMAFORMAT_YUV422;
                break;

            case FourCC.RGB4:
                mfxEncParams.mfx.FrameInfo.ChromaFormat = ChromaFormat.MFX_CHROMAFORMAT_YUV444;
                break;

            default:
                Trace.Assert(false);
                break;
            }


            mfxEncParams.mfx.FrameInfo.PicStruct = PicStruct.MFX_PICSTRUCT_PROGRESSIVE;
            mfxEncParams.mfx.FrameInfo.CropX     = 0;
            mfxEncParams.mfx.FrameInfo.CropY     = 0;
            mfxEncParams.mfx.FrameInfo.CropW     = (ushort)width;
            mfxEncParams.mfx.FrameInfo.CropH     = (ushort)height;
            // Width must be a multiple of 16
            // Height must be a multiple of 16 in case of frame picture and a multiple of 32 in case of field picture
            mfxEncParams.mfx.FrameInfo.Width  = QuickSyncStatic.ALIGN16(width);
            mfxEncParams.mfx.FrameInfo.Height = QuickSyncStatic.AlignHeightTo32or16(height, mfxEncParams.mfx.FrameInfo.PicStruct);
            mfxEncParams.IOPattern            = IOPattern.MFX_IOPATTERN_IN_SYSTEM_MEMORY; // must be 'in system memory'
            mfxEncParams.AsyncDepth           = 4;                                        // Pipeline depth. Best at 4


            mfxEncParams.mfx.FrameInfo.Width  = QuickSyncStatic.ALIGN32(width);
            mfxEncParams.mfx.FrameInfo.Height = QuickSyncStatic.ALIGN32(height);


            BitStreamChunk bsc = new BitStreamChunk(); //where we receive compressed frame data

            ILowLevelEncoder encoder = new LowLevelEncoder(mfxEncParams, impl);
            //ILowLevelEncoder encoder = new LowLevelEncoder(mfxEncParams, impl);


            string impltext = QuickSyncStatic.ImplementationString(encoder.session);
            Console.WriteLine("Implementation = {0}", impltext);


            // not needed for YUY2 encoding
            //var formatConverter = new NV12FromXXXXConverter(fileFourcc, width, height);


            int inputFrameLength = width * height * VideoUtility.GetBitsPerPixel(fourcc) / 8;

            byte[] uncompressed = new byte[inputFrameLength];

            int count = 0;

            // we do not call encoder.LockFrame() and encoder.UnlockFrame() as this example is
            // for system memory.


            while (infs.Read(uncompressed, 0, inputFrameLength) == inputFrameLength)
            {
                int ix = encoder.GetFreeFrameIndex();  //this call relys locks in authoritative array of surf

                //formatConverter.ConvertToNV12FrameSurface(ref encoder.Frames[ix], uncompressed, 0);
                mfxFrameSurface1 *f = (mfxFrameSurface1 *)encoder.Frames[ix];


                switch (fourcc)
                {
                case FourCC.NV12:
                    Trace.Assert(f->Data.Pitch == width * 1);

                    fixed(byte *aa = &uncompressed[0])
                    FastMemcpyMemmove.memcpy(f->Data.Y, (IntPtr)aa, height * width);

                    fixed(byte *aa = &uncompressed[height * width])
                    FastMemcpyMemmove.memcpy(f->Data.UV, (IntPtr)aa, height / 2 * width);

                    break;

                case FourCC.YUY2:

                    Trace.Assert(f->Data.Pitch == width * 2);

                    fixed(byte *aa = &uncompressed[0])
                    FastMemcpyMemmove.memcpy(f->Data.Y, (IntPtr)aa, height * width * 2);

                    break;

                default:
                    Trace.Assert(false);
                    break;
                }

                encoder.EncodeFrame(ix, ref bsc);

                if (bsc.bytesAvailable > 0)
                {
                    outfs.Write(bsc.bitstream, 0, bsc.bytesAvailable);

                    if (++count % 100 == 0)
                    {
                        Console.Write("Frame {0}\r", count);
                    }
                }

#if ENABLE_BENCHMARK     // delete this code for most simple example
                if (infs.Position + inputFrameLength - 1 >= infs.Length)
                {
                    infs.Position = 0;
                }
                if (count >= minimumFrames)
                {
                    break;
                }
#endif
            }

            while (encoder.Flush(ref bsc))
            {
                if (bsc.bytesAvailable > 0)
                {
                    outfs.Write(bsc.bitstream, 0, bsc.bytesAvailable);

                    if (++count % 100 == 0)
                    {
                        Console.Write("Frame {0}\r", count);
                    }
                }
            }

            if (bt != null)
            {
                bt.StopAndReport(count, infs.Position, outfs.Position);
            }

            infs.Close();
            outfs.Close();

            encoder.Dispose();

            Console.WriteLine("Encoded {0} frames", count);

            // make sure program always waits for user, except F5-Release run
            if (Debugger.IsAttached ||
                Environment.GetEnvironmentVariable("VisualStudioVersion") == null)
            {
                Console.WriteLine("done - press a key to exit");
                Console.ReadKey();
            }
        }
示例#2
0
        /// <summary>
        /// <para>Convert a raw frame to NV12.</para>
        /// <para>Used to convert fourcc formats to NV12.</para>
        ///
        /// </summary>
        /// <param name="srcFourcc">One of NV12 RGB3 RGB4 UYVY YUY2 YV12 BGR3 BGR4 P411 P422 I420_IYUV</param>
        /// <param name="nv12pitch">output pitch in bytes</param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="inFrameptr"></param>
        /// <param name="nv12">Y output plane destination</param>
        /// <param name="nv12uv">UV output plane destination</param>
        public unsafe void ConvertToNV12FrameSurface(FourCC srcFourcc, int nv12pitch, int width, int height, byte *inFrameptr, byte *nv12, byte *nv12uv)
        {
            NativeResizeConvertStatus sts = NativeResizeConvertStatus.NativeStatusNoErr;

            roisizea.height = height;
            roisizea.width  = width;
            switch (srcFourcc)
            {
            //case FourCC.A2RGB10:
            //    break;
            //case FourCC.ARGB16:
            //    break;

            case FourCC.NV12:
                //memmove(nv12, inFrameptr, height * width);
                //memmove(nv12uv, inFrameptr + height * width, height * width / 2);

                for (int j = 0; j < height; j++)
                {
                    // Marshal.Copy(uncompressed, i * framelen + j * w, e.Frames[ix].Data.Y + e.Frames[ix].Data.Pitch * j, w);
                    FastMemcpyMemmove.memcpy(nv12 + nv12pitch * j, inFrameptr + width * j, width);
                }
                for (int j = 0; j < height / 2; j++)
                {
                    FastMemcpyMemmove.memcpy(nv12uv + nv12pitch * j, inFrameptr + width * height + width * j, width);
                }
                //  Marshal.Copy(uncompressed, i * framelen + j * w + h * w, e.Frames[ix].Data.UV + e.Frames[ix].Data.Pitch * j, w);


                break;
            //case FourCC.NV16:
            //    break;
            //case FourCC.P010:
            //    break;
            //case FourCC.P210:
            //    break;
            //case FourCC.P8:
            //    break;
            //case FourCC.P8_TEXTURE:
            //    break;
            //case FourCC.R16:
            //    break;



            case FourCC.BGR3:
                sts = NV12Convert.BGR3ToNV12(inFrameptr, width * 3, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);
                break;

            case FourCC.BGR4:      // this was not supported originally due to lack of support in intel IPP

                sts = NV12Convert.BGR4ToNV12(inFrameptr, width * 4, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);
                break;

            case FourCC.IYUV:
                pointers[0] = inFrameptr;
                pointers[1] = inFrameptr + height * width;
                pointers[2] = inFrameptr + height * width + height * width / 2 / 2;
                intarr[0]   = width;
                intarr[1]   = width / 2;
                intarr[2]   = width / 2;
                fixed(byte **p1 = pointers)
                fixed(int *p2 = intarr)
                {
                    sts = NV12Convert.IYUVToNV12(p1, p2, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);
                }
                break;

            case FourCC.P411:

                pointers[0] = inFrameptr;
                pointers[1] = inFrameptr + height * width;
                pointers[2] = inFrameptr + height * width + height * width / 4;
                intarr[0]   = width;
                intarr[1]   = width / 4;
                intarr[2]   = width / 4;
                fixed(byte **p1 = pointers)
                fixed(int *p2 = intarr)
                {
                    sts = NV12Convert.P411ToNV12(p1, p2, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);
                }
                break;

            case FourCC.P422:
                pointers[0] = inFrameptr;
                pointers[1] = inFrameptr + height * width;
                pointers[2] = inFrameptr + height * width + height * width / 2;
                intarr[0]   = width;
                intarr[1]   = width / 2;
                intarr[2]   = width / 2;
                fixed(byte **p1 = pointers)
                fixed(int *p2 = intarr)
                {
                    sts = NV12Convert.P422ToNV12(p1, p2, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);
                }
                break;

            case FourCC.RGB3:
                sts = NV12Convert.RGB3ToNV12(inFrameptr, width * 3, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);
                break;

            case FourCC.RGB4:
                sts = NV12Convert.RGB4ToNV12(inFrameptr, width * 4, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);
                break;


            case FourCC.YUY2:
                sts = NV12Convert.YUY2ToNV12(inFrameptr, width * 2, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);

                break;

            case FourCC.YV12:
                //YVU
                // YCbCr == YUV
                pointers[0] = inFrameptr;
                pointers[1] = inFrameptr + height * width;
                pointers[2] = inFrameptr + height * width + height * width / 2 / 2;
                intarr[0]   = width;
                intarr[1]   = width / 2;
                intarr[2]   = width / 2;

                fixed(byte **p1 = pointers)
                fixed(int *p2 = intarr)
                sts           = NV12Convert.YV12ToNV12(p1, p2, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);

                break;

            case FourCC.UYVY:

                // sts = NV12Convert.ippiCbYCr422ToYCbCr420_8u_C2P2R(inFrameptr, width * 2, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);
                sts = NV12Convert.UYVYToNV12(inFrameptr, width * 2, nv12, nv12pitch, nv12uv, nv12pitch, roisizea);
                break;

            default:
                break;
            }
            if (sts != NativeResizeConvertStatus.NativeStatusNoErr)
            {
                throw new Exception("FourCC convert error:" + sts.ToString());
            }
        }
示例#3
0
        unsafe static void Main(string[] args)
        {
            ConfirmQuickSyncReadiness.HaltIfNotReady();

            Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
            // keep ascending directories until 'media' folder is found
            for (int i = 0; i < 10 && !Directory.Exists("Media"); i++)
            {
                Directory.SetCurrentDirectory("..");
            }
            Directory.SetCurrentDirectory("Media");


            CodecId codecId = CodecId.MFX_CODEC_JPEG;
            FourCC  fourcc  = FourCC.UYVY;  // supported: RGB4, YUY2 NV12 [UYVY through tricks! see below]
            mfxIMPL impl    = mfxIMPL.MFX_IMPL_AUTO;



            string fourccString = fourcc.ToString().Substring(0, 4);
            string inFilename;

            //inFilename = "BigBuckBunny_320x180.UYVY.enc.jpeg";
            inFilename = "BigBuckBunny_1920x1080.UYVY.enc.jpeg";
            //inFilename = "BigBuckBunny_3840x2160.UYVY.enc.jpeg";
            string outFilename = Path.ChangeExtension(inFilename, ".yuv");

            Console.WriteLine("Working directory: {0}", Environment.CurrentDirectory);
            Console.WriteLine("Input filename: {0}", inFilename);
            Console.WriteLine();

            if (!File.Exists(inFilename))
            {
                Console.WriteLine("Input file not found. Press any key to exit.");
                Console.ReadKey();
                return;
            }


            Stream         infs, outfs;
            BenchmarkTimer bt = null;


#if !ENABLE_BENCHMARK
            infs  = File.Open(inFilename, FileMode.Open);
            outfs = File.Open(outFilename, FileMode.Create);
#else       // delete this code for most simple example
            // * Benchmark Mode *
            // this block does a couple things:
            //   1. causes the file to be pre-read into memory so we are not timing disk reads.
            //   2. replaces the output stream with a NullStream so nothing gets written to disk.
            //   3. Starts the timer for benchmarking
            // this pre-reads file into memory for benchmarking
            long maximumMemoryToAllocate = (long)4L * 1024 * 1024 * 1024;
            Console.WriteLine("Pre-reading input");
            infs = new PreReadLargeMemoryStream(File.Open(inFilename, FileMode.Open), maximumMemoryToAllocate);



            Console.WriteLine("Input read");

            outfs = new NullStream();
            bt    = new BenchmarkTimer();
            bt.Start();

            int minimumFrames = 4000;
#endif



            Console.WriteLine("Output filename: {0}",
                              Path.GetFileName((outfs as FileStream)?.Name ?? "NO OUTPUT"));
            Console.WriteLine();

            var outIOPattern = IOPattern.MFX_IOPATTERN_OUT_SYSTEM_MEMORY;


            // The encoder cannot encode UYVY, but if you are the only decoder of the JPEG
            // files, you can encode UYVY as YUY2 and everything is good.
            if (fourcc == FourCC.UYVY)
            {
                fourcc = FourCC.YUY2;
            }

            mfxVideoParam decoderParameters = QuickSyncStatic.ReadFileHeaderInfo(codecId, impl, infs, outIOPattern);
            decoderParameters.mfx.FrameInfo.FourCC = fourcc;

            AssignChromaFormat(fourcc, ref decoderParameters);


            var decoder = new StreamDecoder(infs, decoderParameters, null, impl);

#if ENABLE_BENCHMARK     // delete this code for most simple example
            decoder.benchmarkNeverStopMode = true;
#endif

            string impltext = QuickSyncStatic.ImplementationString(decoder.lowLevelDecoder.session);
            Console.WriteLine("Implementation = {0}", impltext);

            // not needed
            //var formatConverter = new NV12ToXXXXConverter(fourcc, decoder.width, decoder.height);

            int width  = decoderParameters.mfx.FrameInfo.CropW;
            int height = decoderParameters.mfx.FrameInfo.CropH;
            var tmpbuf = new byte[width * height * 2];

            int count = 0;

            foreach (var frame in decoder.GetFrames())
            {
                //var frameBytes = formatConverter.ConvertFromNV12(frame.Data);        // Convert to format requested


                Trace.Assert(frame.Data.Pitch == width * 2);  // yuy2 only

                fixed(byte *aa = &tmpbuf[0])
                FastMemcpyMemmove.memcpy((IntPtr)aa, frame.Data.Y, height * width * 2);

                outfs.Write(tmpbuf, 0, tmpbuf.Length);

                if (++count % 100 == 0)
                {
                    Console.Write("Frame {0}\r", count);
                }

#if ENABLE_BENCHMARK     // delete this code for most simple example
                if (count > minimumFrames)
                {
                    break;
                }
#endif
            }

            if (bt != null)
            {
                bt.StopAndReport(count, infs.Position, outfs.Position);
            }

            infs.Close();
            outfs.Close();

            Console.WriteLine("Decoded {0} frames", count);

            // make sure program always waits for user, except F5-Release run
            if (Debugger.IsAttached ||
                Environment.GetEnvironmentVariable("VisualStudioVersion") == null)
            {
                Console.WriteLine("done - press a key to exit");
                Console.ReadKey();
            }
        }
示例#4
0
        /// <summary>
        /// Convert an NV12 frame to another fourcc format
        /// </summary>
        /// <param name="destFourcc">One of NV12 RGB3 RGB4 UYVY YUY2 YV12 BGR3 P411 P422 I420_IYUV</param>
        /// <param name="Y">Y plane of NV12 input</param>
        /// <param name="UV">UV plane of NV12 input</param>
        /// <param name="outputFramePtr">where output frame goes</param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="outputLen"></param>
        /// <param name="srcPitch">Pitch of the source NV12</param>
        /// <param name="dstPitch">Pitch of the dest frame</param>
        /// <param name="alpha">Only used for formats with sn alpha plane: RGB4, ...</param>
        public unsafe void ConvertFromNV12(FourCC destFourcc, byte *Y, byte *UV, byte *outputFramePtr, int width, int height, int outputLen, int srcPitch = 0, int dstPitch = 0, byte alpha = 255)
        {
            int bitsPerPixel = VideoUtility.GetBitsPerPixel(destFourcc);
            // int dstpitch = bitsPerPixel * width / 8;
            int compactFrameSize = width * height * bitsPerPixel / 8;

            Trace.Assert(outputLen == compactFrameSize);



            //byte* nv12uv = nv12 + width * height;


            roisize.height = height;
            roisize.width  = width;

            NativeResizeConvertStatus sts = NativeResizeConvertStatus.NativeStatusNoErr;



            if (srcPitch == 0)
            {
                srcPitch = width * 1;
            }

            if (dstPitch == 0)
            {
                dstPitch = width * VideoUtility.GetPackedPitchMultiplier(destFourcc);
            }


            switch (destFourcc)
            {
            case FourCC.BGR3:
                sts = NV12Convert.NV12ToBGR3(Y, srcPitch, UV, srcPitch, outputFramePtr, dstPitch, roisize);
                break;

            case FourCC.BGR4:
                sts = NV12Convert.NV12ToBGR4(Y, srcPitch, UV, srcPitch, outputFramePtr, dstPitch, roisize, alpha);
                break;


            case FourCC.RGB4:
                sts = NV12Convert.NV12ToRGB4(Y, srcPitch, UV, srcPitch, outputFramePtr, dstPitch, roisize, alpha);
                break;

            case FourCC.RGB3:
                sts = NV12Convert.NV12ToRGB3(Y, srcPitch, UV, srcPitch, outputFramePtr, dstPitch, roisize);
                break;



            case FourCC.YUY2:
                sts = NV12Convert.NV12ToYUY2(Y, srcPitch, UV, srcPitch, outputFramePtr, dstPitch, roisize);

                break;

            case FourCC.YV12:
                pdst[0] = outputFramePtr;
                // This seems wrong, backwards, maybe a bug in IPP 7.x
                // indicies should be 1,2 not 2,1
                //manual check indicates this is what works correctly 2/22/15
                pdst[2]    = outputFramePtr + height * width;
                pdst[1]    = outputFramePtr + height * width + height * width / 2 / 2;
                dststep[0] = dstPitch;
                dststep[1] = dstPitch / 2;
                dststep[2] = dstPitch / 2;

                fixed(byte **p1 = pdst)
                fixed(int *p2 = dststep)
                sts           = NV12Convert.NV12ToYV12(Y, srcPitch, UV, srcPitch, p1, p2, roisize);

                break;

            case FourCC.UYVY:
                sts = NV12Convert.NV12ToUYVY(Y, srcPitch, UV, srcPitch, outputFramePtr, dstPitch, roisize);
                break;

            case FourCC.I420_IYUV:
                pdst[0]    = outputFramePtr;
                pdst[1]    = outputFramePtr + height * width;
                pdst[2]    = outputFramePtr + height * width + height * width / 2 / 2;
                dststep[0] = dstPitch;
                dststep[1] = dstPitch / 2;
                dststep[2] = dstPitch / 2;

                fixed(byte **p1 = pdst)
                fixed(int *p2 = dststep)
                sts           = NV12Convert.NV12ToYV12(Y, srcPitch, UV, srcPitch, p1, p2, roisize);

                break;

            case FourCC.P411:

                pdst[0]    = outputFramePtr;
                pdst[1]    = outputFramePtr + height * width;
                pdst[2]    = outputFramePtr + height * width + height * width / 4;
                dststep[0] = dstPitch;
                dststep[1] = dstPitch / 4;
                dststep[2] = dstPitch / 4;

                fixed(byte **p1 = pdst)
                fixed(int *p2 = dststep)
                sts           = NV12Convert.NV12ToP411(Y, srcPitch, UV, srcPitch, p1, p2, roisize);

                break;

            case FourCC.P422:
                pdst[0]    = outputFramePtr;
                pdst[1]    = outputFramePtr + height * width;
                pdst[2]    = outputFramePtr + height * width + height * width / 2;
                dststep[0] = dstPitch;
                dststep[1] = dstPitch / 2;
                dststep[2] = dstPitch / 2;

                fixed(byte **p1 = pdst)
                fixed(int *p2 = dststep)
                sts           = NV12Convert.NV12ToP422(Y, srcPitch, UV, srcPitch, p1, p2, roisize);

                break;

            case FourCC.NV12:

                // XXX nonono
                // does not work for pitch!=width  !!
                //memmove(outputFramePtr, Y, height * width);
                //memmove(outputFramePtr + height * width, UV, height * width / 2);
                for (int i = 0; i < height; i++)
                {
                    FastMemcpyMemmove.memcpy(outputFramePtr + i * dstPitch, Y + i * srcPitch, width);
                }
                outputFramePtr += height * dstPitch;
                for (int i = 0; i < height / 2; i++)
                {
                    FastMemcpyMemmove.memcpy(outputFramePtr + i * dstPitch, UV + i * srcPitch, width);
                }
                break;

            default:
                throw new Exception("fourcc conversion not supported, contact Lime Video  support for options");
            }

            if (sts != NativeResizeConvertStatus.NativeStatusNoErr)
            {
                throw new Exception("FourCC convert error:" + sts.ToString());
            }
        }