-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMediaEncoder.java
149 lines (138 loc) · 4.67 KB
/
MediaEncoder.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package com.uni.vr.encoder;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.util.Log;
import com.uni.pano.config.EnumElement;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* Created by DELL on 2017/4/14.
*/
public abstract class MediaEncoder implements Runnable {
private Semaphore semaphoreDataAvailable = new Semaphore(0);
private Semaphore semaphoreWriteProtect = new Semaphore(1);
protected MediaCodec mediaCodec;
protected MediaCodec.BufferInfo bufferInfo;
protected final WeakReference<MediaMuxerWrapper> mediaMuxerWrapperWeakReference;
protected int mTrackIndex;
protected volatile boolean mIsCapturing = false;
protected volatile boolean mRequestStop;
protected boolean mIsEOS;
protected boolean mMuxerStarted;
ExecutorService singleThreadExecutor= Executors.newSingleThreadExecutor();
public static class Message{
public EnumElement.ENCODE_MESSAGE msg;
public String filePath = "";
};
public interface MediaEncoderListener {
public void onStartRecording(MediaEncoder encoder);
public void onStopRecording(MediaEncoder encoder);
}
MediaEncoderListener mediaEncoderListener;
private List<Message> messageArrayList = new LinkedList<>();
public void addMsg(Message message, boolean flush) {
try {
semaphoreWriteProtect.acquire();
if (flush){
messageArrayList.clear();
}
messageArrayList.add(message);
}catch (InterruptedException e){
}finally {
semaphoreWriteProtect.release();
semaphoreDataAvailable.release();
}
}
@Override
public void run() {
while(true) {
try {
semaphoreDataAvailable.acquire();
semaphoreWriteProtect.acquire();
if (messageArrayList.isEmpty()){
continue;
}
Message message = messageArrayList.remove(0);
if (message.msg == EnumElement.ENCODE_MESSAGE.QUIT){
release();
break;
}else{
handle(message);
}
}catch (InterruptedException e){
}finally {
semaphoreWriteProtect.release();
}
}
}
public void startRecording(){
mTrackIndex = -1;
mMuxerStarted = mIsEOS = false;
mIsCapturing = true;
mRequestStop = false;
}
public void stopRecording(){
//mIsCapturing = false;
mRequestStop = true;
}
protected void release() {
singleThreadExecutor.shutdown();
mIsCapturing = false;
if (mediaCodec != null) {
mediaCodec.stop();
mediaCodec.release();
mediaCodec = null;
}
MediaMuxerWrapper mediaMuxerWrapper = mediaMuxerWrapperWeakReference != null ? mediaMuxerWrapperWeakReference.get() : null;
if (mediaMuxerWrapper != null) {
mediaMuxerWrapper.stop();
}
bufferInfo = null;
if (mediaEncoderListener!=null){
mediaEncoderListener.onStopRecording(this);
mediaEncoderListener = null;
}
}
public MediaEncoder(MediaMuxerWrapper mediaMuxerWrapper, MediaEncoderListener mediaEncoderListener) {
mediaMuxerWrapperWeakReference = new WeakReference<MediaMuxerWrapper>(mediaMuxerWrapper);
singleThreadExecutor.execute(this);
this.mediaEncoderListener = mediaEncoderListener;
}
public void frameAvailableSoon(){
if (mIsCapturing || !mRequestStop) {
Message message = new Message();
message.msg = EnumElement.ENCODE_MESSAGE.AVAILABLE;
addMsg(message, false);
}
}
public void handle(Message message){
switch (message.msg){
case AVAILABLE:{
drainEncoder(false);
}
break;
case STOP:{
drainEncoder(true);
release();
}
break;
default:
break;
}
}
public abstract void drainEncoder(boolean endOfStream);
protected long prevOutputPTSUs = 0;
protected long getPTSUs() {
long result = System.nanoTime() / 1000L;
if (result < prevOutputPTSUs)
result = (prevOutputPTSUs - result) + result;
return result;
}
}