/* * myLib - https://github.com/taktod/myLib * Copyright (c) 2014 ttProject. All rights reserved. * * Licensed under GNU LESSER GENERAL PUBLIC LICENSE Version 3. */ package com.ttProject.flazr.rtmp.message; import java.nio.ByteBuffer; import java.util.List; import java.util.ArrayList; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.flazr.amf.Amf0Object; import com.flazr.rtmp.RtmpHeader; import com.flazr.rtmp.RtmpMessage; import com.flazr.rtmp.message.CommandAmf0; import com.flazr.rtmp.message.MessageType; import com.ttProject.container.flv.amf.Amf0Value; import com.ttProject.flazr.unit.Amf0ObjectManager; import com.ttProject.nio.channels.ByteReadChannel; import com.ttProject.nio.channels.IReadChannel; import com.ttProject.util.BufferUtil; /** * CommandAmf3 * * @author taktod */ public class CommandAmf3 implements RtmpMessage { private static final Logger logger = LoggerFactory.getLogger(CommandAmf3.class); private final RtmpHeader header; private String name; private Integer transactionId; private Object object; private Object[] args; private ChannelBuffer resBuffer = null; private final Amf0ObjectManager amf0ObjectManager = new Amf0ObjectManager(); /** * constructor * @param header * @param in */ public CommandAmf3(RtmpHeader header, ChannelBuffer in) { this.header = header; decode(in); } /** * constructor * @param amf0 */ public CommandAmf3(CommandAmf0 amf0) { this.header = amf0.getHeader(); header.setMessageType(MessageType.COMMAND_AMF3); ByteBuffer data = amf0.encode().toByteBuffer(); ChannelBuffer buffer = ChannelBuffers.buffer(data.remaining() + 1); buffer.writeByte((byte)0x00); buffer.writeBytes(data); resBuffer = buffer; } /** * {@inheritDoc} */ @Override public void decode(ChannelBuffer in) { int length = in.readableBytes(); byte[] bytes = new byte[length]; in.readBytes(bytes); try { IReadChannel channel = new ByteReadChannel(bytes); // check the first byte, if 0x00 do amf0, if 0x11 do amf3. switch(BufferUtil.safeRead(channel, 1).get()) { case 0x00: name = (String)Amf0Value.getValueObject(channel); transactionId = ((Double)Amf0Value.getValueObject(channel)).intValue(); object = Amf0Value.getValueObject(channel); List<Object> list = new ArrayList<Object>(); while(channel.size() > channel.position()) { list.add(Amf0Value.getValueObject(channel)); } args = list.toArray(); break; case 0x11: throw new Exception("unexpect data is comming. taktod wanna sample for this case. please contact me."); } } catch(Exception e) { logger.error("failed to parse data.", e); } } @Override public ChannelBuffer encode() { if(resBuffer == null) { throw new RuntimeException("encode is not supported now."); } return resBuffer; } @Override public RtmpHeader getHeader() { return header; } public String getName() { return name; } public Integer getTransactionId() { return transactionId; } public Object getObject() { return object; } public Object getArg(int index) { return args[index]; } public int getArgCount() { if(args == null) { return 0; } return args.length; } public CommandAmf0 transform() { if(object == null || object instanceof com.ttProject.container.flv.amf.Amf0Object) { CommandAmf0 command0 = new CommandAmf0(transactionId, name, (Amf0Object)amf0ObjectManager.toFlazrObject(object), args); return command0; } throw new RuntimeException("base object is not amf0Object."); } }