public bool Update() { var bitStream = downloader.DownloadStream; var reader = new EndianBinaryReader(EndianBitConverter.Big, bitStream); if (bitStream != null) { var stream = new StreamReader(bitStream); { reader.ReadBytes(3); //"FLV" reader.ReadBytes(6); //Other starter shit while (true) { try { var footer = reader.ReadUInt32(); var tag = new FlvTag(); tag.Load(reader); AddedTag(tag); } catch (Exception) { reader.Close(); //End of stream return(false); } } } } return(true); }
public bool Update() { var bitStream = downloader.DownloadStream; var reader = new EndianBinaryReader(EndianBitConverter.Big, bitStream); if(bitStream != null) { var stream = new StreamReader(bitStream); { reader.ReadBytes(3); //"FLV" reader.ReadBytes(6); //Other starter shit while (true) { try { var footer = reader.ReadUInt32(); var tag = new FlvTag(); tag.Load(reader); AddedTag(tag); } catch (Exception) { reader.Close(); //End of stream return false; } } } } return true; }
private static int RunExtractAndReturnExitCode(LaunchOptions.Extract opts) { Quite = opts.Quite; using var flv_stream = File.Open(opts.InputPath, FileMode.Open, FileAccess.Read, FileShare.Read); var tags = FlvReader.ReadFlvFile(flv_stream, opts.TagNum + 1); if (tags.Length > opts.TagNum) { FlvTag tag = tags[opts.TagNum]; if (string.IsNullOrWhiteSpace(opts.OutputPath)) { var s = new MemoryStream(); if (tag.TagType == TagType.Script && !opts.Byte) { FlvWriter.WriteTagData(s, flv_stream, tag); s.Position = 0; var body = ScriptTagBody.Parse(s); Console.WriteLine(body.ToJson()); } else { FlvWriter.WriteTag(s, flv_stream, tag); var str = BitConverter.ToString(s.ToArray()).Replace("-", ""); str = string.Join('\n', str.SplitInParts(64)); Console.WriteLine(str); } return(0); } else { var fi = new FileInfo(opts.OutputPath); if (fi.Exists && !opts.Overwrite) { if (!Quite) { Console.WriteLine("文件已经存在,使用 --force 参数覆盖目标位置文件"); } return(1); } using var output = fi.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.Read); FlvWriter.WriteTag(output, flv_stream, tag); return(0); } } else { if (!Quite) { Console.WriteLine($"文件中只有个 {tags.Length} Tag,而需要第 {opts.TagNum} 个 Tag"); } return(1); } }
public void Remove(int index) { if (index < 0 || index >= Tags.Count) { return; } FlvTag tag = Tags[index]; //if (Duration <= tag.TimeStamp) { // RefreshDuration(); //} this.Length -= tag.DataSize + 11; Tags.RemoveAt(index); }
public FlvParser(Stream stream, Predicate <FlvTag> exec) { FLVHeader header = FLVHeader.ReadHeader(stream); if (!header.IsFlv) { this.IsFlv = false; return; } this.IsFlv = true; stream.Seek(header.Length, SeekOrigin.Begin); Tags = new List <FlvTag>(); FlvTag tag; while ((tag = FlvTag.ReadTag(stream)) != null) { if (tag is ScriptTag) { this.MetaTag = tag as ScriptTag; } Tags.Add(tag); if (Duration < tag.TimeStamp) { Duration = tag.TimeStamp; } if (exec != null) { if (!exec(tag)) { break; } } } if (Tags.Count > 1) { this.Length = stream.Length - Tags[1].Offset + 11; //+ FlvMain.c_HeaderSize; this.Rate = (this.Duration == 0 ? 0 : this.Length * 8 / this.Duration); } }
private void flvStreamSource_SampleRequested(MediaStreamSource sender, MediaStreamSourceSampleRequestedEventArgs args) { MediaStreamSourceSampleRequest request = args.Request; MediaStreamSourceSampleRequestDeferral deferal = request.GetDeferral(); FlvFile flvFile = mediaStreamFileSource as FlvFile; FlvTag flvTag = null; MemoryStream stream = null; MediaStreamSample sample = null; try { if (flvFile != null) { if (request.StreamDescriptor is VideoStreamDescriptor) { flvTag = flvFile.FlvFileBody.CurrentVideoTag; if (flvTag.VideoData.CodecID == CodecID.AVC) { byte[] by = flvTag.VideoData.AVCVideoPacket.NALUs; if (by != null && by.Length > 0) { MemoryStream srcStream = new MemoryStream(by); stream = new MemoryStream(); if (flvTag.VideoData.FrameType == FrameType.Keyframe) { if (NALUnitHeader != null) { stream.Write(NALUnitHeader, 0, NALUnitHeader.Length); } } using (BinaryReader reader = new BinaryReader(srcStream)) { var sampleSize = srcStream.Length; while (sampleSize > 4L) { var ui32 = reader.ReadUInt32(); var count = OldSkool.swaplong(ui32); stream.Write(h264StartCode, 0, h264StartCode.Length); stream.Write(reader.ReadBytes((int)count), 0, (int)count); sampleSize -= 4 + (uint)count; } } if (stream != null && stream.Length > 0) { IBuffer buffer = stream.ToArray().AsBuffer(); stream.Position = 0; sample = MediaStreamSample.CreateFromBuffer(buffer, TimeSpan.FromTicks(flvTag.Timestamp)); sample.KeyFrame = flvTag.VideoData.FrameType == FrameType.Keyframe; } } } else { IBuffer buffer = flvTag.VideoData.RawData.AsBuffer(); sample = MediaStreamSample.CreateFromBuffer(buffer, TimeSpan.FromTicks(flvTag.Timestamp)); sample.KeyFrame = flvTag.VideoData.FrameType == FrameType.Keyframe; } } else { byte[] by = null; flvTag = flvFile.FlvFileBody.CurrentAudioTag; switch (flvTag.AudioData.SoundFormat) { case SoundFormat.AAC: by = (flvTag.AudioData.SoundData as AACAudioData).RawAACFrameData; break; case SoundFormat.MP3: by = flvTag.AudioData.SoundData.RawData; break; case SoundFormat.ADPCM: by = flvTag.AudioData.SoundData.RawData; break; } if (by != null && by.Length > 0) { stream = new MemoryStream(by); IBuffer buffer = by.AsBuffer(); sample = MediaStreamSample.CreateFromBuffer(buffer, TimeSpan.FromTicks(flvTag.Timestamp)); sample.KeyFrame = true; request.Sample = sample; } } } //샘플보고 request.Sample = sample; } catch (Exception e) { System.Diagnostics.Debug.WriteLine("샘플오류 " + e.Message); sender.NotifyError(MediaStreamSourceErrorStatus.DecodeError); } finally { if (deferal != null) { deferal.Complete(); } } }
private void SetNalUnitParameterSets(FlvTag videoInfoFlvTag) { List <byte[]> sequenceParameterSets = new List <byte[]>(); List <byte[]> pictureParameterSets = new List <byte[]>(); //Video byte[] abyte = videoInfoFlvTag.VideoData.AVCVideoPacket.AVCDecoderConfigurationRecord; using (MemoryStream sm = new MemoryStream(abyte)) { long offset = 0; uint configurationVersion = sm.ReadUInt8(ref offset); uint AVCProfileIndication = sm.ReadUInt8(ref offset); uint profile_compatibility = sm.ReadUInt8(ref offset); uint AVCLevelIndication = sm.ReadUInt8(ref offset); uint t1 = sm.ReadUInt8(ref offset); uint lengthSizeMinusOne = (t1 & 3); uint lengthSizeMinusOnePaddingBits = (t1 >> 2); uint t2 = sm.ReadUInt8(ref offset); uint numberOfSeuqenceParameterSets = (t2 & 7); uint numberOfSequenceParameterSetsPaddingBits = (t2 >> 5); for (int i = 0; i < numberOfSeuqenceParameterSets; i++) { byte[] by = new byte[2]; sm.Read(by, 0, by.Length); Array.Reverse(by); int sequenceParameterSetLength = BitConverter.ToInt16(by, 0); byte[] sequenceParameterSetNALUnit = new byte[sequenceParameterSetLength]; sm.Read(sequenceParameterSetNALUnit, 0, sequenceParameterSetLength); sequenceParameterSets.Add(sequenceParameterSetNALUnit); } offset = sm.Position; uint numberOfPictureParameterSets = sm.ReadUInt8(ref offset); for (int i = 0; i < numberOfPictureParameterSets; i++) { byte[] by = new byte[2]; sm.Read(by, 0, by.Length); Array.Reverse(by); int pictureParameterSetLength = BitConverter.ToInt16(by, 0); byte[] pictureParameterSetNALUnit = new byte[pictureParameterSetLength]; sm.Read(pictureParameterSetNALUnit, 0, pictureParameterSetLength); pictureParameterSets.Add(pictureParameterSetNALUnit); } //NAL Sequence Parameter Set, Picture Parameter Set using (MemoryStream ms = new MemoryStream()) { var sps = sequenceParameterSets[0]; var pps = pictureParameterSets[0]; ms.Write(h264StartCode, 0, h264StartCode.Length); ms.Write(sps, 0, sps.Length); ms.Write(h264StartCode, 0, h264StartCode.Length); ms.Write(pps, 0, pps.Length); NALUnitHeader = ms.ToArray(); } } }
IMediaStreamDescriptor GetFlvAudioDescriptor(FlvTag audioInfoFlvTag) { AudioEncodingProperties audioEncodingProperites = null; AudioStreamDescriptor audioStreamDescriptor = null; uint sampleRate = 0; uint channelCount = 0; uint bitRate = 0; switch (audioInfoFlvTag.AudioData.SoundRate) { case SoundRate._5kHz: sampleRate = 5512; break; case SoundRate._11kHz: sampleRate = 11025; break; case SoundRate._22kHz: sampleRate = 22050; break; case SoundRate._44kHz: sampleRate = 44100; break; } switch (audioInfoFlvTag.AudioData.SoundSize) { case SoundSize.snd8Bit: bitRate = 8; break; case SoundSize.snd16Bit: bitRate = 16; break; } switch (audioInfoFlvTag.AudioData.SoundType) { case SoundType.sndMono: channelCount = 1; break; case SoundType.sndStereo: channelCount = 2; break; } switch (audioInfoFlvTag.AudioData.SoundFormat) { case SoundFormat.AAC: if ((audioInfoFlvTag.AudioData.SoundData as AACAudioData).AudioSpecificConfig != null) { var acfg = (audioInfoFlvTag.AudioData.SoundData as AACAudioData).AudioSpecificConfig; int offset = 0; var type = BitHelper.Read(acfg, ref offset, 5); if (type == 31) { type = BitHelper.Read(acfg, ref offset, 6) + 32; } var feqIndex = BitHelper.Read(acfg, ref offset, 4); if (feqIndex == 15) { sampleRate = (uint)BitHelper.Read(acfg, ref offset, 24); } else { sampleRate = Mp4AudioSpecificConfig.GetSamplingFrequency(feqIndex); } channelCount = (uint)BitHelper.Read(acfg, ref offset, 4); } audioEncodingProperites = AudioEncodingProperties.CreateAac(sampleRate, channelCount, bitRate); break; case SoundFormat.ADPCM: audioEncodingProperites = AudioEncodingProperties.CreatePcm(sampleRate, channelCount, bitRate); break; case SoundFormat.MP3: audioEncodingProperites = AudioEncodingProperties.CreateMp3(sampleRate, channelCount, bitRate); break; default: break; } audioStreamDescriptor = new AudioStreamDescriptor(audioEncodingProperites); return(audioStreamDescriptor); }
internal static FlvTag ReadTag(Stream stream) { try { FlvTag tag; byte[] buffer = new byte[4]; int rtn; rtn = stream.Read(buffer, 0, 4); if (rtn <= 0) { return null; } int type = stream.ReadByte(); if (type == 8) tag = new AudioTag(); else if (type == 9) tag = new VideoTag(); else if (type == 0x12) tag = new ScriptTag(); else tag = new FlvTag(); tag.presize = ByteUtil.ByteToUInt(buffer, 4); tag.tagtype = type; tag.datasize = ByteUtil.ReadUI24(stream); tag.timestamp = ByteUtil.ReadUI24(stream); tag.timestamp_ex = stream.ReadByte(); tag.streamid = ByteUtil.ReadUI24(stream); tag.offset = stream.Position; if (tag is ScriptTag) { (tag as ScriptTag).ReadScript(stream); stream.Seek(tag.offset + tag.DataSize, SeekOrigin.Begin); } else if (tag is AudioTag) { rtn = stream.Read(buffer, 0, 1); if (rtn <= 0) return null; tag.taginfo = buffer[0]; stream.Seek(tag.DataSize - 1, SeekOrigin.Current); } else if (tag is VideoTag) { rtn = stream.Read(buffer, 0, 2); if (rtn <= 0) return null; tag.taginfo = buffer[0]; tag.avcpaktype = buffer[1]; stream.Seek(tag.DataSize - 2, SeekOrigin.Current); } return tag; } catch { return null; } }
internal static FlvTag ReadTag(Stream stream) { try { FlvTag tag; byte[] buffer = new byte[4]; int rtn; rtn = stream.Read(buffer, 0, 4); if (rtn <= 0) { return(null); } int type = stream.ReadByte(); if (type == 8) { tag = new AudioTag(); } else if (type == 9) { tag = new VideoTag(); } else if (type == 0x12) { tag = new ScriptTag(); } else { tag = new FlvTag(); } tag.presize = ByteUtil.ByteToUInt(buffer, 4); tag.tagtype = type; tag.datasize = ByteUtil.ReadUI24(stream); tag.timestamp = ByteUtil.ReadUI24(stream); tag.timestamp_ex = stream.ReadByte(); tag.streamid = ByteUtil.ReadUI24(stream); tag.offset = stream.Position; if (tag is ScriptTag) { (tag as ScriptTag).ReadScript(stream); stream.Seek(tag.offset + tag.DataSize, SeekOrigin.Begin); } else if (tag is AudioTag) { rtn = stream.Read(buffer, 0, 1); if (rtn <= 0) { return(null); } tag.taginfo = buffer[0]; stream.Seek(tag.DataSize - 1, SeekOrigin.Current); } else if (tag is VideoTag) { rtn = stream.Read(buffer, 0, 2); if (rtn <= 0) { return(null); } tag.taginfo = buffer[0]; tag.avcpaktype = buffer[1]; stream.Seek(tag.DataSize - 2, SeekOrigin.Current); } return(tag); } catch { return(null); } }
private int ComputeOffset(Span <FlvTag> span, int index, int audioDiff, int videoDiff) { try { FlvTag beforeVideo = new FlvTag(), afterVideo, beforeAudio = new FlvTag(), afterAudio; bool findA = false, findV = false; if (span[index].TagType == TagType.Audio) { afterAudio = span[index]; int i = 1; do { if ((!span[index + i].Flag.HasFlag(TagFlag.SameAsLastTimestamp)) && span[index + i].TagType == TagType.Video) { afterVideo = span[index + i]; break; } i++; } while (true); } else { afterVideo = span[index]; int i = 1; do { if ((!span[index + i].Flag.HasFlag(TagFlag.SameAsLastTimestamp)) && span[index + i].TagType == TagType.Audio) { afterAudio = span[index + i]; break; } i++; } while (true); } { int i = 1; do { FlvTag curr = span[index - i]; if (!curr.Flag.HasFlag(TagFlag.SameAsLastTimestamp)) { if (!findA && curr.TagType == TagType.Audio) { findA = true; beforeAudio = curr; } else if (!findV && curr.TagType == TagType.Video) { findV = true; beforeVideo = curr; } } i++; } while (!(findA && findV)); } var vtimstamp = beforeVideo.TimeStamp + videoDiff; if (vtimstamp <= beforeAudio.TimeStamp) { vtimstamp = beforeAudio.TimeStamp + 1; } var atimestamp = beforeAudio.TimeStamp + audioDiff; if (atimestamp <= beforeVideo.TimeStamp) { atimestamp = beforeVideo.TimeStamp + 1; } if (atimestamp > vtimstamp) { return(atimestamp - afterAudio.TimeStamp); } else { return(vtimstamp - afterVideo.TimeStamp); } } catch (IndexOutOfRangeException) { Console.WriteLine("请反馈问题:计算偏移量失败,i" + index); return(0); } }
private FlvTag[] ReadAllTagsFromInput(Stream stream) { List <FlvTag> tags = new List <FlvTag>(1800); byte[] b = new byte[4]; do { FlvTag tag = new FlvTag(); // ----------------------------- // if (4 != stream.Read(b, 0, 4)) { break; } // ----------------------------- // tag.Position = stream.Position; tag.TagType = (TagType)stream.ReadByte(); if (tag.TagType != TagType.Audio && tag.TagType != TagType.Video && tag.TagType != TagType.Script) { break; } // ----------------------------- // b[0] = 0; if (3 != stream.Read(b, 1, 3)) { break; } tag.TagSize = BitConverter.ToInt32(b.ToBE(), 0); // ----------------------------- // if (3 != stream.Read(b, 1, 3)) { break; } var temp = stream.ReadByte(); if (temp == -1) { break; } b[0] = (byte)temp; tag.TimeStamp = BitConverter.ToInt32(b.ToBE(), 0); // ----------------------------- // switch (tag.TagType) { case TagType.Audio: { if (4 != stream.Read(b, 0, 4)) { goto break_out; } tag.Flag = stream.ReadByte() == 0 ? TagFlag.Header : TagFlag.None; var totalSkip = tag.TagSize - 2; if (totalSkip != stream.SkipBytes(totalSkip)) { goto break_out; } } break; case TagType.Video: { if (3 != stream.Read(b, 0, 3)) { goto break_out; } if (stream.ReadByte() == 0x17) { tag.Flag |= TagFlag.Keyframe; } switch (stream.ReadByte()) { case 0: tag.Flag |= TagFlag.Header; break; case 2: tag.Flag |= TagFlag.End; break; } var totalSkip = tag.TagSize - 2; if (totalSkip != stream.SkipBytes(totalSkip)) { goto break_out; } } break; default: { var totalSkip = 3 + tag.TagSize; if (totalSkip != stream.SkipBytes(totalSkip)) { goto break_out; } } break; } // ----------------------------- // tags.Add(tag); } while (true); break_out: return(tags.ToArray()); }