Android - декодировать сырой поток видео h264 - PullRequest
0 голосов
/ 28 декабря 2018

Я написал простой класс, который должен получать необработанный поток 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 получается корректное видео, то я думаю, что можно жить без них.

...