private void SetupTranscoder()
        {
            transcoder = new PrimoSoftware.AVBlocks.Transcoder();
            transcoder.AllowDemoMode = true;

            captureFramerate = Convert.ToInt32(cCaptureFramerate.Text);

            /*
             * Important!
             * Make sure the calculated viewport size is in pixels because it's used as video frame size.
             * The rendered viewport size includes the margins.
             */
            var margin      = viewport.Margin;
            var frameWidth  = (int)(viewport.ActualWidth * dpiScaleX + margin.Left + margin.Right);
            var frameHeight = (int)(viewport.ActualHeight * dpiScaleY + margin.Top + margin.Bottom);

            /*
             * Round down to even frame size.
             * This is required by the AVBlocks Transcoder
             */
            captureFrameWidth  = frameWidth / 2 * 2;
            captureFrameHeight = frameHeight / 2 * 2;


            var preset = cOutputPreset.SelectedItem as PresetDescriptor;
            var output = MediaSocket.FromPreset(preset.Name);

            output.File = cOutputFile.Text;
            AdjustVideoOutput(output, captureFramerate);
            transcoder.Outputs.Add(output);

            var input = new MediaSocket()
            {
                StreamType = StreamType.UncompressedVideo
            };

            input.Pins.Add(new MediaPin()
            {
                StreamInfo = new VideoStreamInfo()
                {
                    StreamType  = StreamType.UncompressedVideo,
                    FrameWidth  = captureFrameWidth,
                    FrameHeight = captureFrameHeight,
                    ColorFormat = ColorFormat.BGR32,
                    ScanType    = ScanType.Progressive,
                }
            });

            transcoder.Inputs.Add(input);

            File.Delete(output.File);
        }
        public int SampleCB(double SampleTime, IMediaSample pSample)
        {
            if (!bProcess)
            {
                lastSampleTime = SampleTime;
                return(WinAPI.E_FAIL);
            }

            // internal stats
            ++sampleIndex;
            long tStart, tEnd;

            pSample.GetMediaTime(out tStart, out tEnd);
            Debug.Assert(tStart < tEnd);
            Debug.Assert(tStart > lastMediaTime);
            sampleProcessed += tEnd - tStart;
            sampleDropped   += tStart - lastMediaTime - 1;
            lastMediaTime    = tEnd - 1;

            int    dataLen = pSample.GetActualDataLength();
            IntPtr bufPtr;
            int    hr = pSample.GetPointer(out bufPtr);

            Debug.Assert(0 == hr);

            // BEGIN TRACE

            int bufSize = pSample.GetSize();

            long timeStart, timeEnd;

            pSample.GetTime(out timeStart, out timeEnd);

            string msg = string.Format(
                "SampleCB ({0}) {1}, sampleTime:{2} datalen:{3} bufsize:{4} mediaTime:{5}-{6} time:{7}-{8}",
                name, sampleIndex, SampleTime, dataLen, bufSize, tStart, tEnd, timeStart, timeEnd);

            Trace.WriteLine(msg);

            if (tStart - lastMediaTime - 1 > 0)
            {
                msg = string.Format("!!! Frame drop: {0}", tStart - lastMediaTime - 1 > 0);
                Trace.WriteLine(msg);
            }

            //END TRACE

            byte[] buf = new byte[dataLen];
            Marshal.Copy(bufPtr, buf, 0, dataLen);

            if (file != null)
            {
                file.Write(buf, 0, dataLen);
            }

            //DBG - simulate encoding error
            //if (sampleIndex > 100)
            //    goto STOP_CAPTURE;

            if (mediaState != null && mediaState.mpeg2Enc != null)
            {
                PrimoSoftware.AVBlocks.Transcoder enc = mediaState.mpeg2Enc;
                MediaSample inputSample = new MediaSample();
                inputSample.Buffer    = new MediaBuffer(buf);
                inputSample.StartTime = Math.Max(SampleTime, 0);
                //TODO: end time

                try
                {
                    bool pushed = false;

                    // transcoder.Push() is not threads safe.
                    // lock (enc){ } ensure that only one thread is calling transcoder.Push()
                    lock (enc)
                    {
                        pushed = enc.Push(StreamNumber, inputSample);
                    }

                    if (pushed)
                    {
                        return(0);
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Trace.WriteLine(ex.ToString());
                }

                Trace.WriteLine("PushSample FAILED");
            }

            //STOP_CAPTURE:

            Trace.WriteLine("SampleCB: Before Post STOP_CAPTURE");
            WinAPI.PostMessage(MainWindow, Util.WM_STOP_CAPTURE, new IntPtr(streamNumber), IntPtr.Zero);
            Trace.WriteLine("SampleCB: After Post STOP_CAPTURE");
            bProcess = false;
            return(WinAPI.E_FAIL);
        } // end of SampleCB