Example #1
0
 public Vp9PictureInfo Convert()
 {
     return(new Vp9PictureInfo()
     {
         IsKeyFrame = Flags.HasFlag(FrameFlags.IsKeyFrame),
         IntraOnly = Flags.HasFlag(FrameFlags.IntraOnly),
         UsePrevInFindMvRefs =
             !Flags.HasFlag(FrameFlags.ErrorResilientMode) &&
             !Flags.HasFlag(FrameFlags.FrameSizeChanged) &&
             !Flags.HasFlag(FrameFlags.IntraOnly) &&
             Flags.HasFlag(FrameFlags.LastShowFrame) &&
             !Flags.HasFlag(FrameFlags.LastFrameIsKeyFrame),
         RefFrameSignBias = RefFrameSignBias,
         BaseQIndex = BaseQIndex,
         YDcDeltaQ = YDcDeltaQ,
         UvDcDeltaQ = UvDcDeltaQ,
         UvAcDeltaQ = UvAcDeltaQ,
         Lossless = Lossless != 0,
         TransformMode = TxMode,
         AllowHighPrecisionMv = AllowHighPrecisionMv != 0,
         InterpFilter = InterpFilter,
         ReferenceMode = ReferenceMode,
         CompFixedRef = CompFixedRef,
         CompVarRef = CompVarRef,
         Log2TileCols = Log2TileCols,
         Log2TileRows = Log2TileRows,
         SegmentEnabled = Seg.Enabled != 0,
         SegmentMapUpdate = Seg.UpdateMap != 0,
         SegmentMapTemporalUpdate = Seg.TemporalUpdate != 0,
         SegmentAbsDelta = Seg.AbsDelta,
         SegmentFeatureEnable = Seg.FeatureMask,
         SegmentFeatureData = Seg.FeatureData,
         ModeRefDeltaEnabled = Lf.ModeRefDeltaEnabled != 0,
         RefDeltas = Lf.RefDeltas,
         ModeDeltas = Lf.ModeDeltas
     });
 }
Example #2
0
        /// <summary>
        /// Reads the next Tag or Frame.
        /// If <see cref="IsFrame"/> is true then <see cref="Container.Node.LengthSize"/> will be negitive to indicate it's variable length from <see cref="Container.Node.Position"/>
        /// </summary>
        /// <returns>The <see cref="Container.Node"/> found</returns>
        public Node ReadNext()
        {
            //long offset = Position;

            byte nextByte = (byte)ReadByte();

            if (nextByte == NutByte)
            {
                byte[] identifier = new byte[] { NutByte, 0, 0, 0, 0, 0, 0, 0 };

                Read(identifier, 1, IdentifierBytesSize);

                int lengthSize = 0;

                long length = DecodeVariableLength(this, out lengthSize);

                return(new Node(this, identifier, lengthSize, Position, length, length <= Remaining));
            }
            else
            {
                //  if (avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance)
                //if (Position > (m_MaxDistance ?? DefaultMaxDistance)) throw new InvalidOperationException("Last frame must have been damaged.");

                /*
                 *          Frame Coding
                 *
                 *          Each frame begins with a "framecode", a single byte which indexes a
                 *          table in the main header. This table can associate properties such as
                 *          stream ID, size, relative timestamp, keyframe flag, etc. with the
                 *          frame that follows, or allow the values to be explicitly coded
                 *          following the framecode byte. By careful construction of the framecode
                 *          table in the main header, an average overhead of significantly less
                 *          than 2 bytes per frame can be achieved for single-stream files at low
                 *          bitrates.
                 *          Framecodes can also be flagged as invalid, and seeing such a framecode
                 *          indicates a damaged file. The frame code 0x4E ('N') is a special invalid
                 *          framecode which marks the next packet as a NUT packet, and not a frame.
                 *          The following 7 bytes, combined with 'N', are the full startcode of
                 *          the NUT packet.
                 */

                FrameFlags frameFlags = (FrameFlags)HeaderOptions[nextByte].Item1;

                //Check for invalid flag
                if (frameFlags.HasFlag(FrameFlags.Invalid))
                {
                    throw new InvalidOperationException("FrameCodes must not have the flag \"FrameFlags.Invalid\"");
                }

                long streamId = HeaderOptions[nextByte].Item2;

                long reserved_count = HeaderOptions[nextByte].Rest.Item1;

                int header_idx = (int)HeaderOptions[nextByte].Item7;

                long size_mul = HeaderOptions[nextByte].Item3;

                long size_msb = 0, size_lsb = HeaderOptions[nextByte].Item4,
                // Size in bytes at the end inside data which represent frame sidedata and frame metadata.
                     sidedata_size = HeaderOptions[nextByte].Rest.Item2;

                int bytesReadTotal = 0, bytesReadNow;

                long length = size_lsb, temp;

                //Check to see if the real flags are in the data
                if (frameFlags.HasFlag(FrameFlags.Coded))
                {
                    frameFlags     ^= (FrameFlags)(DecodeVariableLength(this, out bytesReadNow));
                    bytesReadTotal += bytesReadNow;
                }

                //Check for invalid flag
                if (frameFlags.HasFlag(FrameFlags.Invalid))
                {
                    throw new InvalidOperationException("FrameCodes must not have the flag \"FrameFlags.Invalid\"");
                }

                //Check for StreamId
                if (frameFlags.HasFlag(FrameFlags.StreamId))
                {
                    streamId        = DecodeVariableLength(this, out bytesReadNow);
                    bytesReadTotal += bytesReadNow;
                    if (streamId > MaximumHeaderOptions)
                    {
                        throw new InvalidOperationException("StreamId cannot be > 256");
                    }
                }

                //Check for the PTS
                //Should probably be stored in Identifier.
                if (frameFlags.HasFlag(FrameFlags.CodedPTS))
                {
                    temp            = DecodeVariableLength(this, out bytesReadNow);
                    bytesReadTotal += bytesReadNow;
                }
                else
                {
                    //Todo
                    //Decode PTS
                    //Store somewhere easy to get to (Identifier)
                }

                //Check to see if the size is coded in the data
                if (frameFlags.HasFlag(FrameFlags.SizeMSB))
                {
                    size_msb        = DecodeVariableLength(this, out bytesReadNow);
                    bytesReadTotal += bytesReadNow;
                }

                if (frameFlags.HasFlag(FrameFlags.MatchTime))
                {
                    temp            = DecodeVariableLength(this, out bytesReadNow);
                    bytesReadTotal += bytesReadNow;
                }

                //Check for alternate header index
                if (frameFlags.HasFlag(FrameFlags.HeaderIndex))
                {
                    header_idx = (int)DecodeVariableLength(this, out bytesReadNow);
                    if (header_idx > m_HeaderOptions.Count())
                    {
                        throw new InvalidOperationException("Invalid header index found: '" + header_idx + "'. Cannot indicate a header which does not exist");
                    }
                    bytesReadTotal += bytesReadNow;
                }

                //7  FLAG_RESERVED    If set, reserved_count is coded in the frame header.
                //reserved_count[frame_code] (v)
                //MUST be <256.
                if (frameFlags.HasFlag(FrameFlags.Reserved))
                {
                    reserved_count  = DecodeVariableLength(this, out bytesReadNow);
                    bytesReadTotal += bytesReadNow;
                }

                //If the header set a sidedata_size > 0 then it was set in the header, if was set to 0 then this means to ignore it for this frame.
                //Read the side data ONLY for Draft Compatibility (20130327)
                if (sidedata_size >= 0 && frameFlags.HasFlag(FrameFlags.SideMetaData))
                {
                    //Optionally side data size can be specified here, this was not required because the structure contains the sidedata_size implicitly due to the main header having it set there.
                    //1 - Because it is confusing because the header could indicate 0 and there could be a non 0 value here thus it is redundant to store it twice.
                    //2 - Because in the latest version there is also meta data right after

                    /*
                     +    if(frame_flags&FLAG_SIDEDATA)
                     +        sidedata_size                   v
                     +    for(i=0; i<frame_res - !(frame_flags&FLAG_SIDEDATA); i++)
                     */
                    sidedata_size   = DecodeVariableLength(this, out bytesReadNow);
                    bytesReadTotal += bytesReadNow;
                    //Reduce reserved_count by sidedata_size
                    reserved_count -= sidedata_size;
                }

                //Read any reserved data is left
                while (reserved_count > 0)
                {
                    DecodeVariableLength(this, out bytesReadNow);
                    bytesReadTotal += bytesReadNow;
                    reserved_count -= bytesReadNow;
                }

                //from MainHeader
                length = size_msb * size_mul + size_lsb;

                //Frames with a final size of less than ForwardPointerWithChecksum (4096) will have the header data preprended.
                //thus TotalLength cannot include EllisionHeaders[header_idx] length
                if (length > ForwardPointerWithChecksum)
                {
                    header_idx = 0;
                }
                else
                {
                    length -= EllisionHeaders[header_idx].Length;
                }

                /*
                 * EOR frames MUST be zero-length and must be set keyframe.
                 * All streams SHOULD end with EOR, where the pts of the EOR indicates the end presentation time of the final frame. (NOT AN EXCEPTION CASE)
                 *
                 * An EOR set stream is unset by the first content frame.
                 * EOR can only be unset in streams with zero decode_delay .
                 *
                 * Checksum MUST be set if the frame's data_size is strictly greater than
                 * 2*max_distance or the difference abs(pts-last_pts) is strictly greater than
                 * max_pts_distance (where pts represents this frame's pts and last_pts is defined as below).
                 */

                //Ensure Key Frame for Eor and that Length is positive
                if (frameFlags.HasFlag(FrameFlags.EOR))
                {
                    if (false == frameFlags.HasFlag(FrameFlags.Key))
                    {
                        throw new InvalidOperationException("EOR Frames must be key");
                    }

                    if (length != 0)
                    {
                        throw new InvalidOperationException("EOR Frames must have size 0");
                    }
                }

                //Check for Checksum flag only because if it is present length is not checked.
                if (frameFlags.HasFlag(FrameFlags.Checksum))
                {
                    //Checksum

                    //Position += 4;

                    //Do this so the Frame can be optionall CRC'd by the Enumerator if CheckCRC is true
                    //length += 4;
                }
                else if (false == (HasMainHeaderFlags && false == MainHeaderFlags.HasFlag(HeaderFlags.Pipe))
                         &&
                         length > (2 * MaximumDistance))
                {
                    throw new InvalidOperationException("frame size > 2 max_distance and no checksum");
                }

                //Can store 3 more bytes in identifier (PTS) @ 1
                //LengthSize is negitive which indicates its variable length from Position
                return(new Node(this, new byte[] { 0, 0, 0, 0, (byte)sidedata_size, (byte)header_idx, (byte)streamId, nextByte }, bytesReadTotal - IdentifierSize, Position, length, length <= Remaining));
            }
        }
Example #3
0
        public static byte[] GetFrameData(NutReader reader, Node node, out byte[] sideData, out byte[] metaData)
        {
            FrameFlags flags = GetFrameFlags(reader, node);

            sideData = metaData = null;

            //Always include the frame header
            IEnumerable <byte> frameData = GetFrameHeader(reader, node);

            //Check if data needs to be removed
            if (flags.HasFlag(FrameFlags.SideMetaData))
            {
                //Compatibility
                //If SizeData in the header was set this is a draft version and the data is at the end of the frame.
                //In such a case the sidedata size was already read from the frame header and is stored in the Identifier.
                long sidedata_size = node.Identifier[4];

                //Just incase it was indicated that this frame uses a normal side data size of 0 and includes specific side data for the frame
                //Check the header and frame headers value which was stored when reading the frame.
                if (sidedata_size > 0)
                {
                    metaData = null; //Not included in spec.

                    int dataSize = (int)(node.DataSize - sidedata_size);

                    frameData = Enumerable.Concat(frameData, node.Data.Take(dataSize));

                    sideData = node.Data.Skip(dataSize).ToArray();
                }
                else //Current Spec
                {
                    int bytesReadNow = 0, bytesReadTotal = 0;
                    //Get a stream of the data
                    using (var stream = node.DataStream)
                    {
                        int size = (int)reader.DecodeVariableLength(stream, out bytesReadNow);

                        //Side Data Count (From Info) and read
                        if (size > 0)
                        {
                            bytesReadTotal += bytesReadNow;

                            sideData = new byte[size];

                            reader.Read(sideData, 0, size);

                            bytesReadTotal += size;
                        }

                        //Meta Data Count (From Info) and read
                        size = (int)reader.DecodeVariableLength(stream, out bytesReadNow);

                        if (size > 0)
                        {
                            bytesReadTotal += bytesReadNow;

                            metaData = new byte[size];

                            reader.Read(sideData, 0, size);

                            bytesReadTotal += size;
                        }

                        //The position of this stream is now @ the end of the data which does not belong to the frame itself.
                        frameData = Enumerable.Concat(frameData, node.Data.Skip(bytesReadTotal));
                    }
                }
            }
            else //The data of the frame is as it is
            {
                frameData = Enumerable.Concat(frameData, node.Data);
            }

            //Return the allocated array
            return(frameData.ToArray());
        }