private IEnumerator <Nalu> GetAllNalus(Stream fs) { fs.Seek(0, SeekOrigin.Begin); uint offset = 0; ReadHeader(fs, ref offset); for (; ;) { long fsPos = fs.Position; FLVTag tag = ReadTag(fs, ref offset); if (tag != null) { var x = GetNalus(tag, fsPos); while (x.MoveNext()) { yield return(x.Current); } } else { break; } } yield break; }
//tag type, tag size, tag data private FLVTag ReadTag(Stream fs, ref uint offset) { try { FLVTag result = new FLVTag(); //prev tag size if (fs.ReadBlock(4) == null) { return(null); } offset += 4; result.tagType = fs.ReadU8(); offset += 1; result.tagSize = fs.ReadU24BE(); offset += 3; //timestamp fs.ReadU24BE(); offset += 3; //timestamp ext fs.ReadU8(); offset += 1; //stream id fs.ReadU24BE(); offset += 3; result.tagDataOffset = offset; // tag > 10M, maybe parse in wrong position if (result.tagSize > 10485760) { throw new FLVToolException(fs.Position, "Tag data > 10M, maybe an error."); } result.tagData = fs.ReadBlock(result.tagSize); offset += result.tagSize; return(result); } catch (EndOfStreamException) { return(null); } }
private IEnumerator <Nalu> GetNalus(FLVTag tag, long fsPos) { if (tag.tagType == 9) { MemoryStream ms = new MemoryStream(tag.tagData); uint offset = tag.tagDataOffset; //frame type and codec id uint tmp = ms.ReadU8(); offset += 1; if ((tmp & 0xf) == 7) { uint avcpkttype = ms.ReadU8(); offset += 1; if (avcpkttype == 1) //nalu { //composition time ms.ReadU24BE(); offset += 3; //avcc to annex-b while (ms.Position < ms.Length) { Nalu nalu = new Nalu(); nalu.type = Nalu.NaluType.OTHER; nalu.offset = offset; uint len = ms.ReadU32BE(); offset += 4; nalu.len = len; nalu.data = startcode.Append(ms.ReadBlock(len)); offset += len; yield return(nalu); } } else if (avcpkttype == 0) //sps pps { //??? ms.ReadU24BE(); offset += 3; //conf ver ms.ReadU8(); offset += 1; //avc profile ms.ReadU8(); offset += 1; //profile compatibility ms.ReadU8(); offset += 1; //avc level ms.ReadU8(); offset += 1; //length size - 1 uint len_minus_one = ms.ReadU8(); if (len_minus_one != 0xff) { throw new FLVToolException(fsPos + ms.Position - 1, "lengthSizeMinusOne != 3 in SPS, not supported"); } offset += 1; //sps count | 11100000 uint spsCntRaw = ms.ReadU8(); int spscount = (int)(spsCntRaw) & 0x1f; offset += 1; //sps for (int i = 0; i < spscount; ++i) { Nalu nalu = new Nalu(); nalu.type = Nalu.NaluType.SPS; nalu.offset = offset; uint spslen = ms.ReadU16BE(); offset += 2; nalu.len = spslen + 2; nalu.data = startcode.Append(ms.ReadBlock(spslen)); offset += spslen; yield return(nalu); } //pps count int ppscount = (int)(ms.ReadU8()); offset += 1; //pps for (int i = 0; i < ppscount; ++i) { Nalu nalu = new Nalu(); nalu.type = Nalu.NaluType.PPS; nalu.offset = offset; uint ppslen = ms.ReadU16BE(); offset += 2; nalu.len = ppslen + 2; nalu.data = startcode.Append(ms.ReadBlock(ppslen)); offset += ppslen; yield return(nalu); } } } } }