| | |
| | | package cn.org.hentai.jtt1078.util; |
| | | |
| | | import cn.org.hentai.jtt1078.flv.AudioTag; |
| | | import io.netty.buffer.ByteBuf; |
| | | import io.netty.buffer.Unpooled; |
| | | |
| | | /** |
| | | * Created by matrixy on 2017/8/22. |
| | | */ |
| | | public final class ByteUtils |
| | | { |
| | | public static String toHexString(byte[] bytes, int offset, int length) { |
| | | StringBuilder sb = new StringBuilder(length * 3); |
| | | for (int i = offset; i < offset + length && i < bytes.length; i++) { |
| | | sb.append(String.format("%02X ", bytes[i])); |
| | | } |
| | | return sb.toString().trim(); |
| | | } |
| | | |
| | | public static byte[] parse(String hexString) |
| | | { |
| | | String[] hexes = hexString.split(" "); |
| | |
| | | } |
| | | return dst; |
| | | } |
| | | |
| | | public static String toHexString(byte[] bytes, int offset, int length) { |
| | | StringBuilder sb = new StringBuilder(length * 3); |
| | | for (int i = offset; i < offset + length && i < bytes.length; i++) { |
| | | sb.append(String.format("%02X ", bytes[i])); |
| | | } |
| | | return sb.toString().trim(); |
| | | } |
| | | |
| | | // 可选:打印整个数组 |
| | | public static String toHexString(byte[] bytes) { |
| | | return toHexString(bytes, 0, bytes.length); |
| | | } |
| | | |
| | | public static int getShort(byte[] bytes, int offset) { |
| | | return ((bytes[offset] & 0xFF) << 8) | (bytes[offset + 1] & 0xFF); |
| | | } |
| | | public static long getLong(byte[] bytes, int offset) { |
| | | return ((long)(bytes[offset] & 0xFF) << 56) | |
| | | ((long)(bytes[offset + 1] & 0xFF) << 48) | |
| | | ((long)(bytes[offset + 2] & 0xFF) << 40) | |
| | | ((long)(bytes[offset + 3] & 0xFF) << 32) | |
| | | ((long)(bytes[offset + 4] & 0xFF) << 24) | |
| | | ((long)(bytes[offset + 5] & 0xFF) << 16) | |
| | | ((long)(bytes[offset + 6] & 0xFF) << 8) | |
| | | ((long)(bytes[offset + 7] & 0xFF)); |
| | | } |
| | | |
| | | /** |
| | | * Flv 音频封装编码 |
| | | * |
| | | * @param audioTag 音频tag |
| | | * @return 字节流 |
| | | * @author xingkong |
| | | * @date 2021-09-07 17:02 |
| | | */ |
| | | public static ByteBuf encode(AudioTag audioTag) throws Exception { |
| | | ByteBuf buffer = Unpooled.buffer(); |
| | | if (audioTag == null) { |
| | | return buffer; |
| | | } |
| | | //----------------------tag header begin------- |
| | | buffer.writeByte(8); |
| | | buffer.writeMedium(audioTag.getTagDataSize()); |
| | | buffer.writeMedium(audioTag.getOffSetTimestamp() & 0xFFFFFF); |
| | | buffer.writeByte(audioTag.getOffSetTimestamp() >> 24); |
| | | buffer.writeMedium(audioTag.getStreamId()); |
| | | //---------------------tag header length 11--------- |
| | | //---------------------tag header end---------------- |
| | | byte formatAndRateAndSize = (byte) (audioTag.getFormat() << 4 | audioTag.getRate() << 2 | audioTag.getSize() << 1 | audioTag.getType()); |
| | | //-------------data begin------- |
| | | buffer.writeByte(formatAndRateAndSize); |
| | | buffer.writeBytes(audioTag.getData()); |
| | | //-------------data end ------- |
| | | //应该等于11+tagDataSize |
| | | buffer.writeInt(buffer.writerIndex()); |
| | | return buffer; |
| | | } |
| | | |
| | | /** |
| | | * 读取bytebuf剩下的字节 |
| | | * |
| | | * @param msg 可读取bytebuf |
| | | * @return 剩下所有的字节 |
| | | * @author xingkong |
| | | * @date 2021-09-07 16:15 |
| | | */ |
| | | public static byte[] readReadableBytes(ByteBuf msg) { |
| | | byte[] content = new byte[msg.readableBytes()]; |
| | | msg.readBytes(content); |
| | | msg.release(); |
| | | return content; |
| | | } |
| | | /** |
| | | * 转换数据 转换为我们需要的报文形式 |
| | | * |
| | | * @param data 带转换的报文 |
| | | * @return 转换好的报文 |
| | | * @author xingkong |
| | | * @date 2021/9/8 |
| | | */ |
| | | public static byte[] make(byte[] data) { |
| | | ByteBuf buffer = Unpooled.buffer(); |
| | | buffer.writeBytes(String.format("%x\r\n", data.length).getBytes()); |
| | | buffer.writeBytes(data); |
| | | buffer.writeByte((byte) '\r'); |
| | | buffer.writeByte((byte) '\n'); |
| | | return readReadableBytes(buffer); |
| | | } |
| | | |
| | | |
| | | } |