private MediaStreamSample GetAudioSample() { if (aIdx > (aNum - 1)) { // next second abuffer = null; aNum = 0; aIdx = 0; } if (abuffer == null) { int i = -1; //第几秒数据? abuffer = m_demux2.GetCurrentBuffer(curChannelIdx, MediaStreamType.Audio, out i); if (abuffer != null) { if (i == 1) //第一秒数据 { // 因为播放器的timestamp必须从0 开始 atimestamp_base = abuffer.msfHeader.PlayStartTime; } aNum = (int)abuffer.audioBlock.AudioFrameNum; atimestamp_offset = abuffer.msfHeader.PlayStartTime - atimestamp_base; } else { MediaStreamSample sample = new MediaStreamSample(this.audioStreamDescription, null, 0, 0, 0, emptyDict); return(sample); } } MemoryStream stream = new MemoryStream();//abuffer.audioBlock.aFrames[aIdx]._as as MemoryStream; //LATM 封装,第一个字节是length, 跳过第一个字节, 相应的长度应该减1 int len = (int)abuffer.audioBlock.aFrames[aIdx].Length - 1; stream.Write(abuffer.audioBlock.aFrames[aIdx]._data, 1, len); long timestamp = atimestamp_offset + abuffer.audioBlock.aFrames[aIdx].RelativeTime; // 以100 纳秒为单位 MediaStreamSample mediaStreamSample = new MediaStreamSample ( this.audioStreamDescription, stream, 0, len, timestamp, emptyDict ); aIdx++; return(mediaStreamSample); }
private void AdjustTimeStampOf1stSecond(MSF msf) { int ifIdx = msf.videoBlock.FirstIFrameIdx; if (ifIdx == 0) { return; } msf.videoBlock.FirstIFrameIdx = 0; long ts_base = msf.videoBlock.vFrames[ifIdx].RelativeTime; // Remove other non-I frame for (int i = 0; i < ifIdx; i++) { msf.videoBlock.vFrames.RemoveAt(0); } msf.videoBlock.VideoFrameNum = msf.videoBlock.VideoFrameNum - (uint)ifIdx; foreach (var v in msf.videoBlock.vFrames) { v.RelativeTime -= ts_base; } // 处理audio, 使其同步 // 首先查找和Video I 帧大概同步的audio 帧 long offset = msf.audioBlock.aFrames[1].RelativeTime - msf.audioBlock.aFrames[0].RelativeTime; long ts_base_audio = 0; int idx_audio = 0; for (int m = 0; m < msf.audioBlock.AudioFrameNum; m++) { if (Math.Abs(msf.audioBlock.aFrames[m].RelativeTime - ts_base) < offset) { ts_base_audio = msf.audioBlock.aFrames[m].RelativeTime; idx_audio = m; break; } } // remove other frames; for (int i = 0; i < idx_audio; i++) { msf.audioBlock.aFrames.RemoveAt(0); } msf.audioBlock.AudioFrameNum -= (uint)idx_audio; foreach (var v in msf.audioBlock.aFrames) { v.RelativeTime -= ts_base_audio; } }
private void AdjustTimeStampBase(MSF msf, int idx) { if (idx > 0) { msf.msfHeader.PlayStartTime = msf.msfHeader.PlayStartTime - FistTSBase; foreach (var v in msf.audioBlock.aFrames) { v.RelativeTime += msf.msfHeader.PlayStartTime; } foreach (var v in msf.videoBlock.vFrames) { v.RelativeTime += msf.msfHeader.PlayStartTime; } } else if (idx == 0) { long offset = msf.videoBlock.vFrames[1].RelativeTime - msf.videoBlock.vFrames[0].RelativeTime; FistTSBase += msf.videoBlock.vFrames[(int)msf.videoBlock.VideoFrameNum - 1].RelativeTime + offset; FistTSBase += msf.msfHeader.PlayStartTime; msf.msfHeader.PlayStartTime = 0; } }
private void AdjustTimeStampOf1stSecond(MSF msf) { int ifIdx = msf.videoBlock.FirstIFrameIdx; if (ifIdx == 0) return; msf.videoBlock.FirstIFrameIdx = 0; long ts_base = msf.videoBlock.vFrames[ifIdx].RelativeTime; // Remove other non-I frame for (int i = 0; i < ifIdx; i++) { msf.videoBlock.vFrames.RemoveAt(0); } msf.videoBlock.VideoFrameNum = msf.videoBlock.VideoFrameNum - (uint)ifIdx; foreach (var v in msf.videoBlock.vFrames) { v.RelativeTime -= ts_base; } // 处理audio, 使其同步 // 首先查找和Video I 帧大概同步的audio 帧 long offset = msf.audioBlock.aFrames[1].RelativeTime - msf.audioBlock.aFrames[0].RelativeTime; long ts_base_audio = 0; int idx_audio = 0; for (int m = 0; m < msf.audioBlock.AudioFrameNum; m++) { if (Math.Abs(msf.audioBlock.aFrames[m].RelativeTime - ts_base) < offset) { ts_base_audio = msf.audioBlock.aFrames[m].RelativeTime; idx_audio = m; break; } } // remove other frames; for (int i = 0; i < idx_audio; i++) { msf.audioBlock.aFrames.RemoveAt(0); } msf.audioBlock.AudioFrameNum -= (uint)idx_audio; foreach (var v in msf.audioBlock.aFrames) { v.RelativeTime -= ts_base_audio; } }
public bool ParseNALHeader(MSF.VideoBlock vb) { // Need to get the SPS and PPS of the stream, the first frame must be I frame, other frames cannot be played. if (vb.FirstIFrameIdx == -1) return false; //有I帧 byte[] tmp = new byte[32]; byte[] NALStartCode = new byte[] { 0x00, 0x00, 0x01 }; List<byte[]> nals = new List<byte[]>(); Stream s = new MemoryStream(); //vb.vFrames[vb.FirstIFrameIdx]._vs; s.Write(vb.vFrames[vb.FirstIFrameIdx]._data, 0, (int)vb.vFrames[vb.FirstIFrameIdx].Length); s.Seek(0, SeekOrigin.Begin); s.Read(tmp, 0, 3); if (BitTools.FindBytePattern(tmp, NALStartCode) != 0) return false; while (true) { long pos = s.Position; s.Read(tmp, 0, 32); int nextNALidx = BitTools.FindBytePattern(tmp, NALStartCode); if (nextNALidx == -1) break; byte[] nal = new byte[nextNALidx]; BitTools.CopyToBytesArray(tmp, nal, nextNALidx); nals.Add(nal); // rollback pos pos += nextNALidx + 3; //跳过下一个startcode s.Seek(pos, SeekOrigin.Begin); } s.Close(); vb.FirstIFrameInfo = new MSF.VideoBlock.NAL_SPS_PPS_SEI(); foreach (var v in nals) { switch (v[0]) { case 0x67: //SPS http://www.eefocus.com/czzheng/blog/11-09/230262_65ff0.html vb.FirstIFrameInfo.sps = new byte[v.Length - 1]; BitTools.CopyToBytesArray(v, 1, vb.FirstIFrameInfo.sps, v.Length - 1); break; case 0x68: //PPS vb.FirstIFrameInfo.pps = new byte[v.Length - 1]; BitTools.CopyToBytesArray(v, 1, vb.FirstIFrameInfo.pps, v.Length - 1); break; case 0x06: // SEI vb.FirstIFrameInfo.sei = new byte[v.Length - 1]; BitTools.CopyToBytesArray(v, 1, vb.FirstIFrameInfo.sei, v.Length - 1); break; default: break; } } return true; }
private MediaStreamSample GetVideoSample() { if (vIdx == -1) { // the first frame requested,the first frame must be I frame, int i; if (msfVideoBuffer == null) { msfVideoBuffer = this.m_demux2.GetCurrentBuffer(curChannelIdx, MediaStreamType.Video, out i); } vIdx = msfVideoBuffer.videoBlock.FirstIFrameIdx; fNum = (int)msfVideoBuffer.videoBlock.VideoFrameNum; // 因为播放器的timestamp必须从0 开始 timestamp_base = msfVideoBuffer.msfHeader.PlayStartTime + msfVideoBuffer.videoBlock.vFrames[vIdx].RelativeTime; timestamp_offset = msfVideoBuffer.msfHeader.PlayStartTime - timestamp_base; } else if (vIdx > (fNum - 1)) { // next second msfVideoBuffer = null; fNum = 0; vIdx = 0; } if (msfVideoBuffer == null) { int i = -1; //第几秒数据? msfVideoBuffer = m_demux2.GetCurrentBuffer(curChannelIdx, MediaStreamType.Video, out i); if (msfVideoBuffer != null) { fNum = (int)msfVideoBuffer.videoBlock.VideoFrameNum; timestamp_offset = msfVideoBuffer.msfHeader.PlayStartTime - timestamp_base; } else { MediaStreamSample sample = new MediaStreamSample(this.videoStreamDescription, null, 0, 0, 0, emptyDict); return(sample); } } MemoryStream vStream = new MemoryStream();//msfVideoBuffer.videoBlock.vFrames[vIdx]._vs as MemoryStream; int len = (int)msfVideoBuffer.videoBlock.vFrames[vIdx].Length; vStream.Write(msfVideoBuffer.videoBlock.vFrames[vIdx]._data, 0, len); // 以100 纳秒为单位 long timestamp = (timestamp_offset + msfVideoBuffer.videoBlock.vFrames[vIdx].RelativeTime); MediaStreamSample mediaStreamSample = new MediaStreamSample ( this.videoStreamDescription, vStream, 0, len, timestamp, emptyDict ); vIdx++; return(mediaStreamSample); }
private MediaStreamSample GetVideoSample() { if (vIdx == -1) { // the first frame requested,the first frame must be I frame, int i; if (msfVideoBuffer == null) msfVideoBuffer = this.m_demux2.GetCurrentBuffer(curChannelIdx, MediaStreamType.Video, out i); vIdx = msfVideoBuffer.videoBlock.FirstIFrameIdx; fNum = (int)msfVideoBuffer.videoBlock.VideoFrameNum; // 因为播放器的timestamp必须从0 开始 timestamp_base = msfVideoBuffer.msfHeader.PlayStartTime + msfVideoBuffer.videoBlock.vFrames[vIdx].RelativeTime; timestamp_offset = msfVideoBuffer.msfHeader.PlayStartTime - timestamp_base; } else if (vIdx > (fNum - 1)) { // next second msfVideoBuffer = null; fNum = 0; vIdx = 0; } if (msfVideoBuffer == null) { int i = -1; //第几秒数据? msfVideoBuffer = m_demux2.GetCurrentBuffer(curChannelIdx, MediaStreamType.Video, out i); if (msfVideoBuffer != null) { fNum = (int)msfVideoBuffer.videoBlock.VideoFrameNum; timestamp_offset = msfVideoBuffer.msfHeader.PlayStartTime - timestamp_base; } else { MediaStreamSample sample = new MediaStreamSample(this.videoStreamDescription, null, 0, 0, 0, emptyDict); return sample; } } MemoryStream vStream = new MemoryStream();//msfVideoBuffer.videoBlock.vFrames[vIdx]._vs as MemoryStream; int len = (int)msfVideoBuffer.videoBlock.vFrames[vIdx].Length; vStream.Write(msfVideoBuffer.videoBlock.vFrames[vIdx]._data, 0, len); // 以100 纳秒为单位 long timestamp = (timestamp_offset + msfVideoBuffer.videoBlock.vFrames[vIdx].RelativeTime); MediaStreamSample mediaStreamSample = new MediaStreamSample ( this.videoStreamDescription, vStream, 0, len, timestamp, emptyDict ); vIdx++; return mediaStreamSample; }
private MediaStreamSample GetAudioSample() { if (aIdx > (aNum - 1)) { // next second abuffer = null; aNum = 0; aIdx = 0; } if (abuffer == null) { int i = -1; //第几秒数据? abuffer = m_demux2.GetCurrentBuffer(curChannelIdx, MediaStreamType.Audio, out i); if (abuffer != null) { if (i == 1) //第一秒数据 { // 因为播放器的timestamp必须从0 开始 atimestamp_base = abuffer.msfHeader.PlayStartTime; } aNum = (int)abuffer.audioBlock.AudioFrameNum; atimestamp_offset = abuffer.msfHeader.PlayStartTime - atimestamp_base; } else { MediaStreamSample sample = new MediaStreamSample(this.audioStreamDescription, null, 0, 0, 0, emptyDict); return sample; } } MemoryStream stream = new MemoryStream();//abuffer.audioBlock.aFrames[aIdx]._as as MemoryStream; //LATM 封装,第一个字节是length, 跳过第一个字节, 相应的长度应该减1 int len = (int)abuffer.audioBlock.aFrames[aIdx].Length - 1; stream.Write(abuffer.audioBlock.aFrames[aIdx]._data, 1, len); long timestamp = atimestamp_offset + abuffer.audioBlock.aFrames[aIdx].RelativeTime; // 以100 纳秒为单位 MediaStreamSample mediaStreamSample = new MediaStreamSample ( this.audioStreamDescription, stream, 0, len, timestamp, emptyDict ); aIdx++; return mediaStreamSample; }