/// <summary> /// actually write a packet to file /// timestamp sequence must be nondecreasing /// </summary> /// <param name="j"></param> void writeActual(JMDPacket j) { if (j.timestamp < timestampoff) { throw new ArithmeticException("JMD Timestamp problem?"); } UInt64 timestampout = j.timestamp - timestampoff; while (timestampout > 0xffffffff) { timestampout -= 0xffffffff; // write timestamp skipper for (int i = 0; i < 6; i++) { f.WriteByte(0xff); } } timestampoff = j.timestamp; writeBE16(j.stream); writeBE32((UInt32)timestampout); f.WriteByte(j.subtype); writeVar((UInt64)j.data.LongLength); f.Write(j.data, 0, j.data.Length); }
/// <summary> /// assemble JMDPacket and send to packetqueue /// </summary> /// <param name="source">zlibed frame with width and height prepended</param> public void AddVideo(byte[] source) { var j = new JMDPacket(); j.stream = 0; j.subtype = 1; // zlib compressed, other possibility is 0 = uncompressed j.data = source; j.timestamp = timestampcalc(fpsnum, fpsden, (UInt64)totalframes); totalframes++; writevideo(j); }
/// <summary> /// add a video packet to the file write queue /// will be written when order-appropriate wrt audio /// the video packets added must be internally ordered (but need not match audio order) /// </summary> /// <param name="j"></param> void writevideo(JMDPacket j) { while (astorage.Count > 0) { var p = astorage.Peek(); if (p.timestamp <= j.timestamp) { writeActual(astorage.Dequeue()); } else { break; } } vstorage.Enqueue(j); }
/// <summary> /// helper function makes a JMDPacket out of one sample pair and adds it to the order queue /// </summary> /// <param name="l">left sample</param> /// <param name="r">right sample</param> void doaudiopacket(short l, short r) { var j = new JMDPacket(); j.stream = 1; j.subtype = 1; // raw PCM audio j.data = new byte[4]; j.data[0] = (byte)(l >> 8); j.data[1] = (byte)(l & 255); j.data[2] = (byte)(r >> 8); j.data[3] = (byte)(r & 255); j.timestamp = timestampcalc(audiosamplerate, 1, totalsamples); totalsamples++; writesound(j); }
/// <summary> /// add a video packet to the file write queue /// will be written when order-appropriate wrt audio /// the video packets added must be internally ordered (but need not match audio order) /// </summary> /// <param name="j"></param> void writevideo(JMDPacket j) { while (astorage.Count > 0) { var p = astorage.Peek(); if (p.timestamp <= j.timestamp) writeActual(astorage.Dequeue()); else break; } vstorage.Enqueue(j); }
/// <summary> /// actually write a packet to file /// timestamp sequence must be nondecreasing /// </summary> /// <param name="j"></param> void writeActual(JMDPacket j) { if (j.timestamp < timestampoff) throw new ArithmeticException("JMD Timestamp problem?"); UInt64 timestampout = j.timestamp - timestampoff; while (timestampout > 0xffffffff) { timestampout -= 0xffffffff; // write timestamp skipper for (int i = 0; i < 6; i++) f.WriteByte(0xff); } timestampoff = j.timestamp; writeBE16(j.stream); writeBE32((UInt32)timestampout); f.WriteByte(j.subtype); writeVar((UInt64)j.data.LongLength); f.Write(j.data, 0, j.data.Length); }