/// <summary> /// Terminates the encoding process and closes the output and live streams. /// </summary> /// <returns>True if the encoding completed succesfully. False if it wasn't encoding in the first place.</returns> public bool EndEncode() { if (!encodeInProgress) { return(false); } System.GC.Collect(); //if streaming live if (streamLive) { client.disconnect(); streamLive = false; } //if streaming to file if (streamFile) { output.Close(); streamFile = false; } //stop the timer timer.Stop(); this.encodeInProgress = false; //reset the current FLVTag this.tag = null; return(true); }
/// <summary> /// Sends the flv tag to the RTMP server. /// </summary> /// <param name="tagData"></param> /// <param name="tag"></param> public override bool sendFLVTag(byte[] tagData, FLVTag tag) { if (!isConnected) { return(false); } outputBuff.Position = 0; chunkBuff.Position = 0; AMFHeader header = new AMFHeader(AMFHeader.HEADER_12, 0x8); header.RTMPType = AMFHeader.RTMP_TYPE_VIDEO; header.TimeStamp = tag.TimeStamp; header.EndPoint = 0x00000001; header.BodySize = tag.getTagSizeInBytes() - 11; //write the header to teh chunkbuffer header.writeHeader(chunkBuff); //the size remaining in the data buffer int size = tag.getTagSizeInBytes() - 11; //the position in the data buffer (from which to start sending bytes) int position = 0; //write the header to the chunk buffer header.writeHeader(chunkBuff); //copy <= 128 bytes from the tagData into the chunk buffer to send. Array.Copy(tagData, 11, chunk_buffer, header.getHeaderSize(), size > 128 ? 128 : size); //send the first packet of information connectionSocket.Send(chunk_buffer, (header.getHeaderSize() + (size > 128 ? 128 : size)), SocketFlags.None); size -= 128; position += 128 + 11; //while there is still bytes while (size > 0) { //add a header byte byte t = tagData[position - 1]; tagData[position - 1] = header.get_1_HeaderByte(); //send out the data connectionSocket.Send(tagData, position - 1, size > 128 ? 129 : size + 1, SocketFlags.None); //restore where the header was tagData[position - 1] = t; position += 128; size -= 128; } return(true); }
public override bool sendFLVTag(byte[] buffer, FLVTag tag) { //throw new Exception("The method or operation is not implemented."); return true; }
public abstract bool sendFLVTag(byte[] buffer, FLVTag tag);
/// <summary> /// Sends the flv tag to the RTMP server. /// </summary> /// <param name="tagData"></param> /// <param name="tag"></param> public override bool sendFLVTag(byte[] tagData, FLVTag tag) { if (!isConnected) return false; outputBuff.Position = 0; chunkBuff.Position = 0; AMFHeader header = new AMFHeader(AMFHeader.HEADER_12, 0x8); header.RTMPType = AMFHeader.RTMP_TYPE_VIDEO; header.TimeStamp = tag.TimeStamp; header.EndPoint = 0x00000001; header.BodySize = tag.getTagSizeInBytes() - 11; //write the header to teh chunkbuffer header.writeHeader(chunkBuff); //the size remaining in the data buffer int size = tag.getTagSizeInBytes() - 11; //the position in the data buffer (from which to start sending bytes) int position = 0; //write the header to the chunk buffer header.writeHeader(chunkBuff); //copy <= 128 bytes from the tagData into the chunk buffer to send. Array.Copy(tagData, 11, chunk_buffer, header.getHeaderSize(), size > 128 ? 128 : size); //send the first packet of information connectionSocket.Send(chunk_buffer, (header.getHeaderSize() + (size > 128 ? 128 : size)), SocketFlags.None); size -= 128; position += 128 + 11; //while there is still bytes while (size > 0) { //add a header byte byte t = tagData[position - 1]; tagData[position - 1] = header.get_1_HeaderByte(); //send out the data connectionSocket.Send(tagData, position - 1, size > 128 ? 129 : size + 1, SocketFlags.None); //restore where the header was tagData[position - 1] = t; position += 128; size -= 128; } return true; }
/// <summary> /// Appends another frame / or tag to the current FLV file. Instead of using /// built in timing mechanisms within the class itself, a timestamp value /// can be used to override the "pre calculated" time stamp. /// </summary> /// <param name="frame">A raw array of pixel data to encode.</param> /// <param name="timestamp">The time at which this frame will apply.</param> /// <returns>The time in ms to encode the frame, or -1 if an error occured.</returns> public double EncodeFrame(byte[] frame, long timestamp) { if ((!streamFile && !streamLive) && !encodeInProgress) { return(-1); } //make sure the buffer represents the "supposed" video dimensions //if its too small, return an error if (frame.Length < par.VideoHeight * par.VideoWidth * par.SourceBytesPerPixel) { return(-1); } //record the time at the "start" of encoding of this frame double start = timer.Duration; //reset the buffer memoryStream.Position = 0; bool isKeyFrame = false; //determine whether or not to send a key frame if (frameCount == 0) //if this is the first frame { isKeyFrame = true; } //if the duration has passed the frame frequency if (timestamp - lastKeyFrameTime > par.KeyFrameFrequency * 1000) { isKeyFrame = true; lastKeyFrameTime = (int)timestamp; System.GC.Collect(); } //set up the new tag tag = new FLVTag(FLVTag.TAGTYPE_VIDEO, frame, this.previousFrame, (frameCount > 0) ? (int)timestamp : 0, par.VideoWidth, par.VideoHeight, srcBlockBuffer, destBlockBuffer, isKeyFrame, par.CompressionLevel, par.SourceBytesPerPixel); //write the tag to the inmemory buffer (faster seeks) tag.writeTag(memoryStream); //get the size of the tag int tagSize = tag.getTagSizeInBytes(); //write the tag in memory out to file //and only if information is changed (no point writing an empty frame and //wasting space) if (tag.isFrameDirty()) { if (streamFile) { output.Write(buffer, 0, (int)memoryStream.Position); this.output.WriteByte((byte)(tagSize >> 24)); this.output.WriteByte((byte)(tagSize >> 16)); this.output.WriteByte((byte)(tagSize >> 8)); this.output.WriteByte((byte)(tagSize)); this.output.Flush(); } if (streamLive) { try { client.sendFLVTag(buffer, tag); //dont need the size } catch (Exception e) { this.streamLive = false; throw e; } } } //increment the frame counter frameCount++; //store the frame for comparison this.previousFrame = frame; //store the timestamp of this encoded frame this.lastTimeStamp = timestamp; //return the duration of of the this frame's encode time return(timer.Duration - start); }
public abstract bool sendFLVTag(byte[] buffer, FLVTag tag);
public override bool sendFLVTag(byte[] buffer, FLVTag tag) { //throw new Exception("The method or operation is not implemented."); return(true); }
/// <summary> /// Appends another frame / or tag to the current FLV file. Instead of using /// built in timing mechanisms within the class itself, a timestamp value /// can be used to override the "pre calculated" time stamp. /// </summary> /// <param name="frame">A raw array of pixel data to encode.</param> /// <param name="timestamp">The time at which this frame will apply.</param> /// <returns>The time in ms to encode the frame, or -1 if an error occured.</returns> public double EncodeFrame(byte[] frame, long timestamp) { if ((!streamFile && !streamLive) && !encodeInProgress) { return -1; } //make sure the buffer represents the "supposed" video dimensions //if its too small, return an error if (frame.Length < par.VideoHeight * par.VideoWidth * par.SourceBytesPerPixel) { return -1; } //record the time at the "start" of encoding of this frame double start = timer.Duration; //reset the buffer memoryStream.Position = 0; bool isKeyFrame = false; //determine whether or not to send a key frame if (frameCount == 0) //if this is the first frame isKeyFrame = true; //if the duration has passed the frame frequency if (timestamp - lastKeyFrameTime > par.KeyFrameFrequency * 1000) { isKeyFrame = true; lastKeyFrameTime = (int)timestamp; System.GC.Collect(); } //set up the new tag tag = new FLVTag(FLVTag.TAGTYPE_VIDEO, frame, this.previousFrame, (frameCount > 0) ? (int)timestamp : 0, par.VideoWidth, par.VideoHeight, srcBlockBuffer, destBlockBuffer, isKeyFrame, par.CompressionLevel, par.SourceBytesPerPixel); //write the tag to the inmemory buffer (faster seeks) tag.writeTag(memoryStream); //get the size of the tag int tagSize = tag.getTagSizeInBytes(); //write the tag in memory out to file //and only if information is changed (no point writing an empty frame and //wasting space) if (tag.isFrameDirty()) { if (streamFile) { output.Write(buffer, 0, (int)memoryStream.Position); this.output.WriteByte((byte)(tagSize >> 24)); this.output.WriteByte((byte)(tagSize >> 16)); this.output.WriteByte((byte)(tagSize >> 8)); this.output.WriteByte((byte)(tagSize)); this.output.Flush(); } if (streamLive) { try { client.sendFLVTag(buffer, tag); //dont need the size } catch (Exception e) { this.streamLive = false; throw e; } } } //increment the frame counter frameCount++; //store the frame for comparison this.previousFrame = frame; //store the timestamp of this encoded frame this.lastTimeStamp = timestamp; //return the duration of of the this frame's encode time return timer.Duration - start; }
/// <summary> /// Terminates the encoding process and closes the output and live streams. /// </summary> /// <returns>True if the encoding completed succesfully. False if it wasn't encoding in the first place.</returns> public bool EndEncode() { if (!encodeInProgress) return false; System.GC.Collect(); //if streaming live if (streamLive) { client.disconnect(); streamLive = false; } //if streaming to file if (streamFile) { output.Close(); streamFile = false; } //stop the timer timer.Stop(); this.encodeInProgress = false; //reset the current FLVTag this.tag = null; return true; }