Example #1
0
        /// <summary>
        /// QBox.Read
        /// Read-in a QBox
        /// NOTE: stream position is NOT assumed to start at the beginning of a qbox.
        /// </summary>
        /// <param name="br"></param>
        public void Read(BinaryReader br)
        {
            //ODS.Processing.Core.Logger.Instance.Info("Reading QBox");
              mHeaderSize = 0;
              if (br.BaseStream.CanSeek) {
            mHeaderPosition = br.BaseStream.Position; // needed for flashback only
            if (br.BaseStream.Position + 4 > br.BaseStream.Length)
              throw new Exception("QBox:Read, Not enough data to read qbox length");
              }
              mBoxSize = QBox.BE32(br.ReadUInt32()); mHeaderSize += 4;
              if (mBoxSize == 0)
            throw new Exception("QBox:Read, Invalid box size");

              if (br.BaseStream.CanSeek) {
            // subtract 4 as the size includes the 4 bytes we read already which was the length...
            if (br.BaseStream.Position + (long)(mBoxSize - 4) > br.BaseStream.Length) {
              // reset the location to the start of the qbox
              // this allows the reader to try again later...
              br.BaseStream.Position = mHeaderPosition;
              throw new Exception("QBox:Read, Not enough data to read qbox content");
            }
              }

              try {
            mBoxType = QBox.BE32(br.ReadUInt32());
            mHeaderSize += 4;
            if (mBoxType != QBOX_TYPE)
              throw new Exception("QBox:Read, Invalid box type (not a qbox)");
            mBoxFlags.value = (uint) QBox.BE32(br.ReadUInt32());
            mHeaderSize += 4;
            mSampleStreamType = QBox.BE16(br.ReadUInt16());
            mHeaderSize += 2;
            mSampleStreamId = QBox.BE16(br.ReadUInt16());
            mHeaderSize += 2; // replacement for all of commented lines below
            mSampleFlags = QBox.BE32(br.ReadUInt32());
            mHeaderSize += 4;

            // version 0 only uses a single int for the CTS, version 1 uses 64 bit high/low value
            _SampleCTSHigh = QBox.BE32(br.ReadUInt32());
            mHeaderSize += 4;
            if (mBoxFlags.version == 1 || mBoxFlags.version == 2) {
              _SampleCTSLow = QBox.BE32(br.ReadUInt32());
              mHeaderSize += 4;
            }

            if (mBoxFlags.version == 2) {
              mBoxContinuityCounter = (uint)QBox.BE32(br.ReadUInt32()); mHeaderSize += 4;
              mFrameCounter = (uint)QBox.BE32(br.ReadUInt32()); mHeaderSize += 4;
              mSampleDuration = (uint)QBox.BE32(br.ReadUInt32()); mHeaderSize += 4;
              mStreamDuration = (ulong)QBox.BE64(br.ReadUInt64()); mHeaderSize += 8;

                    mOffsetFromLastSyncPoint = (uint)QBox.BE32(br.ReadUInt32()); mHeaderSize += 4;
                    mOffsetFromLastFrame = (uint)QBox.BE32(br.ReadUInt32()); mHeaderSize += 4;

              mReserved2 = (ulong)QBox.BE64(br.ReadUInt64()); mHeaderSize += 8;
              mReserved3 = (ulong)QBox.BE64(br.ReadUInt64()); mHeaderSize += 8;
              mReserved4 = (ulong)QBox.BE64(br.ReadUInt64()); mHeaderSize += 8;
            }

            //// adjust time stamp if 120KHz bit is ON (doesn't matter which track)
            //if ((mSampleFlags & QBox.QBOX_SAMPLE_FLAGS_120HZ_CLOCK) != 0U) {
            //  mSampleCTS = (mSampleCTS * QBox.BASE_TIME_SCALE) / 120000U;
            //  mSampleDuration = (mSampleDuration * QBox.BASE_TIME_SCALE) / 120000U;
            //  mStreamDuration = (mStreamDuration * QBox.BASE_TIME_SCALE) / 120000U;
            //}

            mSampleSize = (int) mBoxSize - mHeaderSize;
            if (mSampleSize == 0)
              return;

            mSample = new QBoxSample();
            mSampleSize -= mSample.Read(br, mSampleSize, mBoxFlags.flags, mSampleFlags, mSampleStreamType, mSampleStreamId);
            mSamplePosition += mSample.mSampleHeaderSize;
              } catch (Exception ex) {
            // reset the location to the start of the qbox
            // this allows the reader to try again later...
            if (br.BaseStream.CanSeek)
              br.BaseStream.Position = mHeaderPosition;
            throw ex;
              }
            #if REMOVE_EXTRA_SPS
              // deal with the special case in which the box is a Meta V box
              if ((mSample.v != null) && (mSample.mSampleHeaderSize > 0))
            mSamplePosition += 6; // nalu delimiter length is always 6
            #endif
        }
Example #2
0
        public static int GetSampleSize(QBoxSample audioMetaSample)
        {
            if (audioMetaSample == null)
            return 0;

              if (audioMetaSample.a != null)
            return (int)audioMetaSample.a.samplesize;

              if (audioMetaSample.qmed != null)
              {
            QMed.QMedAAC aacQ = (QMed.QMedAAC)audioMetaSample.qmed; // FIXME: for now we assume it's a QMedAAC
            return (int)aacQ.sampleSize;
              }

              return 0;
        }
Example #3
0
        public static byte[] GetAudioSpecificConfig(QBoxSample audioMetaSample)
        {
            if (audioMetaSample == null)
            return null;

              if (audioMetaSample.qmed != null)
              {
            QMed.QMedAAC aacQ = (QMed.QMedAAC)audioMetaSample.qmed; // FIXME: for now we assume it's a QMedAAC
            return aacQ.audioSpecificConfig;
              }

              return null;
        }
Example #4
0
        public static int GetChannelCount(QBoxSample audioMetaSample)
        {
            if (audioMetaSample == null)
            return 0;

              if (audioMetaSample.a != null)
            return (int)audioMetaSample.a.channels;

              if (audioMetaSample.qmed != null)
              {
            QMed.QMedAAC aacQ = (QMed.QMedAAC)audioMetaSample.qmed; // FIXME: for now we assume it's a QMedAAC
            return (int)aacQ.channels;
              }

              return 0;
        }
Example #5
0
        /// <summary>
        /// Constructor for writing to a qbox file.
        /// FIXME: Need to add v2 properties like mFrameCounter, mContinuityCounter, mSampleDuration, and mStreamDuration.
        /// </summary>
        /// <param name="dataSize"></param>
        /// <param name="flags"></param>
        /// <param name="timeStamp"></param>
        /// <param name="sampleStreamType"></param>
        /// <param name="sampleFlags"></param>
        public QBox(int dataSize, uint qboxFlags, ulong timeStamp, string sampleStreamType, ulong sampleFlags)
            : this(QBOX_FLAGS_SAMPLE_DATA_PRESENT)
        {
            mBoxFlags.flags |= qboxFlags;
              //mSampleCTS = timeStamp;
              // set stream type: at this time we only accept AAC and H264 payload
              mSampleStreamType = (ushort)((sampleStreamType == "Audio") ? QBOX_SAMPLE_TYPE_AAC :
            ((sampleStreamType == "Video") ? QBOX_SAMPLE_TYPE_H264 : 0u));
              mSampleStreamId = (ushort)((sampleStreamType == "Audio") ? QBOX_AUDIO_TRACK :
            ((sampleStreamType == "Video") ? QBOX_VIDEO_TRACK : 0u));
              mSampleFlags |= sampleFlags;

              if (mBoxFlags.version == 0)
            mHeaderSize = 24;
              else if (mBoxFlags.version == 1)
            mHeaderSize = 28;
              else // version 2;
            mHeaderSize = 80;

              mBoxSize = (ulong)mHeaderSize;
              if ((mBoxFlags.flags & QBOX_FLAGS_SAMPLE_DATA_PRESENT) != 0)
              {
            mSample = new QBoxSample(dataSize, sampleFlags, mSampleStreamType);
            mBoxSize = (ulong)(mHeaderSize + mSample.mSampleHeaderSize + dataSize);
            mSampleSize = dataSize;
              }
        }