RTMP学习笔记(五)AMF0数据解析

298 阅读1分钟

欢迎关注公众号:冒泡的肥皂

image.png

AMF0的数据类型是前两位。所以首先解析数据类型,然后根据数据类型的格式进行数据读取

数据类型可以在上篇文件查看

部分类型解析

public static Object decode(final ByteBuf in) {
                //读取数据类型
		final Type type = Type.valueToEnum(in.readByte());
		final Object value = decode(in, type);
		log.info("<< " + toString(type, value));
		return value;
	}
        
private static Object decode(final ByteBuf in, final Type type) {
	switch (type) {
	case NUMBER://0x00
		return Double.longBitsToDouble(in.readLong());
	case BOOLEAN://0x01
		return in.readByte() == BOOLEAN_TRUE;
	case STRING://0x02
		return decodeString(in);
        case OBJECT://0x03
		final int count=0;
		final Map<String, Object> map=new Amf0Object();
		int i = 0;
		final byte[] endMarker = new byte[3];
		while (in.isReadable()) {
			in.getBytes(in.readerIndex(), endMarker);
			if (Arrays.equals(endMarker, OBJECT_END_MARKER)) {
				in.skipBytes(3);
				log.debug("end MAP / OBJECT, found object end marker [000009]");
				break;
			}
			if (count > 0 && i++ == count) {
				log.debug("stopping map decode after reaching count: {}", count);
				break;
			}
			map.put(decodeString(in), decode(in));
		}
		return map;        
       case NULL://0x05
                return null;
       case UNDEFINED://0x06
               return null;
       case MAP://0x08 
                final int count = in.readInt(); // should always be 0
		final Map<String, Object> map = new LinkedHashMap<String, Object>();
		int i = 0;
		final byte[] endMarker = new byte[3];
		while (in.isReadable()) {
			in.getBytes(in.readerIndex(), endMarker);
			if (Arrays.equals(endMarker, OBJECT_END_MARKER)) {
				in.skipBytes(3);
				log.debug("end MAP / OBJECT, found object end marker [000009]");
				break;
			}
			if (count > 0 && i++ == count) {
				log.debug("stopping map decode after reaching count: {}", count);
				break;
			}
			map.put(decodeString(in), decode(in));
		}
		return map;
	case ARRAY://0x0a
		final int arraySize = in.readInt();
		final Object[] array = new Object[arraySize];
		for (int i = 0; i < arraySize; i++) {
			array[i] = decode(in);
		}
		return array;

	
	case DATE://0x0b
		final long dateValue = in.readLong();
		in.readShort(); // consume the timezone
		return new Date((long) Double.longBitsToDouble(dateValue));
	case LONG_STRING://0x0c 大小4字节
		final int stringSize = in.readInt();
		final byte[] bytes = new byte[stringSize];
		in.readBytes(bytes);
		return new String(bytes); // UTF-8 ?
	case UNSUPPORTED://0x0d
		return null;
        case AMF_INVALID://0xff
                return null;
	default:
		throw new RuntimeException("AMF0数据解码类型不支持: " + type);
	}
}        
        //string类型解析 大小 2字节
   	private static String decodeString(final ByteBuf in) {
		final short size = in.readShort();
		final byte[] bytes = new byte[size];
		in.readBytes(bytes);
		return new String(bytes); // should we force encode to UTF-8 ?
	}