public void write(AVStream av, AVPacket frame) throws IOException { tryWriteHeader(av); Format vf = frame.getFormat(); if (Constants.H264.equalsIgnoreCase(vf.getEncoding())) { writeH264WithStartCode(frame); return; } else if (Constants.AAC.equalsIgnoreCase(vf.getEncoding())) { writeAAC(frame); return; } logger.warn("unsupported format {}", frame.getFormat()); }
private void writeAAC(AVPacket frame) throws IOException { ByteBuffer data = frame.getByteBuffer(); int dataSize = 2 + data.remaining(); ChannelBuffer aac = ChannelBuffers.buffer(11 + dataSize + 4); aac.writeByte(0x08); aac.writeMedium(dataSize); // timestamp long timestamp = frame.getTimestamp(AVTimeUnit.MILLISECONDS); aac.writeMedium((int) (0xFFFFFF & timestamp)); aac.writeByte((int) (0xFF & (timestamp >> 24))); aac.writeMedium(0); aac.writeByte(0xAF); // aac, 44100, 2 channels, stereo aac.writeByte(0x01); // aac data aac.writeBytes(data); aac.writeInt(aac.readableBytes()); // pre tag size aac.readBytes(out, aac.readableBytes()); }
private void writeH264WithStartCode(AVPacket frame) throws IOException { ByteBuffer data = frame.getByteBuffer(); if (data.remaining() > 4 && 1 != data.getInt(data.position())) { logger.warn("H264 Not Start With 0x00 00 00 01"); return; } List<ByteBuffer> segs = H264Utils.splitFrame(data); int dataSize = 5 + 4 * segs.size(); for (ByteBuffer seg : segs) { dataSize += seg.remaining(); } ChannelBuffer avc = ChannelBuffers.buffer(11 + dataSize + 4 + 4 + 5); avc.writeByte(0x09); // video type avc.writeMedium(dataSize); // tag data size // timestamp long timestamp = frame.getTimestamp(AVTimeUnit.MILLISECONDS); avc.writeMedium((int) (0xFFFFFF & timestamp)); avc.writeByte((int) (0xFF & (timestamp >> 24))); avc.writeMedium(0x0); // stream id avc.writeByte(frame.isKeyFrame() ? 0x17 : 0x27); // key frame + avc avc.writeByte(0x01); // avc NAL avc.writeMedium( (int) frame.getCompositionTime(AVTimeUnit.MILLISECONDS)); // Composition time offset // data for (ByteBuffer seg : segs) { avc.writeInt(seg.remaining()); avc.writeBytes(seg); } avc.writeInt(avc.readableBytes()); // pre tag size avc.readBytes(out, avc.readableBytes()); }