Example #1
0
        private bool ReadNextSequence()
        {
            bufferLength = 0;
            Frames.Clear();

            SequenceExtensionPresent = false;
            SequenceFrames           = 0;
            SequenceStartFrame       = CurrentFrame;

            if (!FindNextSequenceStart())
            {
                LastError = ErrorCode.MPEG_ERROR_NOSEQUENCE;
                return(false);
            }

            int       picture  = 0;
            MPEGFrame newFrame = new MPEGFrame();

            newFrame.StartIndex  = bufferLength - 4;    // -4 compensates for sequence start code
            newFrame.FrameNumber = CurrentFrame++;

            if (!ConsumeSequenceHeader())
            {
                return(false);
            }

            if (!ConsumeExtensions(0))
            {
                return(false);
            }

            int  pictures = 0;
            bool done     = false;

            while (!done)
            {
                uint startCode = reader.Peek32();
                if (startCode == MPEG_CODE_GROUP_START)
                {
                    newFrame.StartOfGOP = true;
                    ConsumeGroupOfPicturesHeader();
                    ConsumeExtensions(1);
                }
                else if (startCode >= MPEG_CODE_SLICE_START_LOW && startCode <= MPEG_CODE_SLICE_START_HIGH)
                {
                    ConsumeSlice();
                }
                else if (startCode == MPEG_CODE_PICTURE_START)
                {
                    picture++;
                    if (picture > 1)
                    {
                        newFrame.EndIndex = bufferLength - 1;
                        Frames.Add(newFrame);
                        newFrame             = new MPEGFrame();
                        newFrame.StartIndex  = bufferLength;
                        newFrame.FrameNumber = CurrentFrame++;
                    }
                    pictures++;
                    ConsumePictureHeader();

                    if (PictureCodingType == 1)
                    {
                        newFrame.FrameType = 'I';
                    }
                    else if (PictureCodingType == 2)
                    {
                        newFrame.FrameType = 'P';
                    }
                    else if (PictureCodingType == 3)
                    {
                        newFrame.FrameType = 'B';
                    }

                    newFrame.TemporalReference  = TemporalReference;
                    newFrame.PresentationNumber = SequenceStartFrame + TemporalReference;
                    newFrame.VBVDelay           = PictureVBVDelay;
                }
                else if (startCode == MPEG_CODE_EXTENSION_START)
                {
                    ConsumeExtensions(2);
                }
                else if (startCode == MPEG_CODE_SEQUENCE_END)
                {
                    // consume sequence_end_code
                    ReadAndBuffer32();
                    done = true;
                }
                else
                {
                    done = true;
                }
            }

            newFrame.EndIndex = bufferLength - 1;
            Frames.Add(newFrame);

            return(true);
        }
Example #2
0
        private ByteArray PesForFrame(int mpegStream, int index, double initialDTS)
        {
            ByteArray result = new ByteArray();

            MPEGFrame frame = Frames[index];

            result.Append((uint)(0x000001E0 + mpegStream));
            result.Append((ushort)0x0000);  // Transport stream PES packets don't need lengths if they're video

            // '10'								(2 bits)	02		= 0x80
            // PES_scrambling_control = '00'	(2 bits)	04		= 0x00
            // PES_priority	= '0'				(1 bit)		05		= 0x00
            // data_alignment indicator	= '1'	(1 bit)		06		= 0x04
            // copyright = '0'					(1 bit)		07		= 0x00
            // original_or_copy = '1'			(1 bit)		08		= 0x01
            //														= 0x85
            result.Append((byte)0x85);

            if (frame.FrameNumber == 0)
            {
                VBVDelay = frame.VBVDelay;
            }
            double frameDuration = 1.0 / SequenceFrameRate;
            double dts           = (double)frame.FrameNumber * frameDuration + VBVDelay;              // initialDTS;
            double pts           = (double)(frame.PresentationNumber + 1) * frameDuration + VBVDelay; // initialDTS;

            if (frame.PresentationNumber == 0)
            {
                InitialPTS = pts;
            }

            ulong intDts = (ulong)Math.Round(90000.0 * dts);
            ulong intPts = (ulong)Math.Round(90000.0 * pts);

            //if ((double)intDts / 90000.0 != dts)
            //  System.Diagnostics.Debugger.Break();

            if (dts == pts)
            {
                // PTS_DTS_flags = '10'				(2 bits)	02		= 0x80
                // ESCR_flag = '0'					(1 bit)		03		= 0x00
                // ES_rate_flag = '0'				(1 bit)		04		= 0x00
                // DSM_trick_mode_flag = '0'		(1 bit)		05		= 0x00
                // additional_copy_info_flag = '0'	(1 bit)		06		= 0x00
                // PES_CRC_flag = '0'				(1 bit)		07		= 0x00
                // PES_extension_flag				(1 bit)		08		= 0x00
                //														= 0x80
                result.Append((byte)0x80);

                // if(PTS_DTS_flags == '10')
                //	'0010'							(4 bits)	04
                //  PTS[32..30]						(3 bits)	07
                //  marker_bit = '1'				(1 bit)		08
                //  PTS[29..15]						(15 bits)	23
                //  marker_bit = '1'				(1 bit)		24
                //  PTS[14..0]						(15 bits)	39
                //  marker_bit = '1'				(1 bit)		40
                //	PES_header_data_length =                    40 bits or 5 bytes
                result.Append((byte)5);

                result.EnterBitMode();
                result.AppendBits((byte)0x2, 3, 0);
                result.AppendBits(intPts, 32, 30);
                result.AppendBit(1);
                result.AppendBits(intPts, 29, 15);
                result.AppendBit(1);
                result.AppendBits(intPts, 14, 0);
                result.AppendBit(1);
                result.LeaveBitMode();
            }
            else
            {
                // PTS_DTS_flags = '11'				(2 bits)	02		= 0xC0
                // ESCR_flag = '0'					(1 bit)		03		= 0x00
                // ES_rate_flag = '0'				(1 bit)		04		= 0x00
                // DSM_trick_mode_flag = '0'		(1 bit)		05		= 0x00
                // additional_copy_info_flag = '0'	(1 bit)		06		= 0x00
                // PES_CRC_flag = '0'				(1 bit)		07		= 0x00
                // PES_extension_flag				(1 bit)		08		= 0x00
                //														= 0xC0
                result.Append((byte)0xC0);

                // if(PTS_DTS_flags == '11')
                //	'0011'							(4 bits)	04
                //  PTS[32..30]						(3 bits)	07
                //  marker_bit = '1'				(1 bit)		08
                //  PTS[29..15]						(15 bits)	23
                //  marker_bit = '1'				(1 bit)		24
                //  PTS[14..0]						(15 bits)	39
                //  marker_bit = '1'				(1 bit)		40
                //	'0001'							(4 bits)	44
                //  DTS[32..30]						(3 bits)	47
                //  marker_bit = '1'				(1 bit)		48
                //  DTS[29..15]						(15 bits)	63
                //  marker_bit = '1'				(1 bit)		64
                //  DTS[14..0]						(15 bits)	79
                //  marker_bit = '1'				(1 bit)		80
                //	PES_header_data_length =                    80 bits or 10 bytes
                result.Append((byte)10);
                result.EnterBitMode();
                result.AppendBits((byte)0x3, 3, 0);
                result.AppendBits(intPts, 32, 30);
                result.AppendBit(1);
                result.AppendBits(intPts, 29, 15);
                result.AppendBit(1);
                result.AppendBits(intPts, 14, 0);
                result.AppendBit(1);
                result.AppendBits((byte)0x1, 3, 0);
                result.AppendBits(intDts, 32, 30);
                result.AppendBit(1);
                result.AppendBits(intDts, 29, 15);
                result.AppendBit(1);
                result.AppendBits(intDts, 14, 0);
                result.AppendBit(1);
                result.LeaveBitMode();
            }

            // Append the frame data
            result.Append(buffer, frame.StartIndex, frame.Length);

            // TODO : figure out what the heck the quad-byte alignment thing is in Cablelabs VoD

            /*int pesHeaderSize = 14;     // just pts
             * if (pts != dts)
             *  pesHeaderSize += 5;     // adjust for dts
             *
             * while (((result.length - pesHeaderSize) % 4) != 0)
             *  result.append((byte)0x00);*/

            frame.PESPacket = result;
            frame.DTS       = dts;
            frame.PTS       = pts;

            return(result);
        }