Skip to content

Commit

Permalink
Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo4405 committed Dec 3, 2016
1 parent 44e2128 commit a0702af
Show file tree
Hide file tree
Showing 20 changed files with 150 additions and 60 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
.gradle
build
*.jar
1 change: 1 addition & 0 deletions app/app.iml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="support-annotations-23.4.0" level="project" />
<orderEntry type="library" exported="" name="commons-io-2.5" level="project" />
<orderEntry type="library" exported="" name="animated-vector-drawable-23.4.0" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="hamcrest-core-1.3" level="project" />
<orderEntry type="library" exported="" name="commons-lang3-3.4" level="project" />
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.4'
compile group: 'commons-io', name: 'commons-io', version: '2.5'
compile 'org.jetbrains:annotations-java5:15.0'
}

Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/com/haishinkit/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ protected void onCreate(Bundle savedInstanceState) {
stream = new RTMPStream(connection);

cameraView = new CameraView(this);
stream.attachCamera(cameraView.getCamera());
setContentView(cameraView);

connection.connect("rtmp:https://192.168.179.3/live");
//stream.attachCamera(cameraView.getCamera());
stream.publish("live");
}
}
3 changes: 3 additions & 0 deletions app/src/main/java/com/haishinkit/amf/AMF0Serializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ public AMF0Serializer putObject(final Object value) {
if (value instanceof Integer) {
return putDouble(((Integer) value).doubleValue());
}
if (value instanceof Short) {
return putDouble(((Short) value).doubleValue());
}
if (value instanceof Boolean) {
return putBoolean((Boolean) value);
}
Expand Down
16 changes: 7 additions & 9 deletions app/src/main/java/com/haishinkit/iso/AVCConfigurationRecord.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package com.haishinkit.iso;

import android.media.MediaFormat;

import com.haishinkit.util.ByteBufferUtils;
import com.haishinkit.util.Log;

import org.apache.commons.lang3.builder.ToStringBuilder;

import java.nio.ByteBuffer;
Expand Down Expand Up @@ -160,15 +156,15 @@ public byte getNALULength() {
}

public ByteBuffer toByteBuffer() {
int capacity = 5 + 2;
int capacity = 5;
List<byte[]> sequenceParameterSets = getSequenceParameterSets();
List<byte[]> pictureParameterSets = getPictureParameterSets();

for (int i = 0; i < sequenceParameterSets.size(); ++i) {
capacity += 3;
for (byte[] sps : sequenceParameterSets) {
capacity += 3 + sps.length;
}
for (int i = 0; i < pictureParameterSets.size(); ++i) {
capacity += 3;
for (byte[] psp : pictureParameterSets) {
capacity += 3 + psp.length;
}

ByteBuffer buffer = ByteBuffer.allocate(capacity);
Expand All @@ -194,6 +190,8 @@ public ByteBuffer toByteBuffer() {
buffer.put(pps);
}

buffer.flip();

return buffer;
}

Expand Down
34 changes: 34 additions & 0 deletions app/src/main/java/com/haishinkit/iso/AVCFormatUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.haishinkit.iso;

import com.haishinkit.util.Log;

import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.Arrays;

public final class AVCFormatUtils {
private AVCFormatUtils() {
}

public final static ByteBuffer toNALFileFormat(final ByteBuffer buffer) {
ByteBuffer result = ByteBuffer.allocate(buffer.remaining());
result.put(buffer);
result.flip();
int length = 0;
int position = -1;
int remaining = result.remaining() - 3;
for (int i = 0; i < remaining; ++i) {
if (result.get(i) == 0x00 && result.get(i + 1) == 0x00 && result.get(i + 2) == 0x00 && result.get(i + 3) == 0x01) {
if (0 <= position) {
result.putInt(position, length - 3);
}
position = i;
length = 0;
} else {
++length;
}
}
result.putInt(position, length);
return result;
}
}
10 changes: 7 additions & 3 deletions app/src/main/java/com/haishinkit/media/EncoderBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import android.media.MediaCodec;

import com.haishinkit.util.Log;

import org.apache.commons.lang3.builder.ToStringBuilder;

import java.nio.ByteBuffer;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
Expand Down Expand Up @@ -52,7 +56,7 @@ public final void stopRunning() {
running.set(false);
}

public synchronized final void encodeBytes(byte[] data) {
public synchronized final void encodeBytes(byte[] data, long presentationTimeUs) {
if (!running.get()) {
return;
}
Expand All @@ -66,7 +70,7 @@ public synchronized final void encodeBytes(byte[] data) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(data);
codec.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0);
codec.queueInputBuffer(inputBufferIndex, 0, data.length, presentationTimeUs, 0);
}

int outputBufferIndex = 0;
Expand Down Expand Up @@ -98,7 +102,7 @@ public synchronized final void encodeBytes(byte[] data) {
}
} while (0 <= outputBufferIndex);
} catch (Exception e) {
e.printStackTrace();
Log.w(getClass().getName(), e.toString());
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/haishinkit/media/H264Encoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ protected MediaCodec createMediaCodec() throws IOException {
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);
codec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
return codec;
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/haishinkit/media/IEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
public interface IEncoder extends IRunnable {
public IEncoderListener getListener();
public IEncoder setListener(final IEncoderListener listener);
public void encodeBytes(byte[] data);
public void encodeBytes(byte[] data, long presentationTimeUs);
}
19 changes: 11 additions & 8 deletions app/src/main/java/com/haishinkit/net/Socket.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.haishinkit.util.Log;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;

import java.io.IOException;
Expand Down Expand Up @@ -35,11 +36,12 @@ public void run() {
network.start();
}

public final void close() {
public void close(final boolean disconnected) {
IOUtils.closeQuietly(socket);
try {
socket.close();
} catch (IOException e) {
Log.e(getClass().getName(), e.toString());
network.join();
} catch (InterruptedException e) {
Log.w(getClass().getName() + "#close", e.toString());
}
}

Expand Down Expand Up @@ -67,7 +69,7 @@ private void doInput() {
listen(buffer);
inputBuffer = buffer.slice();
} catch (IOException e) {
Log.w(getClass().getName(), e.toString());
close(true);
}
}

Expand All @@ -80,14 +82,14 @@ private void doOutput() {
outputStream.flush();
outputQueue.remove(buffer);
} catch (IOException e) {
Log.e(getClass().getName(), e.toString());
//IOUtils.closeQuietly(socket);
Log.e(getClass().getName() + "#doOutput", e.toString());
}
}
}
}

private void doConnection(final String dstName, final int dstPort) {
Log.v(getClass().getName(), dstName + ":" + dstPort);
try {
socket = new java.net.Socket(dstName, dstPort);
if (socket.isConnected()) {
Expand All @@ -106,7 +108,8 @@ public void run() {
doInput();
}
} catch (Exception e) {
Log.v(getClass().getName(), e.toString());
Log.e(getClass().getName() + "#doOutput", e.toString());
close(true);
}
}

Expand Down
13 changes: 5 additions & 8 deletions app/src/main/java/com/haishinkit/rtmp/RTMPChunk.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package com.haishinkit.rtmp;

import java.nio.BufferOverflowException;
import java.util.List;
import java.util.ArrayList;
import java.nio.ByteBuffer;

import com.haishinkit.lang.IRawValue;
import com.haishinkit.rtmp.messages.RTMPMessage;
import com.haishinkit.util.ByteBufferUtils;
import com.haishinkit.util.Log;

public enum RTMPChunk implements IRawValue<Byte> {
ZERO((byte) 0x00),
Expand Down Expand Up @@ -51,13 +48,13 @@ public List<ByteBuffer> encode(RTMPSocket socket, RTMPMessage message) {
throw new IllegalArgumentException();
}

ByteBuffer payload = message.encode(socket);
final ByteBuffer payload = message.encode(socket);
payload.flip();

List<ByteBuffer> list = new ArrayList<ByteBuffer>();
int length = payload.limit();
int timestamp = message.getTimestamp();
int chunkSize = socket.getChunkSizeC();
final List<ByteBuffer> list = new ArrayList<ByteBuffer>();
final int length = payload.limit();
final int timestamp = message.getTimestamp();
final int chunkSize = socket.getChunkSizeS();
ByteBuffer buffer = ByteBuffer.allocate(length(message.getChunkStreamID()) + (length < chunkSize ? length : chunkSize));
message.setLength(length);

Expand Down
12 changes: 6 additions & 6 deletions app/src/main/java/com/haishinkit/rtmp/RTMPConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import com.haishinkit.net.IResponder;
import com.haishinkit.rtmp.messages.RTMPCommandMessage;
import com.haishinkit.rtmp.messages.RTMPMessage;
import com.haishinkit.rtmp.messages.RTMPSetPeerBandwidthMessage;
import com.haishinkit.rtmp.messages.RTMPSetChunkSizeMessage;
import com.haishinkit.util.EventUtils;
import com.haishinkit.util.Log;

Expand Down Expand Up @@ -145,8 +145,8 @@ public void handleEvent(final Event event) {
switch (data.get("code").toString()) {
case "NetConnection.Connect.Success":
connection.getSocket().setChunkSizeS(RTMPConnection.DEFAULT_CHUNK_SIZE_S);
connection.getSocket().doOutput(RTMPChunk.ONE,
new RTMPSetPeerBandwidthMessage()
connection.getSocket().doOutput(RTMPChunk.ZERO,
new RTMPSetChunkSizeMessage()
.setSize(RTMPConnection.DEFAULT_CHUNK_SIZE_S)
.setChunkStreamID(RTMPChunk.CONTROL)
);
Expand Down Expand Up @@ -266,7 +266,7 @@ public void close() {
if (!isConnected()) {
return;
}
socket.close();
socket.close(false);
}

Map<Short, RTMPMessage> getMessages() {
Expand Down Expand Up @@ -297,14 +297,14 @@ void listen(final ByteBuffer buffer) {
if (!payload.hasRemaining()) {
payload.flip();
message.decode(payload).execute(this);
Log.v(getClass().getName(), message.toString());
Log.w(getClass().getName(), message.toString());
payloads.remove(payload);
}
} else {
message = chunk.decode(streamID, this, buffer);
if (message.getLength() <= chunkSizeC) {
message.decode(buffer).execute(this);
Log.v(getClass().getName(), message.toString());
Log.w(getClass().getName(), message.toString());
} else {
payload = ByteBuffer.allocate(message.getLength());
payload.put(buffer.array(), buffer.position(), chunkSizeC);
Expand Down
20 changes: 11 additions & 9 deletions app/src/main/java/com/haishinkit/rtmp/RTMPMuxer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
import com.haishinkit.flv.FlameType;
import com.haishinkit.flv.VideoCodec;
import com.haishinkit.iso.AVCConfigurationRecord;
import com.haishinkit.iso.AVCFormatUtils;
import com.haishinkit.media.IEncoderListener;
import com.haishinkit.rtmp.messages.RTMPAVCVideoMessage;
import com.haishinkit.rtmp.messages.RTMPMessage;
import com.haishinkit.util.ByteBufferUtils;
import com.haishinkit.util.Log;

import java.nio.ByteBuffer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class RTMPMuxer implements IEncoderListener {
public final class RTMPMuxer implements IEncoderListener {
private final RTMPStream stream;
private Map<String, Long> timestamps = new ConcurrentHashMap<String, Long>();

Expand All @@ -24,16 +27,17 @@ public RTMPMuxer(final RTMPStream stream) {
}

@Override
public void onFormatChanged(final String mime, final MediaFormat mediaFormat) {
public final void onFormatChanged(final String mime, final MediaFormat mediaFormat) {
RTMPMessage message = null;
switch (mime) {
case "video/avc":
AVCConfigurationRecord config = new AVCConfigurationRecord(mediaFormat);
message = new RTMPAVCVideoMessage()
.setFrame(FlameType.COMMAND.rawValue())
.setPacketType(AVCPacketType.SEQ.rawValue())
.setFrame(FlameType.KEY.rawValue())
.setCodec(VideoCodec.AVC.rawValue())
.setFrame(AVCPacketType.SEQ.rawValue())
.setPayload(config.toByteBuffer())
.setChunkStreamID(RTMPChunk.VIDEO)
.setStreamID(stream.getId());
break;
default:
Expand All @@ -45,12 +49,10 @@ public void onFormatChanged(final String mime, final MediaFormat mediaFormat) {
}

@Override
public void onSampleOutput(final String mime, final MediaCodec.BufferInfo info, final ByteBuffer buffer) {
public final void onSampleOutput(final String mime, final MediaCodec.BufferInfo info, final ByteBuffer buffer) {
int timestamp = 0;
RTMPChunk chunk = RTMPChunk.ZERO;
RTMPMessage message = null;
if (timestamps.containsKey(mime)) {
chunk = RTMPChunk.ONE;
timestamp = new Double(info.presentationTimeUs - timestamps.get(mime).doubleValue()).intValue();
}
switch (mime) {
Expand All @@ -60,7 +62,7 @@ public void onSampleOutput(final String mime, final MediaCodec.BufferInfo info,
.setPacketType(AVCPacketType.NAL.rawValue())
.setFrame(keyframe ? FlameType.KEY.rawValue() : FlameType.INTER.rawValue())
.setCodec(VideoCodec.AVC.rawValue())
.setPayload(buffer)
.setPayload(AVCFormatUtils.toNALFileFormat(buffer))
.setChunkStreamID(RTMPChunk.VIDEO)
.setTimestamp(timestamp)
.setStreamID(stream.getId());
Expand All @@ -69,7 +71,7 @@ public void onSampleOutput(final String mime, final MediaCodec.BufferInfo info,
break;
}
if (message != null) {
stream.connection.getSocket().doOutput(chunk, message);
stream.connection.getSocket().doOutput(RTMPChunk.ONE, message);
}
timestamps.put(mime, info.presentationTimeUs);
}
Expand Down
Loading

0 comments on commit a0702af

Please sign in to comment.