Skip to content

Commit de0e502

Browse files
committed
refactor frame send, muxer
1 parent 31e4313 commit de0e502

File tree

8 files changed

+306
-113
lines changed

8 files changed

+306
-113
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
*
3+
* *
4+
* * * Copyright (C) 2017 ChillingVan
5+
* * *
6+
* * * Licensed under the Apache License, Version 2.0 (the "License");
7+
* * * you may not use this file except in compliance with the License.
8+
* * * You may obtain a copy of the License at
9+
* * *
10+
* * * http://www.apache.org/licenses/LICENSE-2.0
11+
* * *
12+
* * * Unless required by applicable law or agreed to in writing, software
13+
* * * distributed under the License is distributed on an "AS IS" BASIS,
14+
* * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* * * See the License for the specific language governing permissions and
16+
* * * limitations under the License.
17+
* *
18+
*
19+
*/
20+
21+
package com.chillingvan.lib.muxer;
22+
23+
import android.media.MediaCodec;
24+
25+
import com.chillingvan.lib.publisher.StreamPublisher;
26+
27+
/**
28+
* Created by Chilling on 2017/12/23.
29+
*/
30+
31+
public abstract class BaseMuxer implements IMuxer {
32+
33+
protected TimeIndexCounter videoTimeIndexCounter = new TimeIndexCounter();
34+
protected TimeIndexCounter audioTimeIndexCounter = new TimeIndexCounter();
35+
36+
@Override
37+
public int open(StreamPublisher.StreamPublisherParam params) {
38+
videoTimeIndexCounter.reset();
39+
audioTimeIndexCounter.reset();
40+
return 0;
41+
}
42+
43+
@Override
44+
public void writeVideo(byte[] buffer, int offset, int length, MediaCodec.BufferInfo bufferInfo) {
45+
videoTimeIndexCounter.calcTotalTime(bufferInfo.presentationTimeUs);
46+
}
47+
48+
@Override
49+
public void writeAudio(byte[] buffer, int offset, int length, MediaCodec.BufferInfo bufferInfo) {
50+
audioTimeIndexCounter.calcTotalTime(bufferInfo.presentationTimeUs);
51+
}
52+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
*
3+
* *
4+
* * * Copyright (C) 2017 ChillingVan
5+
* * *
6+
* * * Licensed under the Apache License, Version 2.0 (the "License");
7+
* * * you may not use this file except in compliance with the License.
8+
* * * You may obtain a copy of the License at
9+
* * *
10+
* * * http://www.apache.org/licenses/LICENSE-2.0
11+
* * *
12+
* * * Unless required by applicable law or agreed to in writing, software
13+
* * * distributed under the License is distributed on an "AS IS" BASIS,
14+
* * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* * * See the License for the specific language governing permissions and
16+
* * * limitations under the License.
17+
* *
18+
*
19+
*/
20+
21+
package com.chillingvan.lib.muxer;
22+
23+
import android.media.MediaCodec;
24+
25+
/**
26+
* Created by Chilling on 2017/12/23.
27+
*/
28+
29+
public class BufferInfoEx {
30+
private MediaCodec.BufferInfo bufferInfo;
31+
private int totalTime;
32+
33+
public BufferInfoEx(MediaCodec.BufferInfo bufferInfo, int totalTime) {
34+
this.bufferInfo = bufferInfo;
35+
this.totalTime = totalTime;
36+
}
37+
38+
public MediaCodec.BufferInfo getBufferInfo() {
39+
return bufferInfo;
40+
}
41+
42+
public int getTotalTime() {
43+
return totalTime;
44+
}
45+
}

applibs/src/main/java/com/chillingvan/lib/muxer/FramePool.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ public FramePool(int poolSize) {
3737
frameItemsPool = new ItemsPool<>(poolSize);
3838
}
3939

40-
public Frame obtain(byte[] data, int offset, int length, int timeStampMs, int type) {
40+
public Frame obtain(byte[] data, int offset, int length, BufferInfoEx bufferInfo, int type) {
4141
Frame frame = frameItemsPool.acquire();
4242
if (frame == null) {
43-
frame = new Frame(data, offset, length, timeStampMs, type);
43+
frame = new Frame(data, offset, length, bufferInfo, type);
4444
} else {
45-
frame.set(data, offset, length, timeStampMs, type);
45+
frame.set(data, offset, length, bufferInfo, type);
4646
}
4747
return frame;
4848
}
@@ -110,38 +110,38 @@ private boolean isInPool(T instance) {
110110
public static class Frame {
111111
public byte[] data;
112112
public int length;
113-
public int timeStampMs;
113+
public BufferInfoEx bufferInfo;
114114
public int type;
115115
public static final int TYPE_VIDEO = 1;
116116
public static final int TYPE_AUDIO = 2;
117117

118-
public Frame(byte[] data, int offset, int length, int timeStampMs, int type) {
118+
public Frame(byte[] data, int offset, int length, BufferInfoEx bufferInfo, int type) {
119119
this.data = new byte[length];
120120
System.arraycopy(data, offset, this.data, 0, length);
121121
this.length = length;
122-
this.timeStampMs = timeStampMs;
122+
this.bufferInfo = bufferInfo;
123123
this.type = type;
124124
}
125125

126-
public void set(byte[] data, int offset, int length, int timeStampMs, int type) {
126+
public void set(byte[] data, int offset, int length, BufferInfoEx bufferInfo, int type) {
127127
if (this.data.length < length) {
128128
this.data = new byte[length];
129129
}
130130

131131
System.arraycopy(data, offset, this.data, 0, length);
132132

133133
this.length = length;
134-
this.timeStampMs = timeStampMs;
134+
this.bufferInfo = bufferInfo;
135135
this.type = type;
136136
}
137137

138138
public static void sortFrame(List<Frame> frameQueue) {
139139
Collections.sort(frameQueue, new Comparator<Frame>() {
140140
@Override
141141
public int compare(Frame left, Frame right) {
142-
if (left.timeStampMs < right.timeStampMs) {
142+
if (left.bufferInfo.getTotalTime() < right.bufferInfo.getTotalTime()) {
143143
return -1;
144-
} else if (left.timeStampMs == right.timeStampMs) {
144+
} else if (left.bufferInfo.getTotalTime() == right.bufferInfo.getTotalTime()) {
145145
return 0;
146146
} else {
147147
return 1;

applibs/src/main/java/com/chillingvan/lib/muxer/FrameSender.java

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
package com.chillingvan.lib.muxer;
2222

2323
import android.os.Handler;
24+
import android.os.HandlerThread;
25+
import android.os.Message;
2426

2527
import java.util.LinkedList;
2628
import java.util.List;
@@ -31,12 +33,74 @@
3133

3234
public class FrameSender {
3335

34-
public static final int KEEP_COUNT = 30;
36+
private static final int KEEP_COUNT = 30;
37+
private static final int MESSAGE_READY_TO_CLOSE = 4;
38+
private static final int MSG_ADD_FRAME = 3;
3539

3640
private Handler sendHandler;
3741
private List<FramePool.Frame> frameQueue = new LinkedList<>();
3842
private FramePool framePool = new FramePool(KEEP_COUNT + 10);
43+
private FrameSenderCallback frameSenderCallback;
3944

40-
public FrameSender() {
45+
46+
public FrameSender(final FrameSenderCallback frameSenderCallback) {
47+
this.frameSenderCallback = frameSenderCallback;
48+
final HandlerThread sendHandlerThread = new HandlerThread("send_thread");
49+
sendHandlerThread.start();
50+
sendHandler = new Handler(sendHandlerThread.getLooper()) {
51+
@Override
52+
public void handleMessage(Message msg) {
53+
super.handleMessage(msg);
54+
if (msg.obj != null) {
55+
addFrame((FramePool.Frame) msg.obj);
56+
}
57+
sendFrame(msg.arg1);
58+
59+
if (msg.what == MESSAGE_READY_TO_CLOSE) {
60+
frameSenderCallback.close();
61+
sendHandlerThread.quitSafely();
62+
}
63+
}
64+
};
65+
}
66+
67+
68+
private void addFrame(FramePool.Frame frame) {
69+
frameQueue.add(frame);
70+
FramePool.Frame.sortFrame(frameQueue);
71+
}
72+
73+
private void sendFrame(int keepCount) {
74+
while (frameQueue.size() > keepCount) {
75+
FramePool.Frame sendFrame = frameQueue.remove(0);
76+
if (sendFrame.type == FramePool.Frame.TYPE_VIDEO) {
77+
frameSenderCallback.onSendVideo(sendFrame);
78+
} else if(sendFrame.type == FramePool.Frame.TYPE_AUDIO) {
79+
frameSenderCallback.onSendAudio(sendFrame);
80+
}
81+
framePool.release(sendFrame);
82+
}
83+
}
84+
85+
public void sendAddFrameMessage(byte[] data, int offset, int length, BufferInfoEx bufferInfo, int type) {
86+
FramePool.Frame frame = framePool.obtain(data, offset, length, bufferInfo, type);
87+
Message message = Message.obtain();
88+
message.what = MSG_ADD_FRAME;
89+
message.obj = frame;
90+
message.arg1 = KEEP_COUNT;
91+
sendHandler.sendMessage(message);
92+
}
93+
94+
public void sendCloseMessage() {
95+
Message message = Message.obtain();
96+
message.arg1 = 0;
97+
message.what = MESSAGE_READY_TO_CLOSE;
98+
sendHandler.sendMessage(message);
99+
}
100+
101+
public interface FrameSenderCallback {
102+
void onSendVideo(FramePool.Frame sendFrame);
103+
void onSendAudio(FramePool.Frame sendFrame);
104+
void close();
41105
}
42106
}

applibs/src/main/java/com/chillingvan/lib/muxer/IMuxer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030

3131
public interface IMuxer {
3232

33+
/**
34+
*
35+
* @return 1 if it is connected
36+
* 0 if it is not connected
37+
*/
3338
int open(StreamPublisher.StreamPublisherParam params);
3439

3540
void writeVideo(byte[] buffer, int offset, int length, MediaCodec.BufferInfo bufferInfo);

applibs/src/main/java/com/chillingvan/lib/muxer/MP4Muxer.java

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import android.media.MediaCodec;
2424
import android.media.MediaMuxer;
2525

26+
import com.chillingvan.canvasgl.Loggers;
2627
import com.chillingvan.lib.publisher.StreamPublisher;
2728

2829
import java.io.IOException;
@@ -32,46 +33,82 @@
3233
* Created by Chilling on 2017/12/17.
3334
*/
3435

35-
public class MP4Muxer implements IMuxer {
36+
public class MP4Muxer extends BaseMuxer {
37+
private static final String TAG = "MP4Muxer";
3638

3739
private MediaMuxer mMuxer;
3840
private int videoTrackIndex;
3941
private int audioTrackIndex;
42+
private FrameSender frameSender;
43+
44+
4045

4146
public MP4Muxer() {
47+
super();
4248
}
4349

4450
@Override
4551
public int open(StreamPublisher.StreamPublisherParam params) {
52+
super.open(params);
4653
try {
4754
mMuxer = new MediaMuxer(params.outputFilePath,
4855
MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
4956
} catch (IOException e) {
5057
e.printStackTrace();
51-
return -1;
58+
return 0;
5259
}
5360
videoTrackIndex = mMuxer.addTrack(params.createVideoMediaFormat());
5461
audioTrackIndex = mMuxer.addTrack(params.createAudioMediaFormat());
5562
mMuxer.start();
56-
return 0;
63+
64+
frameSender = new FrameSender(new FrameSender.FrameSenderCallback(){
65+
66+
67+
@Override
68+
public void onSendVideo(FramePool.Frame sendFrame) {
69+
70+
mMuxer.writeSampleData(videoTrackIndex, ByteBuffer.wrap(sendFrame.data, 0, sendFrame.length), sendFrame.bufferInfo.getBufferInfo());
71+
}
72+
73+
@Override
74+
public void onSendAudio(FramePool.Frame sendFrame) {
75+
mMuxer.writeSampleData(audioTrackIndex, ByteBuffer.wrap(sendFrame.data, 0, sendFrame.length), sendFrame.bufferInfo.getBufferInfo());
76+
}
77+
78+
@Override
79+
public void close() {
80+
81+
if (mMuxer != null) {
82+
mMuxer.stop();
83+
mMuxer.release();
84+
mMuxer = null;
85+
}
86+
}
87+
});
88+
89+
90+
return 1;
5791
}
5892

5993
@Override
6094
public void writeVideo(byte[] buffer, int offset, int length, MediaCodec.BufferInfo bufferInfo) {
61-
mMuxer.writeSampleData(videoTrackIndex, ByteBuffer.wrap(buffer, offset, length), bufferInfo);
95+
super.writeVideo(buffer, offset, length, bufferInfo);
96+
97+
Loggers.d(TAG, "writeVideo: " + " offset:" + offset + " length:" + length);
98+
frameSender.sendAddFrameMessage(buffer, offset, length, new BufferInfoEx(bufferInfo, videoTimeIndexCounter.getTimeIndex()), FramePool.Frame.TYPE_VIDEO);
6299
}
63100

64101
@Override
65102
public void writeAudio(byte[] buffer, int offset, int length, MediaCodec.BufferInfo bufferInfo) {
66-
mMuxer.writeSampleData(audioTrackIndex, ByteBuffer.wrap(buffer, offset, length), bufferInfo);
103+
super.writeAudio(buffer, offset, length, bufferInfo);
104+
Loggers.d(TAG, "writeAudio: ");
105+
frameSender.sendAddFrameMessage(buffer, offset, length, new BufferInfoEx(bufferInfo, audioTimeIndexCounter.getTimeIndex()), FramePool.Frame.TYPE_AUDIO);
67106
}
68107

69108
@Override
70109
public int close() {
71-
if (mMuxer != null) {
72-
mMuxer.stop();
73-
mMuxer.release();
74-
mMuxer = null;
110+
if (frameSender != null) {
111+
frameSender.sendCloseMessage();
75112
}
76113
return 0;
77114
}

0 commit comments

Comments
 (0)