Ejemplo n.º 1
0
        void GetBitstreamIfAny(ref BitStreamChunk bsc)
        {
            mfxStatus sts = 0;

            bsc.bytesAvailable = 0;

            Trace.Assert(pTasks[nFirstSyncTask].syncp.sync_ptr != null);

            // No more free tasks, need to sync
            sts = UnsafeNativeMethods.MFXVideoCORE_SyncOperation(session, pTasks[nFirstSyncTask].syncp, 60000);
            QuickSyncStatic.ThrowOnBadStatus(sts, "syncoper");

            //  sts = WriteBitStreamFrame(&pTasks[nFirstSyncTask].mfxBS, fSink);
            //  MSDK_BREAK_ON_ERROR(g);
            int n = (int)pTasks[nFirstSyncTask].mfxBS.DataLength;

            if (bsc.bitstream == null || bsc.bitstream.Length < n)
            {
                bsc.bitstream = new byte[pTasks[nFirstSyncTask].mfxBS.MaxLength];
            }
            Trace.Assert(pTasks[nFirstSyncTask].mfxBS.DataOffset == 0);
            Marshal.Copy(pTasks[nFirstSyncTask].mfxBS.Data, bsc.bitstream, 0, n);
            bsc.bytesAvailable = n;
            pTasks[nFirstSyncTask].mfxBS.DataLength = 0;
            pTasks[nFirstSyncTask].syncp.sync_ptr   = null;
            nFirstSyncTask = (nFirstSyncTask + 1) % pTasks.Length;
        }
Ejemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="bsc"></param>
        /// <returns>true:all done, false:continue to call me</returns>
        public bool Flush4(ref BitStreamChunk bsc)
        {
            mfxStatus sts;

            bsc.bytesAvailable = 0;
            while (pTasks[nFirstSyncTask].syncp.sync != IntPtr.Zero)
            {
                sts = UnsafeNativeMethods.MFXVideoCORE_SyncOperation(session, pTasks[nFirstSyncTask].syncp, 60000);
                QuickSyncStatic.ThrowOnBadStatus(sts, "syncOper");

                if (bsc.bitstream == null || bsc.bitstream.Length < pTasks[nFirstSyncTask].mfxBS.DataLength)
                {
                    bsc.bitstream = new byte[pTasks[nFirstSyncTask].mfxBS.DataLength];
                }
                Trace.Assert(pTasks[nFirstSyncTask].mfxBS.DataOffset == 0);
                Marshal.Copy(pTasks[nFirstSyncTask].mfxBS.Data, bsc.bitstream, 0, (int)pTasks[nFirstSyncTask].mfxBS.DataLength);

                bsc.bytesAvailable = (int)pTasks[nFirstSyncTask].mfxBS.DataLength;

                // WriteBitStreamFrame(pTasks[nFirstSyncTask].mfxBS, outbs);
                //MSDK_BREAK_ON_ERROR(sts);
                pTasks[nFirstSyncTask].syncp.sync       = IntPtr.Zero;
                pTasks[nFirstSyncTask].mfxBS.DataLength = 0;
                pTasks[nFirstSyncTask].mfxBS.DataOffset = 0;
                nFirstSyncTask = (nFirstSyncTask + 1) % taskPoolSize;
                return(true);
            }
            return(false);
        }
Ejemplo n.º 3
0
        //object ILowLevelEncoder.deviceSetup
        //{
        //    get
        //    {
        //        throw new NotImplementedException();
        //    }
        //}

        /// <summary>After passing all frames to be encoded you must call this to flush out bitstream in the engine.</summary>
        /// <param name="bitstreamChunk">Frames returned</param>
        /// <returns>true indicates you must keep calling me</returns>
        public bool Flush(ref BitStreamChunk bitstreamChunk)
        {
            bitstreamChunk.bytesAvailable = 0;
            if (flush1state)
            {
                flush1state = Flush1(ref bitstreamChunk);
                return(true);
            }
            return(Flush2(ref bitstreamChunk));
        }
Ejemplo n.º 4
0
        public unsafe void EncodeFrame(int frameIndex, ref BitStreamChunk bitstreamChunk)
        {
            bitstreamChunk.bytesAvailable = 0;
            var a   = frameIntPtrs[frameIndex];
            var sts = NativeLLEncoderUnsafeNativeMethods.NativeEncoder_EncodeFrame(h, (mfxFrameSurface1 *)a);

            QuickSyncStatic.ThrowOnBadStatus(sts, nameof(NativeLLEncoderUnsafeNativeMethods.NativeEncoder_EncodeFrame));

            CopyOutBitstream(ref bitstreamChunk);
        }
Ejemplo n.º 5
0
 bool Flush2(ref BitStreamChunk bsc)
 {
     if (pTasks[nFirstSyncTask].syncp.sync_ptr != null)
     {
         GetBitstreamIfAny(ref bsc);
         return(true);
     }
     else
     {
         return(false);
     }
 }
Ejemplo n.º 6
0
        bool Flush1(ref BitStreamChunk bsc)
        {
            bsc.bytesAvailable = 0;
            if (GetBitstreamIfFull(ref bsc))
            {
                return(true);
            }

            mfxStatus sts      = 0;
            int       nTaskIdx = GetFreeTaskIndex(pTasks); // Find free task

            Trace.Assert((int)mfxStatus.MFX_ERR_NOT_FOUND != nTaskIdx);


            for (;;)
            {
                // Encode a frame asychronously (returns immediately)

                fixed(mfxBitstream *b = &pTasks[nTaskIdx].mfxBS)
                fixed(mfxSyncPoint * c = &pTasks[nTaskIdx].syncp)
                sts = UnsafeNativeMethods.MFXVideoENCODE_EncodeFrameAsync(session, null, null, b, c);

                if (mfxStatus.MFX_ERR_NONE < sts && !(pTasks[nTaskIdx].syncp.sync_ptr != null))
                {    // Repeat the call if warning and no output
                    if (mfxStatus.MFX_WRN_DEVICE_BUSY == sts)
                    {
                        Thread.Sleep(1);  // Wait if device is busy, then repeat the same call
                    }
                }
                else if (mfxStatus.MFX_ERR_NONE < sts && pTasks[nTaskIdx].syncp.sync_ptr != null)
                {
                    sts = mfxStatus.MFX_ERR_NONE;     // Ignore warnings if output is available
                    break;
                }
                else
                {
                    break;
                }
            }



            // MFX_ERR_MORE_DATA means that the input file has ended, need to go to buffering loop, exit in case of other errors
            //MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA);
            if (sts == mfxStatus.MFX_ERR_MORE_DATA)
            {
                return(false);  // no more to flush here
            }
            sts = mfxStatus.MFX_ERR_NONE;
            //MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
            QuickSyncStatic.ThrowOnBadStatus(sts, "flush1.encodeFrameAsync");
            return(true);  // yes, call me again, more to flush
        }
Ejemplo n.º 7
0
        private void CopyOutBitstream(ref BitStreamChunk bitstreamChunk)
        {
            if (bitstreamChunk.bitstream == null)
            {
                bitstreamChunk.bitstream = new byte[shared->maxbuflen];
            }

            if (shared->buflen > 0)
            {
                Marshal.Copy((IntPtr)shared->buf, bitstreamChunk.bitstream, 0, shared->buflen);
            }
            bitstreamChunk.bytesAvailable = shared->buflen;
        }
Ejemplo n.º 8
0
        bool GetBitstreamIfFull(ref BitStreamChunk bsc)
        {
            bsc.bytesAvailable = 0;

            int nTaskIdx = GetFreeTaskIndex(pTasks);      // Find free task

            if ((int)mfxStatus.MFX_ERR_NOT_FOUND == nTaskIdx)
            {
                GetBitstreamIfAny(ref bsc);
                return(true);
            }

            return(false);
        }
Ejemplo n.º 9
0
        bool Flush2(ref BitStreamChunk bitstreamChunk)
        {
            bitstreamChunk.bytesAvailable = 0;
            var sts = NativeLLEncoderUnsafeNativeMethods.NativeEncoder_Flush2(h);

            if (sts == mfxStatus.MFX_ERR_MORE_DATA)
            {
                return(false);
            }
            QuickSyncStatic.ThrowOnBadStatus(sts, nameof(NativeLLEncoderUnsafeNativeMethods.NativeEncoder_Flush2));

            CopyOutBitstream(ref bitstreamChunk);
            return(true);
        }
Ejemplo n.º 10
0
        /// <summary>Encodes a frame.</summary>
        /// <param name="frameIndex">Index of the frame to encode.</param>
        /// <param name="bitStreamChunk">Output frames bitstream data, if available</param>
        public void EncodeFrame(int frameIndex, ref BitStreamChunk bitStreamChunk)
        {
            mfxStatus sts = 0;

            bitStreamChunk.bytesAvailable = 0;

            GetBitstreamIfFull(ref bitStreamChunk);

            // int nEncSurfIdx = 0;
            int nTaskIdx = GetFreeTaskIndex(pTasks);      // Find free task

            Trace.Assert((int)mfxStatus.MFX_ERR_NOT_FOUND != nTaskIdx);

            //int nsource = 0;

            //var buf = new byte[pTasks[0].mfxBS.MaxLength];

            //
            // Stage 1: Main encoding loop
            //
            //if (mfxStatus.MFX_ERR_NONE <= sts || mfxStatus.MFX_ERR_MORE_DATA == sts)
            //{


            // }
            // else
            // {
            //nEncSurfIdx = GetFreeSurfaceIndex(pmfxSurfaces);   // Find free frame surface
            //MSDK_CHECK_ERROR(MFX_ERR_NOT_FOUND, nEncSurfIdx, MFX_ERR_MEMORY_ALLOC);
            //Trace.Assert(nEncSurfIdx != (int)mfxStatus.MFX_ERR_NOT_FOUND);

            // Surface locking required when read/write D3D surfaces
            //sts = mfxAllocator.Lock(mfxAllocator.pthis, pmfxSurfaces[nEncSurfIdx]->Data.MemId, &(pmfxSurfaces[nEncSurfIdx]->Data));
            //MSDK_BREAK_ON_ERROR(sts);

            // sts = LoadRawFrame(pmfxSurfaces[nEncSurfIdx], fSource);
            // MSDK_BREAK_ON_ERROR(sts);

            // from the prototype, we just copy the frame data from a byte array,
            // but in this class we are passed a prepared frame.
            //int pfs = 320 * 180 * 3 / 2;
            //if (nsource * pfs >= yuv.Length)
            //    break;
            //int stride = pmfxSurfaces[nEncSurfIdx].Data.Pitch;
            //for (int i = 0; i < h; i++)
            //    Marshal.Copy(yuv, nsource * pfs + i * w, pmfxSurfaces[nEncSurfIdx].Data.Y + stride * i, w);
            //for (int i = 0; i < h / 2; i++)
            //    Marshal.Copy(yuv, nsource * pfs + i * w + h * w, pmfxSurfaces[nEncSurfIdx].Data.UV + stride * i, w);



            //sts = mfxAllocator.Unlock(mfxAllocator.pthis, pmfxSurfaces[nEncSurfIdx]->Data.MemId, &(pmfxSurfaces[nEncSurfIdx]->Data));
            //MSDK_BREAK_ON_ERROR(sts);


            // Frames[nEncSurfIdx] = frame;
            for (;;)
            {
                // Encode a frame asychronously (returns immediately)
                fixed(mfxFrameSurface1 *a = &Frames[frameIndex])
                fixed(mfxBitstream * b = &pTasks[nTaskIdx].mfxBS)
                fixed(mfxSyncPoint * c = &pTasks[nTaskIdx].syncp)
                sts = UnsafeNativeMethods.MFXVideoENCODE_EncodeFrameAsync(session, null, a, b, c);

                if (mfxStatus.MFX_ERR_NONE < sts && !(pTasks[nTaskIdx].syncp.sync_ptr != null))
                {    // Repeat the call if warning and no output
                    if (mfxStatus.MFX_WRN_DEVICE_BUSY == sts)
                    {
                        Thread.Sleep(1);  // Wait if device is busy, then repeat the same call
                    }
                }
                else if (mfxStatus.MFX_ERR_NONE < sts && pTasks[nTaskIdx].syncp.sync_ptr != null)
                {
                    sts = mfxStatus.MFX_ERR_NONE;     // Ignore warnings if output is available
                    break;
                }
                else if (mfxStatus.MFX_ERR_NOT_ENOUGH_BUFFER == sts)
                {
                    Trace.Assert(false);
                    // Allocate more bitstream buffer memory here if needed...
                    break;
                }
                else
                {
                    break;
                }
            }

            // }

            // MFX_ERR_MORE_DATA means that the input file has ended, need to go to buffering loop, exit in case of other errors
            //MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA);
            if (sts == mfxStatus.MFX_ERR_MORE_DATA)
            {
                sts = mfxStatus.MFX_ERR_NONE;
            }
            //MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
            QuickSyncStatic.ThrowOnBadStatus(sts, "encodeFrameAsync");

            return;
        }
Ejemplo n.º 11
0
        /// <summary>Get frames during 2nd stage of flushing</summary>
        /// <param name="bitStreamChunk">A single frame</param>
        /// <returns>true if you should continue to call this method, false if you must go to the next phase.</returns>
        public bool Flush3(ref BitStreamChunk bitStreamChunk)
        {
            bitStreamChunk.bytesAvailable = 0;

            ////////

            mfxStatus sts = mfxStatus.MFX_ERR_NONE;

            //
            // Stage 4: Retrieve the buffered encoded frames
            //
            if (mfxStatus.MFX_ERR_NONE <= sts)
            {
                int nTaskIdx = GetFreeTaskIndex(pTasks, taskPoolSize);      // Find free task
                if ((int)mfxStatus.MFX_ERR_NOT_FOUND == nTaskIdx)
                {
                    // No more free tasks, need to sync
                    sts = UnsafeNativeMethods.MFXVideoCORE_SyncOperation(session, pTasks[nFirstSyncTask].syncp, 60000);
                    QuickSyncStatic.ThrowOnBadStatus(sts, "syncOper");


                    if (bitStreamChunk.bitstream == null || bitStreamChunk.bitstream.Length < pTasks[nFirstSyncTask].mfxBS.DataLength)
                    {
                        bitStreamChunk.bitstream = new byte[pTasks[nFirstSyncTask].mfxBS.DataLength];
                    }
                    Trace.Assert(pTasks[nFirstSyncTask].mfxBS.DataOffset == 0);
                    Marshal.Copy(pTasks[nFirstSyncTask].mfxBS.Data, bitStreamChunk.bitstream, 0, (int)pTasks[nFirstSyncTask].mfxBS.DataLength);

                    bitStreamChunk.bytesAvailable = (int)pTasks[nFirstSyncTask].mfxBS.DataLength;

                    // WriteBitStreamFrame(pTasks[nFirstSyncTask].mfxBS, outbs);
                    //MSDK_BREAK_ON_ERROR(sts);
                    pTasks[nFirstSyncTask].syncp.sync       = IntPtr.Zero;
                    pTasks[nFirstSyncTask].mfxBS.DataLength = 0;
                    pTasks[nFirstSyncTask].mfxBS.DataOffset = 0;
                    nFirstSyncTask = (nFirstSyncTask + 1) % taskPoolSize;

                    return(true);
                }
                else
                {
                    for (;;)
                    {
                        // Encode a frame asychronously (returns immediately)
                        //sts = mfxENC.EncodeFrameAsync(NULL, pSurfaces2[nIndex2], &pTasks[nTaskIdx].mfxBS, &pTasks[nTaskIdx].syncp);
                        sts = UnsafeNativeMethods.MFXVideoENCODE_EncodeFrameAsync(session, (mfxEncodeCtrl *)0, null, &pTasks[nTaskIdx].mfxBS, &pTasks[nTaskIdx].syncp);

                        if (mfxStatus.MFX_ERR_NONE < sts && pTasks[nTaskIdx].syncp.sync == IntPtr.Zero)
                        {    // repeat the call if warning and no output
                            if (mfxStatus.MFX_WRN_DEVICE_BUSY == sts)
                            {
                                Thread.Sleep(1);  // wait if device is busy
                            }
                        }
                        else if (mfxStatus.MFX_ERR_NONE < sts && pTasks[nTaskIdx].syncp.sync != IntPtr.Zero)
                        {
                            sts = mfxStatus.MFX_ERR_NONE;     // ignore warnings if output is available
                            break;
                        }
                        else if (mfxStatus.MFX_ERR_NOT_ENOUGH_BUFFER == sts)
                        {
                            // Allocate more bitstream buffer memory here if needed...
                            break;
                        }
                        else
                        {
                            if (sts != mfxStatus.MFX_ERR_MORE_DATA && sts != mfxStatus.MFX_ERR_MORE_SURFACE)
                            {
                                QuickSyncStatic.ThrowOnBadStatus(sts, "encodeAsync");
                            }
                            break;
                        }
                    }
                }
            }


            if (mfxStatus.MFX_ERR_MORE_DATA == sts)
            {
                return(false);
            }

            QuickSyncStatic.ThrowOnBadStatus(sts, "enc error");

            return(true);
        }
Ejemplo n.º 12
0
        /// <summary>Get frames during 2nd stage of flushing</summary>
        /// <param name="bitStreamChunk">A single frame</param>
        /// <returns>true if you should continue to call this method, false if you must go to the next stage.</returns>
        public bool Flush2(ref BitStreamChunk bitStreamChunk)
        {
            mfxSyncPoint      syncpV;
            mfxFrameSurface1 *pmfxOutSurface = (mfxFrameSurface1 *)0;


            int nIndex2 = 0;


            bitStreamChunk.bytesAvailable = 0;

            ////////

            mfxStatus sts = mfxStatus.MFX_ERR_NONE;

            //
            // Stage 3: Retrieve buffered frames from VPP
            //
            if (mfxStatus.MFX_ERR_NONE <= sts || mfxStatus.MFX_ERR_MORE_DATA == sts || mfxStatus.MFX_ERR_MORE_SURFACE == sts)
            {
                int nTaskIdx = GetFreeTaskIndex(pTasks, taskPoolSize);      // Find free task
                if ((int)mfxStatus.MFX_ERR_NOT_FOUND == nTaskIdx)
                {
                    // No more free tasks, need to sync
                    sts = UnsafeNativeMethods.MFXVideoCORE_SyncOperation(session, pTasks[nFirstSyncTask].syncp, 60000);
                    QuickSyncStatic.ThrowOnBadStatus(sts, "syncOper");


                    if (bitStreamChunk.bitstream == null || bitStreamChunk.bitstream.Length < pTasks[nFirstSyncTask].mfxBS.DataLength)
                    {
                        bitStreamChunk.bitstream = new byte[pTasks[nFirstSyncTask].mfxBS.DataLength];
                    }
                    Trace.Assert(pTasks[nFirstSyncTask].mfxBS.DataOffset == 0);
                    Marshal.Copy(pTasks[nFirstSyncTask].mfxBS.Data, bitStreamChunk.bitstream, 0, (int)pTasks[nFirstSyncTask].mfxBS.DataLength);

                    bitStreamChunk.bytesAvailable = (int)pTasks[nFirstSyncTask].mfxBS.DataLength;

                    // WriteBitStreamFrame(pTasks[nFirstSyncTask].mfxBS, outbs);
                    //MSDK_BREAK_ON_ERROR(sts);
                    pTasks[nFirstSyncTask].syncp.sync       = IntPtr.Zero;
                    pTasks[nFirstSyncTask].mfxBS.DataLength = 0;
                    pTasks[nFirstSyncTask].mfxBS.DataOffset = 0;
                    nFirstSyncTask = (nFirstSyncTask + 1) % taskPoolSize;


                    return(true);
                }
                else
                {
                    int compositeFrameIndex = 0;
                    //morevpp:
                    nIndex2 = GetFreeSurfaceIndex(pSurfaces2, nSurfNumVPPEnc);      // Find free frame surface
                    Trace.Assert(nIndex2 != (int)mfxStatus.MFX_ERR_NOT_FOUND);


                    for (;;)
                    {
                        var z = pmfxOutSurface;
                        z = null;
                        // if (compositeFrameIndex == 1)
                        //      z = overlay;
                        Trace.Assert(compositeFrameIndex <= 1);
                        // Process a frame asychronously (returns immediately)
                        sts = UnsafeNativeMethods.MFXVideoVPP_RunFrameVPPAsync(session, z, &pSurfaces2[nIndex2], (mfxExtVppAuxData *)0, &syncpV);

                        // COMPOSITING



                        if (mfxStatus.MFX_ERR_NONE < sts && syncpV.sync == IntPtr.Zero)
                        {    // repeat the call if warning and no output
                            if (mfxStatus.MFX_WRN_DEVICE_BUSY == sts)
                            {
                                Thread.Sleep(1);  // wait if device is busy
                            }
                        }
                        else if (mfxStatus.MFX_ERR_NONE < sts && syncpV.sync != IntPtr.Zero)
                        {
                            sts = mfxStatus.MFX_ERR_NONE;     // ignore warnings if output is available
                            break;
                        }
                        else
                        {
                            if (sts != mfxStatus.MFX_ERR_MORE_DATA && sts != mfxStatus.MFX_ERR_MORE_SURFACE)
                            {
                                QuickSyncStatic.ThrowOnBadStatus(sts, "vppAsync");
                            }
                            break;  // not a warning
                        }
                    }

                    //VPP needs more data, let decoder decode another frame as input
                    if (mfxStatus.MFX_ERR_MORE_DATA == sts)
                    {
                        return(false);
                        // compositeFrameIndex++;
                        //goto morevpp;
                    }
                    else
                    if (mfxStatus.MFX_ERR_MORE_SURFACE == sts)
                    {
                        // Not relevant for the illustrated workload! Therefore not handled.
                        // Relevant for cases when VPP produces more frames at output than consumes at input. E.g. framerate conversion 30 fps -> 60 fps
                        QuickSyncStatic.ThrowOnBadStatus(sts, "vpp");;
                    }
                    else
                    if (mfxStatus.MFX_ERR_NONE != sts)
                    {
                        QuickSyncStatic.ThrowOnBadStatus(sts, "vpp");
                    }
                    ;


                    for (;;)
                    {
                        // Encode a frame asychronously (returns immediately)
                        //sts = mfxENC.EncodeFrameAsync(NULL, pSurfaces2[nIndex2], &pTasks[nTaskIdx].mfxBS, &pTasks[nTaskIdx].syncp);
                        sts = UnsafeNativeMethods.MFXVideoENCODE_EncodeFrameAsync(session, (mfxEncodeCtrl *)0, &pSurfaces2[nIndex2], &pTasks[nTaskIdx].mfxBS, &pTasks[nTaskIdx].syncp);

                        if (mfxStatus.MFX_ERR_NONE < sts && pTasks[nTaskIdx].syncp.sync == IntPtr.Zero)
                        {    // repeat the call if warning and no output
                            if (mfxStatus.MFX_WRN_DEVICE_BUSY == sts)
                            {
                                Thread.Sleep(1);  // wait if device is busy
                            }
                        }
                        else if (mfxStatus.MFX_ERR_NONE < sts && pTasks[nTaskIdx].syncp.sync != IntPtr.Zero)
                        {
                            sts = mfxStatus.MFX_ERR_NONE;     // ignore warnings if output is available
                            break;
                        }
                        else if (mfxStatus.MFX_ERR_NOT_ENOUGH_BUFFER == sts)
                        {
                            // Allocate more bitstream buffer memory here if needed...
                            break;
                        }
                        else
                        {
                            if (sts != mfxStatus.MFX_ERR_MORE_DATA && sts != mfxStatus.MFX_ERR_MORE_SURFACE)
                            {
                                QuickSyncStatic.ThrowOnBadStatus(sts, "encodeAsync");
                            }
                            break;
                        }
                    }
                }
            }


            // MFX_ERR_MORE_DATA means that file has ended, need to go to buffering loop, exit in case of other errors
            //MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA);
            if (sts == mfxStatus.MFX_ERR_MORE_DATA)
            {
                return(false);
            }
            QuickSyncStatic.ThrowOnBadStatus(sts, "dec or enc or vpp");

            return(true);
        }
Ejemplo n.º 13
0
        /// <summary>Return the next frame available</summary>
        public IEnumerable <BitStreamChunk> GetFrames()
        {
            var            inbuf = new byte[lowLevelTranscoder.BufferSize];
            BitStreamChunk bsc   = new BitStreamChunk();

            while (true)
            {
                if (lowLevelTranscoder.BufferFreeCount > lowLevelTranscoder.BufferSize / 2)
                {
                    int r = inStream.Read(inbuf, 0, Math.Min((int)inbuf.Length, lowLevelTranscoder.BufferFreeCount));
                    if (r <= 0)
                    {
                        break;
                    }

                    lowLevelTranscoder.PutBitstream(inbuf, 0, r);
                }

                lowLevelTranscoder.GetNextFrame(ref bsc);
                if (bsc.bytesAvailable > 0)
                {
                    yield return(bsc);
                }
            }

            while (lowLevelTranscoder.GetNextFrame(ref bsc))
            {
                if (bsc.bytesAvailable > 0)
                {
                    yield return(bsc);
                }
            }

            while (lowLevelTranscoder.Flush1(ref bsc))
            {
                if (bsc.bytesAvailable > 0)
                {
                    yield return(bsc);
                }
            }

            while (lowLevelTranscoder.Flush2(ref bsc))
            {
                if (bsc.bytesAvailable > 0)
                {
                    yield return(bsc);
                }
            }

            while (lowLevelTranscoder.Flush3(ref bsc))
            {
                if (bsc.bytesAvailable > 0)
                {
                    yield return(bsc);
                }
            }

            while (lowLevelTranscoder.Flush4(ref bsc))
            {
                if (bsc.bytesAvailable > 0)
                {
                    yield return(bsc);
                }
            }
        }