/* * myLib - https://github.com/taktod/myLib * Copyright (c) 2014 ttProject. All rights reserved. * * Licensed under The MIT license. */ package com.ttProject.media.h264; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import com.ttProject.media.h264.frame.PictureParameterSet; import com.ttProject.media.h264.frame.SequenceParameterSet; import com.ttProject.nio.channels.IReadChannel; import com.ttProject.util.BufferUtil; /** * flvのmediaSequenceHeaderやmp4のdecodeBox(Avcc)の内容から、 * nalデータを取り出す動作 * 01 4D 40 1E FF E1 00 19 67 4D 40 1E 92 42 01 40 5F F2 E0 22 00 00 03 00 C8 00 00 2E D5 1E 2C 5C 90 01 00 04 68 EE 32 C8 * [] avcC version 1 * [ ] profile compatibility level * [] 111111 + 2bit nal size - 1(ff固定とおもっててOKでしょう) * [] number of SPS e1固定? * [ ] spsLength * [spsNalデータ ] * [] number of PPS * [ ] ppsLength * [ ] ppsData * もしくはnalデータからconfigDataを作り出す動作 * @author taktod */ public class ConfigData { /** * spsとppsを取り出す。 * @return */ public List<Frame> getNals(IReadChannel channel) throws Exception { FrameAnalyzer analyzer = new FrameAnalyzer(); List<Frame> list = new ArrayList<Frame>(); if(channel.size() - channel.position() < 8) { throw new Exception("先頭データの読み込み部のサイズが小さすぎます。"); } ByteBuffer buffer = BufferUtil.safeRead(channel, 6); if(buffer.get() != 0x01) { throw new Exception("avccVersionが1ではないです。"); } // spsのサイズを調べておく。 short spsSize = BufferUtil.safeRead(channel, 2).getShort(); // spsデータ本体 Frame sps = analyzer.analyze(channel); if(!(sps instanceof SequenceParameterSet)) { throw new Exception("取得データがspsではありませんでした。"); } sps.setSize(spsSize); sps.analyze(channel); list.add(sps); // numberOfPPS buffer = BufferUtil.safeRead(channel, 1); short ppsSize = BufferUtil.safeRead(channel, 2).getShort(); Frame pps = analyzer.analyze(channel); if(!(pps instanceof PictureParameterSet)) { throw new Exception("取得データがppsではありませんでした。"); } pps.setSize(ppsSize); pps.analyze(channel); list.add(pps); return list; } public ByteBuffer makeConfigData(SequenceParameterSet sps, PictureParameterSet pps) throws Exception { ByteBuffer spsBuffer = sps.getData(); ByteBuffer ppsBuffer = pps.getData(); ByteBuffer data = ByteBuffer.allocate(11 + spsBuffer.remaining() + ppsBuffer.remaining()); data.put((byte)1); spsBuffer.position(1); data.put(spsBuffer.get()); data.put(spsBuffer.get()); data.put(spsBuffer.get()); spsBuffer.position(0); data.put((byte)0xFF); data.put((byte)0xE1); data.putShort((short)spsBuffer.remaining()); data.put(spsBuffer); data.put((byte)1); data.putShort((short)ppsBuffer.remaining()); data.put(ppsBuffer); data.flip(); return data; } }