/// <summary> /// ReadMetaInfo /// </summary> /// <param name="br"></param> /// <param name="sampleStreamType"></param> /// <param name="inTotalSize"></param> private void ReadMetaInfo(BinaryReader br, uint sampleStreamType, int inTotalSize) { if (sampleStreamType == QBox.QBOX_SAMPLE_TYPE_H264) { if (v != null) throw new Exception("ReadMetaInfo: QBoxMetaV v already set"); v = new QBoxMetaV(); mSampleHeaderSize = v.Read(br); if ((inTotalSize - mSampleHeaderSize) != 0) throw new Exception("QBoxSample.Read: Video size incorrect."); } else if ((sampleStreamType == QBox.QBOX_SAMPLE_TYPE_QMA) || (sampleStreamType == QBox.QBOX_SAMPLE_TYPE_AAC)) { if (a != null) throw new Exception("There should only be one QBoxMetaA for audio"); a = new QBoxMetaA(); mSampleHeaderSize = a.Read(br); if ((inTotalSize - mSampleHeaderSize) != 0) throw new Exception("QBoxSample.Read: Audio size incorrect."); } else throw new Exception("QBoxSample.Read: Sample stream type not found."); }
public QBoxSample(int dataSize, ulong sampleFlags, ushort sampleStreamType) { if ((sampleFlags & QBox.QBOX_SAMPLE_FLAGS_META_INFO) != 0) { if (sampleStreamType == QBox.QBOX_SAMPLE_TYPE_H264) { if (v != null) throw new Exception("QBoxSample.constructor: QBoxMetaV v already set"); v = new QBoxMetaV(); mSampleHeaderSize = 32; } else if ((sampleStreamType == QBox.QBOX_SAMPLE_TYPE_QMA) || (sampleStreamType == QBox.QBOX_SAMPLE_TYPE_AAC)) { if (a != null) throw new Exception("There should only be one QBoxMetaA for audio"); a = new QBoxMetaA(); mSampleHeaderSize = 24; } else throw new Exception("QBoxSample.Read: Sample stream type not found."); } else if ((sampleFlags & QBox.QBOX_SAMPLE_FLAGS_QMED_PRESENT) > 0) { switch ((uint)sampleStreamType) { case QBOX_SAMPLE_TYPE_AAC: QMed.QMedAAC qmedaac = new QMed.QMedAAC(); qmed = qmedaac; break; //case QBOX_SAMPLE_TYPE_H264: //case QBOX_SAMPLE_TYPE_H264_SLICE: // QMed.QMedH264 qmedh264 = new QMed.QMedH264(); // qmed = qmedh264; // break; case QBOX_SAMPLE_TYPE_QPCM: QMed.QMedPCM qmedpcm = new QMed.QMedPCM(); qmed = qmedpcm; break; case QBOX_SAMPLE_TYPE_Q711: QMed.QMed711 qmed711 = new QMed.QMed711(); qmed = qmed711; break; case QBOX_SAMPLE_TYPE_Q722: QMed.QMed722 qmed722 = new QMed.QMed722(); qmed = qmed722; break; case QBOX_SAMPLE_TYPE_Q726: QMed.QMed726 qmed726 = new QMed.QMed726(); qmed = qmed726; break; case QBOX_SAMPLE_TYPE_Q728: QMed.QMed728 qmed728 = new QMed.QMed728(); qmed = qmed728; break; case QBOX_SAMPLE_TYPE_JPEG: case QBOX_SAMPLE_TYPE_MPEG2_ELEMENTARY: case QBOX_SAMPLE_TYPE_USER_METADATA: case QBOX_SAMPLE_TYPE_QMA: case QBOX_SAMPLE_TYPE_DEBUG: case QBOX_SAMPLE_TYPE_VIN_STATS_GLOBAL: case QBOX_SAMPLE_TYPE_VIN_STATS_MB: break; default: throw new Exception(string.Format("Unknown QMed type: {0}", sampleStreamType)); } mSampleHeaderSize = (int)qmed.boxSize; } else { mSampleHeaderSize = 0; } }
/// <summary> /// GetVideoParamsFromH264SPS /// This private method sets v, the video meta sample. /// It returns the total size of delimiter, sps, and pps NALUs. /// </summary> /// <param name="br"></param> /// <param name="sampleSize"></param> /// <param name="VSetAlready">if V is already set, remove sps and pps and move access unit delimiter</param> int GetVideoParamsFromH264SPS(BinaryReader br, int sampleSize, bool VSetAlready, out int countToZero) { int totalSize = 0; countToZero = sampleSize; if (sampleSize < 60) throw new Exception("Payload too small"); mPayload = br.ReadBytes(sampleSize); BinaryReader reader = new BinaryReader(new MemoryStream(mPayload)); while (countToZero > 4) { ulong naluLen = BE32(reader.ReadUInt32()); long nextPos = reader.BaseStream.Position + (long)naluLen; uint typ = reader.ReadByte(); if ((naluLen > (ulong)countToZero) || (naluLen < 2)) throw new Exception("Invalid QBox video payload"); // access unit delimiter (aud) always comes first and its size is not added to total size because // it is be added back to the payload (see QBoxVideoTrack). if ((typ & 0x1Fu) == 9u) { if (v != null) throw new Exception("QBoxSample: QBoxMetaV object already exists, and a second one cannot be constructed"); v = new QBoxMetaV(); if (naluLen != 2) throw new Exception("Wrong nalu delimiter length"); if (VSetAlready) { v.aud = new byte[naluLen]; v.aud[0] = (byte)typ; v.aud[1] = reader.ReadByte(); } else if (v.aud != null) throw new Exception("QBox.QBoxSample.GetVideoParamsFromH264SPS: v.aud should be null"); } // if nalu type is Sequence Param Set, pick up width and height // also, build private codec data from this SPS // NOTE: it matters which video track this qbox belongs! if ((typ & 0x1Fu) == 7u) { v.sps = new byte[naluLen]; v.sps[0] = (byte)typ; reader.Read(v.sps, 1, (int)naluLen - 1); totalSize += (int)(4 + naluLen); // parse the SPS bit stream, just to get the correct width and height of video. BitReader bitReader = new BitReader(new MemoryStream(v.sps)); SequenceParameterSet sps = new SequenceParameterSet((uint)naluLen); sps.Read(bitReader); v.width = (ulong)sps.Width; v.height = (ulong)sps.Height; } else if ((typ & 0x1Fu) == 8u) { v.pps = new byte[naluLen]; v.pps[0] = (byte)typ; reader.Read(v.pps, 1, (int)naluLen - 1); totalSize += (int)(4 + naluLen); } countToZero -= ((int)naluLen + 4); reader.BaseStream.Position = nextPos; } return totalSize; }
public bool Compare(QBoxMetaV compareTo) { return (sps.SequenceEqual(compareTo.sps) && pps.SequenceEqual(compareTo.pps)); }