⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtmpdecoder.java

📁 MilGra0.8b for java media server
💻 JAVA
字号:
/*   Milenia Grafter Server     Copyright (c) 2007-2008 by Milan Toth. All rights reserved.     This program is free software; you can redistribute it and/or   modify it under the terms of the GNU General Public License   of the License, or (at your option) any later version.     This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.     You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundataion, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.    */ package com.milgra.server.encoder;/**		RtmpDecoder class		@mail milgra@milgra.com	@author Milan Toth	@version 20080316	Tasks of RtmpDecoder			- Deserialize incoming byte stream to rtmp packetBufferA**/import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;import java.util.ArrayList;import com.milgra.server.Library;import com.milgra.server.OProcess;import com.milgra.server.RtmpPacket;import com.milgra.server.SocketController;public class RtmpDecoder extends OProcess{		// read - read count	// next - read amount for next chunk	// nextSize - header size modifiers size register	// chunkSize - actual chunk size for decoder		public int read;	public int next;	public int nextSize = -1;	public int chunkSize = 128;		// header decoding helpers		public int headerFlag;	public int headerSize;	public int headerChannel;		// headerSizes - header size containers	// end - deserialization helper	public byte [ ] headerSizes; 	public boolean end;		// packet buffers	public RtmpPacket [ ] activeBuffer;	public RtmpPacket [ ] packetBufferA;	public RtmpPacket [ ] packetBufferB;		// packet containers	public ArrayList < RtmpPacket > flvList;	public ArrayList < RtmpPacket > dataList;		//		public RtmpPacket packet;	public ByteBuffer buffer;	public SocketChannel socket;	public SocketController controller;						/**	 * RtmpDecoder constructor	 * @param controllerX SocketController	 */		public RtmpDecoder ( SocketController controllerX )	{				// System.out.println( System.currentTimeMillis( ) + " RtmpDecoder.construct" );				// construct				buffer = ByteBuffer.allocate( Library.IOBUFFER );		headerSizes = new byte [ 4 ];				flvList = new ArrayList < RtmpPacket > ( );		dataList = new ArrayList < RtmpPacket > ( );				packetBufferA = new RtmpPacket [ 64 ];		packetBufferB = new RtmpPacket [ 64 ];						// set		controller = controllerX;		activeBuffer = packetBufferA;				// fillup				headerSizes[ 3 ] = 1;		headerSizes[ 2 ] = 4;		headerSizes[ 1 ] = 8;							headerSizes[ 0 ] = 12;		for ( int index = 0 ; index < 64 ; index ++ )		{						packetBufferA[ index ] = new RtmpPacket( );			packetBufferB[ index ] = new RtmpPacket( );			packetBufferA[ index ].rtmpChannel = index;			packetBufferB[ index ].rtmpChannel = index;		}	}		/**	 * Gives flv packets to the given arraylist	 * @param packetsX container for packets	 */		public void giveFlvPackets ( ArrayList < RtmpPacket > packetsX )	{				// System.out.println( System.currentTimeMillis( ) + " RtmpDecoder.giveFlcPackets " + packetBufferAX );				if ( flvList.size( ) > 0 )		{			packetsX.addAll( flvList );			flvList.clear( );		}			}		/**	 * Gives dataa packets to the given arraylist	 * @param packetsX container for packets	 */	public void giveDataPackets ( ArrayList < RtmpPacket > packetsX )	{				// System.out.println( System.currentTimeMillis( ) + " RtmpDecoder.giveDataPackets " + packetsX + " " + dataList.size() );				if ( dataList.size( ) > 0 )		{						packetsX.addAll( dataList );			dataList.clear( );					}			}	/**	 * Fills up buffer for next deserialization	 **/		public void step ( )	{				try		{						read = socket.read( buffer );			controller.bytesIn += read;			// System.out.println( System.currentTimeMillis() + " RtmpDecoder step read: " + read );			if ( read > 0 ) getChunks( ); else 			if ( read == -1 ) controller.close( Library.CLOSURE );				}		catch ( IOException exception ) { controller.close( exception.getMessage( ) ); }			}	/**	 * Deserializes rtmp chunks and creates packet	 * @throws DecodeException at incorrect header sizes	 */		public void getChunks ( )	{				// System.out.println( System.currentTimeMillis() + " " + controller.client.id + " RtmpDecoder.getChunks " + buffer );				buffer.flip( );				do		{						// if a header flag is available			if ( buffer.hasRemaining( ) )			{								// read header flag								headerFlag = buffer.get( );				headerSize = headerSizes[ ( headerFlag & 0xC0 ) >> 6 ];				headerChannel = headerFlag & 0x3F;								// check for page switch								// !!! buffer page flipping is still annoying, has to do something with it								if ( headerChannel == 0 && nextSize == -1 ) 				{										// switch buffer										nextSize = headerSize;					activeBuffer = packetBufferB;				}				else				{									// if we have a nextSize, use that										packet = activeBuffer[ headerChannel ];					if ( nextSize != -1 ) headerSize = nextSize;					// trying to read header										if ( buffer.remaining( ) >= headerSize )					{ 												if ( headerSize > 1 )						{														// extract flv timestamp														packet.flvStamp = buffer.getShort( ) << 8 | buffer.get( ) & 0xFF;													if ( headerSize > 4 )							{																// extract body size and type																packet.bodySize = buffer.getShort( ) << 8 | buffer.get( ) & 0xFF;								packet.bodyType = buffer.get( ) & 0xFF;													if ( headerSize > 8 )								{																		// extract flv channel																		packet.flvChannel = buffer.getInt( );																	}																packet.body = new byte[ packet.bodySize ];								packet.bodyLeft = packet.bodySize;															}													}											// if chunk size is bigger than remaining, use remaining																	next = chunkSize < packet.bodyLeft ? chunkSize : packet.bodyLeft;												// trying to read actual chunk												/* header debug						 						byte [ ] header = new byte[ headerSize ];						buffer.position( buffer.position() - headerSize );						buffer.get( header );												System.out.println( "header : " + Encoder.getHexa( header ) );						System.out.println( "remaining : " + buffer.remaining() + " next: " + next );												//*/												if ( buffer.remaining( ) >= next )						{														// reset nextSize														nextSize = -1;							activeBuffer = packetBufferA;														buffer.get( packet.body , packet.bodySize - packet.bodyLeft , next );							// modify position and remaining														packet.bodyLeft -= next;														// packet is complete								if ( packet.bodyLeft == 0 ) 							{																// packet is chunk size changer																if ( packet.bodyType == 0x01 ) 								{																		chunkSize = Encoder.bytesToInt( packet.body ); 																	}								else								{																		// clone packet																		RtmpPacket newPacket = new RtmpPacket( packet );																		// System.out.println( "packet decode: " + packet );																		switch ( packet.bodyType )									{																			case 0x08 :										case 0x09 : flvList.add( newPacket ); break;										default	  : dataList.add( newPacket ); break;																											}																									}																packet.body = new byte [ packet.bodySize ];								packet.bodyLeft = packet.bodySize;							}												} 						else						{														end = true;							buffer.position( buffer.position( ) - headerSize );													}												// no data for chunk											}					else 					{												end = true;						buffer.position( buffer.position( ) - 1 );											}										// no data for header									}								// go further			}			else end = true;										// no data left in buffer					} 		while ( !end );				end = false;		buffer.compact( );			}	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -