Skip to content

Commit 6724d3e

Browse files
author
WhalenSun
committed
修改不支持的硬编码格式报错。
1 parent 6370750 commit 6724d3e

File tree

1 file changed

+78
-24
lines changed

1 file changed

+78
-24
lines changed

sdk/video-link-android/src/main/java/com/tencent/iot/video/link/encoder/VideoEncoder.java

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
public class VideoEncoder {
2121

22+
private final String TAG = VideoEncoder.class.getSimpleName();
2223
private final VideoEncodeParam videoEncodeParam;
2324
private final ExecutorService executor = Executors.newSingleThreadExecutor();
2425
private MediaCodec mediaCodec;
@@ -28,6 +29,8 @@ public class VideoEncoder {
2829
private int MAX_BITRATE_LENGTH = 1000000;
2930
private int beginBitRate = 0;
3031

32+
private boolean isSupportNV21 = false;
33+
3134
private String firstSupportColorFormatCodecName = ""; // OMX.qcom.video.encoder.avc 和 c2.android.avc.encoder 过滤,这两个h264编码性能好一些。如果都不支持COLOR_FormatYUV420Planar,就用默认的方式。
3235

3336
public VideoEncoder(VideoEncodeParam param) {
@@ -38,6 +41,8 @@ public VideoEncoder(VideoEncodeParam param) {
3841

3942
private void initMediaCodec() {
4043
try {
44+
checkSupportedColorFormats("video/avc"); // H.264 编码器
45+
4146
if (!firstSupportColorFormatCodecName.isEmpty()) {
4247
mediaCodec = MediaCodec.createByCodecName(firstSupportColorFormatCodecName);
4348
} else {
@@ -55,8 +60,13 @@ private void initMediaCodec() {
5560
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
5661
//描述视频格式的帧速率(以帧/秒为单位)的键。帧率,一般在15至30之内,太小容易造成视频卡顿。
5762
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, videoEncodeParam.getFrameRate());
58-
//色彩格式,具体查看相关API,不同设备支持的色彩格式不尽相同
59-
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
63+
if (isSupportNV21) {
64+
//色彩格式,具体查看相关API,不同设备支持的色彩格式不尽相同
65+
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
66+
} else {
67+
//色彩格式,具体查看相关API,不同设备支持的色彩格式不尽相同
68+
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
69+
}
6070
//关键帧间隔时间,单位是秒
6171
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, videoEncodeParam.getiFrameInterval());
6272
mediaFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR);
@@ -74,6 +84,44 @@ private void initMediaCodec() {
7484
}
7585
}
7686

87+
private void checkSupportedColorFormats(String mimeType) {
88+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
89+
MediaCodecList codecList = null;
90+
codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
91+
MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
92+
93+
for (MediaCodecInfo codecInfo : codecInfos) {
94+
if (!codecInfo.isEncoder()) {
95+
continue;
96+
}
97+
98+
String[] supportedTypes = codecInfo.getSupportedTypes();
99+
for (String type : supportedTypes) {
100+
if (type.equalsIgnoreCase(mimeType)) {
101+
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(type);
102+
int[] colorFormats = capabilities.colorFormats;
103+
104+
for (int colorFormat : colorFormats) {
105+
switch (colorFormat) {
106+
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
107+
Log.e(TAG, "Supported color format: COLOR_FormatYUV420Planar");
108+
isSupportNV21 = false;
109+
return;
110+
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
111+
Log.e(TAG, "Supported color format: COLOR_FormatYUV420SemiPlanar");
112+
isSupportNV21 = true;
113+
return;
114+
default:
115+
Log.e(TAG, "Supported color format: " + colorFormat);
116+
break;
117+
}
118+
}
119+
}
120+
}
121+
}
122+
}
123+
}
124+
77125
//描述平均位速率(以位/秒为单位)的键。 关联的值是一个整数
78126
@TargetApi(Build.VERSION_CODES.KITKAT)
79127
public void setVideoBitRate(int bitRate) {
@@ -91,7 +139,7 @@ public void setVideoBitRate(int bitRate) {
91139
mediaCodec.setParameters(params);
92140

93141
} catch (IllegalStateException e) {
94-
Log.e("TAG", "updateBitrate failed", e);
142+
Log.e(TAG, "updateBitrate failed", e);
95143
}
96144
}
97145

@@ -104,24 +152,30 @@ public int getVideoBitRate() {
104152
public void encoderH264(byte[] data, boolean mirror) {
105153
if (executor.isShutdown()) return;
106154
executor.submit(() -> {
107-
byte[] rotateBytes;
108-
//视频顺时针旋转90度
109-
if (mirror) {
110-
rotateBytes = nv21Rotate270(data, videoEncodeParam.getWidth(), videoEncodeParam.getHeight());
155+
byte[] readyToProcessBytes;
156+
if (isSupportNV21) {
157+
//将NV21编码成NV12
158+
byte[] bytes = NV21ToNV12(data, videoEncodeParam.getWidth(), videoEncodeParam.getHeight());
159+
//视频顺时针旋转90度
160+
byte[] nv12 = rotateNV290(bytes, videoEncodeParam.getWidth(), videoEncodeParam.getHeight());
161+
162+
if (mirror) {
163+
verticalMirror(nv12, videoEncodeParam.getHeight(), videoEncodeParam.getWidth());
164+
}
165+
readyToProcessBytes = nv12;
111166
} else {
112-
rotateBytes = nv21Rotate90(data, videoEncodeParam.getWidth(), videoEncodeParam.getHeight());
167+
byte[] rotateBytes;
168+
//视频顺时针旋转90度
169+
if (mirror) {
170+
rotateBytes = nv21Rotate270(data, videoEncodeParam.getWidth(), videoEncodeParam.getHeight());
171+
} else {
172+
rotateBytes = nv21Rotate90(data, videoEncodeParam.getWidth(), videoEncodeParam.getHeight());
173+
}
174+
//将NV21编码成I420
175+
byte[] i420 = toI420(rotateBytes, videoEncodeParam.getHeight(), videoEncodeParam.getWidth());
176+
readyToProcessBytes = i420;
113177
}
114-
//将NV21编码成I420
115-
byte[] i420 = toI420(rotateBytes, videoEncodeParam.getHeight(), videoEncodeParam.getWidth());
116-
117-
// //将NV21编码成NV12
118-
// byte[] bytes = NV21ToNV12(data, videoEncodeParam.getWidth(), videoEncodeParam.getHeight());
119-
// //视频顺时针旋转90度
120-
// byte[] nv12 = rotateNV290(bytes, videoEncodeParam.getWidth(), videoEncodeParam.getHeight());
121-
//
122-
// if (mirror) {
123-
// verticalMirror(nv12, videoEncodeParam.getHeight(), videoEncodeParam.getWidth());
124-
// }
178+
125179

126180
try {
127181
//拿到输入缓冲区,用于传送数据进行编码
@@ -134,9 +188,9 @@ public void encoderH264(byte[] data, boolean mirror) {
134188
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
135189
inputBuffer.clear();
136190
//往输入缓冲区写入数据
137-
inputBuffer.put(i420);
191+
inputBuffer.put(readyToProcessBytes);
138192
//五个参数,第一个是输入缓冲区的索引,第二个数据是输入缓冲区起始索引,第三个是放入的数据大小,第四个是时间戳,保证递增就是
139-
mediaCodec.queueInputBuffer(inputBufferIndex, 0, i420.length, System.nanoTime() / 1000, 0);
193+
mediaCodec.queueInputBuffer(inputBufferIndex, 0, readyToProcessBytes.length, System.nanoTime() / 1000, 0);
140194
}
141195
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
142196
//拿到输出缓冲区的索引
@@ -152,7 +206,7 @@ public void encoderH264(byte[] data, boolean mirror) {
152206

153207
if (bufferInfo.flags == MediaCodec.BUFFER_FLAG_KEY_FRAME) {
154208
// I 帧的处理逻辑
155-
// Log.e("TAG", "==========I帧==============="+seq);
209+
// Log.e(TAG, "==========I帧==============="+seq);
156210
ByteBuffer spsb = mediaCodec.getOutputFormat().getByteBuffer("csd-0");
157211
byte[] sps = new byte[spsb.remaining()];
158212
spsb.get(sps, 0, sps.length);
@@ -170,7 +224,7 @@ public void encoderH264(byte[] data, boolean mirror) {
170224
}
171225
} else {
172226
//outData就是输出的h264数据
173-
// Log.e("TAG", "==========P帧===============" + seq);
227+
// Log.e(TAG, "==========P帧===============" + seq);
174228
if (encoderListener != null) {
175229
encoderListener.onVideoEncoded(outData, System.currentTimeMillis(), seq);
176230
seq++;
@@ -356,7 +410,7 @@ private void checkSupportedColorFormats() {
356410
for (int colorFormat : colorFormats) {
357411

358412
if (colorFormat == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar) {
359-
Log.d("TAG", "Video encoder: " + codecInfo.getName() + ", supported color format: " + colorFormat);
413+
Log.d(TAG, "Video encoder: " + codecInfo.getName() + ", supported color format: " + colorFormat);
360414
firstSupportColorFormatCodecName = codecInfo.getName();
361415
return;
362416
}

0 commit comments

Comments
 (0)