Я написал простой класс, который должен получать необработанный поток H264 через сокет UDP и передавать их в MediaCodec, чтобы я мог декодировать кадры и отображать их в пользовательском интерфейсе (поверхность TextureView).
Воткод
public class StreamReceiver implements Runnable
{
private MyActivity activity;
private MediaCodec decoder;
private DatagramSocket socket;
public StreamReceiver(MyActivity activity, Surface surface)
{
this.activity = activity;
decoder = MediaCodec.createDecoderByType("video/avc");
MediaFormat format = MediaFormat.createVideoFormat("video/avc", 1024, 768);
decoder.configure(format, surface, null, 0);
decoder.start();
try
{
socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(22122));
}
catch(Exception e)
{
e.printStackTrace();
}
}
@Override
public void run()
{
BufferInfo info = new BufferInfo();
byte[] data = new byte[65535];
while (true)
{
DatagramPacket pkt = new DatagramPacket(data, data.length);
try
{
socket.receive(pkt);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int inputIndex = decoder.dequeueInputBuffer(-1);
ByteBuffer inputBuffer = decoder.getInputBuffers()[inputIndex];
if (inputIndex >= 0)
{
inputBuffer.put(data, 0, pkt.getLength());
decoder.queueInputBuffer(inputIndex, 0, pkt.getLength(), 0, 0);
}
int outIndex = decoder.dequeueOutputBuffer(info, 0);
switch (outIndex)
{
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.d("R", "INFO_OUTPUT_FORMAT_CHANGED format : " + decoder.getOutputFormat());
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.d("R", "INFO_TRY_AGAIN_LATER");
break;
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.d("R", "INFO_OUTPUT_BUFFERS_CHANGED");
break;
default:
Log.d("R", "Rendering");
decoder.releaseOutputBuffer(outIndex, true);
try
{
Thread.sleep(40);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.d("R", "BUFFER_FLAG_END_OF_STREAM");
break;
}
}
decoder.stop();
decoder.release();
}
Конечным результатом является то, что первый кадр отображается, но некоторые области изображения перепутаны.Последующие кадры не отображаются, но в приведенном выше коде нет исключений.Чего мне не хватает, чтобы получить видео для рендеринга?
В случае, если требуются значения sps и pps, я буду рад получить объяснение о том, как их сделать.У меня нет к ним доступа, только необработанный канал h264, но если при сбросе его в файл и преобразовании в MP4 получается корректное видео, то я думаю, что можно жить без них.