gpt4 book ai didi

android - 使用 android MediaCodec 对原始 H264 视频流的解码不正确

转载 作者:行者123 更新时间:2023-11-29 01:08:41 25 4
gpt4 key购买 nike

我正在构建一个屏幕共享应用程序,并尝试从套接字接收原始 H264 视频流,并通过使用 MediaCodec 类进行解码,使用 surfaceview 显示它。但是我能够成功地接收数据并在表面上显示。但是我两天以来遇到的问题是视频非常滞后,抖动并且有绿色 strip 和补丁。您可以在 youtube 中查看问题 video link .如果我将此视频保存到 sdcard 并使用 MxPlayer 播放它,那么它播放得很好。我也尝试使用 Gstreamer,一切都很好。这是创建表面 View 时从 Activity 调用的类。

//New Edited Code
public class Server {
static final int socketServerPORT = 53515;
MainActivity activity;
ServerSocket serverSocket;

public Server(MainActivity activity, Surface surface) {
Log.e("constructor()", "called");
this.activity = activity;
Thread socketServerThread = new Thread(new SocketServerThread(surface));
socketServerThread.start();
}

private static MediaCodecInfo selectCodec(String mimeType) {
int numCodecs = MediaCodecList.getCodecCount();
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);

if (codecInfo.isEncoder()) {
continue;
}

String[] types = codecInfo.getSupportedTypes();
for (int j = 0; j < types.length; j++) {
if (types[j].equalsIgnoreCase(mimeType)) {
Log.e("codecinfo", codecInfo.getName());
return codecInfo;
}
}
}
return null;
}

private class SocketServerThread extends Thread {
InputStream is;
Socket socket;
private MediaCodec codec;
private Surface surface;

public SocketServerThread(Surface surface) {
this.surface = surface;
}

@Override
public void run() {
Log.e("socketthread", "called");
try {
selectCodec("video/avc");
codec = MediaCodec.createByCodecName(selectCodec("video/avc").getName());

MediaFormat format = MediaFormat.createVideoFormat("video/avc", 800, 480);
// format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, 1024000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 25);
codec.configure(format, surface, null, 0);
codec.start();
serverSocket = new ServerSocket(socketServerPORT);
while (true) {
socket = serverSocket.accept();
Log.e("connection", "accepted");
is = socket.getInputStream();
if (is != null) {
// File file = new File(Environment.getExternalStorageDirectory() + "/stream.mp4");
// OutputStream output = new FileOutputStream(file);
byte[] buff = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = is.read(buff)) != -1) {
// output.write(buff, 0, read);
if (buff.length == 1)
continue;

int inIndex = codec.dequeueInputBuffer(10000);
if (inIndex >= 0) {
ByteBuffer inputBuffer = codec.getInputBuffer(inIndex);
inputBuffer.clear();
inputBuffer.put(buff);

codec.queueInputBuffer(inIndex, 0, buff.length, 16, 0);
}

MediaCodec.BufferInfo buffInfo = new MediaCodec.BufferInfo();
int outIndex = codec.dequeueOutputBuffer(buffInfo, 10000);

switch (outIndex) {
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
break;
case -3:
break;
default:
codec.releaseOutputBuffer(outIndex, true);
}
}
}
}

} catch (IOException e) {
e.printStackTrace();
} finally {
if (codec != null) {
codec.release();
}
if (socket != null) {
try {
socket.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}

我尝试了你提到的创建 MediaCodec 的方式

MediaCodec.createByCodecName(selectCodec("video/avc").getName());

private static MediaCodecInfo selectCodec(String mimeType) {
int numCodecs = MediaCodecList.getCodecCount();
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);

if (!codecInfo.isEncoder()) {
continue;
}

String[] types = codecInfo.getSupportedTypes();
for (int j = 0; j < types.length; j++) {
if (types[j].equalsIgnoreCase(mimeType)) {
Log.e("codecinfo",codecInfo.getName());
return codecInfo;
}
}
}
return null;
}

但它给我错误

I/OMXClient: MuxOMX ctor
I/MediaCodec: [OMX.qcom.video.encoder.avc] setting surface generation to 28345345
W/ACodec: [OMX.qcom.video.encoder.avc] Failed to set standard component role 'video_decoder.avc'.
E/ACodec: [OMX.qcom.video.encoder.avc] configureCodec returning error -1010
E/ACodec: signalError(omxError 0x80001001, internalError -1010)
E/MediaCodec: Codec reported err 0xfffffc0e, actionCode 0, while in state 3
E/MediaCodec: configure failed with err 0xfffffc0e, resetting...
I/OMXClient: MuxOMX ctor
E/AndroidRuntime: FATAL EXCEPTION: Thread-5
Process: com.androidsrc.server, PID: 27681
android.media.MediaCodec$CodecException: Error 0xfffffc0e
at android.media.MediaCodec.configure(MediaCodec.java:1884)
at com.androidsrc.server.Server$SocketServerThread.run(Server.java:70)
at java.lang.Thread.run(Thread.java:761)

我之前也试过用这个方法创建Mediacodec

codec =  MediaCodec.createDecoderByType("video/avc");

但视频质量与在 YouTube 上分享的视频相同。

最佳答案

我宁愿对此发表评论,但仍然缺少所需的要点:D

我认为您(或者我不知道它在其他方面有效)遗漏了一些重要的部分。您提供的视频显示缺少有关如何解释事物的信息的迹象。

  • 您是否发送和使用 SPS 和 PPS?我不确定您创建的 MediaFormat 是否包含所有需要的信息。

  • MediaCodec 需要将整个帧馈送到它。您确定使用这种逻辑会收到完整的帧吗?

  • 一些解码器期望帧没有 NAL header 。您是否发送没有 NAL header 的帧?

  • 我没有看到你转移任何演示时间

我建议您查看 RTP/RTSP 协议(protocol)以了解如何传输媒体。为了进一步帮助您,我建议您也提供生产者逻辑

关于android - 使用 android MediaCodec 对原始 H264 视频流的解码不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45058679/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com