[英]Decoding an RTP stream with H264 data on Android Using MediaCodec
I am currently attempting to parse H264 data from an RTP stream and then send it to the MediaCodec to render on a SurfaceView for Android.我目前正在尝试从 RTP 流中解析 H264 数据,然后将其发送到 MediaCodec 以在 Android 的 SurfaceView 上呈现。
However, I'm not certain how to:但是,我不确定如何:
I have not seen any examples of this implemented in a clear and concise way and I haven't found the MediaCodec docs to be at all helpful.我还没有看到任何以清晰简洁的方式实现的示例,我也没有发现 MediaCodec 文档有任何帮助。
Anyone have any experience in this domain?任何人在这个领域有任何经验吗?
void videoCodec(ByteBuffer input, int flags) {
bufferInfo.set(0, 0, 0, flags);
int inputBufferId = codec.dequeueInputBuffer(10000);
if (inputBufferId >= 0) {
//put data
ByteBuffer inputData = inputBuffers[inputBufferId];
inputData.clear();
inputData.put(input);
//queue it up
codec.queueInputBuffer(inputBufferId, 0, input.limit(), 0, flags);
}
int outputBufferId = codec.dequeueOutputBuffer(bufferInfo, 10000);
if (outputBufferId >= 0) {
// outputBuffers[outputBufferId] is ready to be processed or rendered.
Timber.e("Rendering Data with Index of: %s", outputBufferId);
codec.releaseOutputBuffer(outputBufferId, true);
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = codec.getOutputBuffers();
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
//format = codec.getOutputFormat();
}
}
MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080);
codec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
codec.configure(format, surfaceVideo.getHolder().getSurface(), null, 0);
codec.start();
inputBuffers = codec.getInputBuffers();
outputBuffers = codec.getOutputBuffers();
while (streaming) {
//receive RTP Packet
h264Parser(rtpPacket.getPayload());
}
And the the h264Parser looks something like this: h264Parser 看起来像这样:
void h264Parser(byte[] payload) {
int packetType = (byte) payload[0] & (byte) 0x1F;
boolean startBit = (payload[1] & 0x80) != 0;
boolean endBit = (payload[1] & 0x40) != 0;
int flags = 0;
switch (packetType) {
case 7:
pps = new ByteArrayOutputStream();
pps.write(prefix);
pps.write(payload);
break;
case 8:
if (pps.size() > 0) {
pps.write(payload);
hasPps = true;
flags = MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
payload = pps.toByteArray();
//Send packet to decoder
videoCodec(ByteBuffer.wrap(payload), flags);
break;
case 28:
if (hasPps) {
if (startBit) {
baos = new ByteArrayOutputStream();
baos.write(prefix);
baos.write(payload);
} else if (endBit) {
if(baos != null) {
baos.write(payload);
flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;
payload = baos.toByteArray();
//Send packet to decoder
videoCodec(ByteBuffer.wrap(payload), flags);
hasPps = false;
} else {
if(baos != null ) {
baos.write(payload);
}
}
}
break;
case 1:
break;
default:
}
As far as i remember MediaCodec uses full acess units, not only slices (someone correct me of i'm wrong)据我所知 MediaCodec 使用完整的访问单元,而不仅仅是切片(有人纠正我我错了)
So you have to build a complete acess unit form RTP and feed it to the decoder (sadly i have no experience with RTP and cannot help you with building one).因此,您必须构建一个完整的 RTP 访问单元并将其提供给解码器(遗憾的是我没有 RTP 经验,无法帮助您构建一个)。
You send the access units to the decoder as follows:您将访问单元发送到解码器,如下所示:
Dequeue a inputbuffer出列输入缓冲区
int inputBufferIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC); ByteBuffer inputBuffer = videoDecoderInputBuffers[videoInputBufIndex];
Fill it with your access unit填写您的访问单元
inputBuffer.put(acessUnit); inputBuffer.flip();
Queue the buffer for decoding将缓冲区排队以进行解码
decoder.queueInputBuffer(inputBufferIndex,0,inputBuffer.limit(), 0, FLAGS);
I hope this helps a little希望这会有帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.