Потоковое видео из MediaRecorder через LocalSocket

Я пытаюсь отправить видео h264/AAC с Android MediaRecorder через локальный сокет. Цель состоит в том, чтобы отправить видео на сервер WOWZA через RTMP или RTSP, но это доставляет мне много хлопот, и сейчас я просто пытаюсь записать данные в файл из LocalServerSocket.

Вот код Извините, это не совсем чисто, но я потратил часы на тестирование многих вещей, и мой проект сейчас беспорядок.

В разделе "Действия с камерой" настройка выходного файла:

LocalSocket outSocket = new LocalSocket();

try {
    outSocket.connect(new LocalSocketAddress(LOCAL_SOCKET));
} catch (Exception e) {
    Log.i(LOG_TAG, "Error connecting socket: "+e);
}
mMediaRecorder.setOutputFile(outSocket.getFileDescriptor());

Реализация LocalServerSocket:

try {
    mLocalServerSocket = new LocalServerSocket(mName);
} catch (Exception e) {
    Log.e(LOG_TAG, "Error creating server socket: "+e);
    return;
}

while (true) {

    File out = null;
    FileOutputStream fop = null;
    try {
        mLocalClientSocket = mLocalServerSocket.accept();

        InputStream in = mLocalClientSocket.getInputStream();

        out = new File(mContext.getExternalFilesDir(null), "testfile.mp4");
        fop = new FileOutputStream(out);

        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) >= 0) {

            Log.i(LOG_TAG, "Writing "+len+" bytes");
            fop.write(buffer, 0, len);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    finally{
        try {
            fop.close();
            mLocalClientSocket.close();
        } catch (Exception e2) {}
    }
}

Проблема в том, что файл, полученный в результате этого, не читается любым медиаплеером. Как вы думаете, это из-за проблемы с кодировкой? Этот код должен генерировать двоичный файл, если я хорошо понимаю?!

Заранее спасибо, ура.

3 ответа

Хорошо, я нашел, почему файлы не могут воспроизводиться. В файлах MP4 и 3GPP есть заголовок, содержащий байты:

ftyp3gp4 3gp43gp6 широкий мдат

в HEX

0000001866747970336770340000030033677034336770360000000877696465000392D86D6461740000

4 байта перед тегом "mdat" представляют положение другого тега "moov", расположенного в конце файла. Положение обычно устанавливается, когда запись заканчивается, но поскольку MediaRecorder не может искать сокеты, он не может установить эти байты на правильное значение в нашем случае.

Теперь моя проблема состоит в том, чтобы найти способ сделать такой файл пригодным для потоковой передачи, поскольку он требует, чтобы он воспроизводился до окончания записи.

Вы можете попробовать использовать mp4box для реструктуризации вашего файла. В окне moov указаны индексы для каждого образца аудио и видео. Если это в конце файла, это затрудняет потоковую передачу.

Это может помочь: http://boliston.wordpress.com/tag/moov-box/

Или это: mp4box -inter 0.5 some_file.mp4

(У меня нет возможности попробовать в настоящее время)

Если вам нужно это для работы с вашим приложением, мне не известны какие-либо действия по переносу mp4box на Android.

Сегодня я попытался сделать то же самое, но mp4 не очень легко транслировать (как было сказано ранее, некоторые части написаны в конце). Я не говорю, что это невозможно, но кажется, по крайней мере, довольно сложно.

Так что обходной путь для новых Android API (4.3) может быть таким:

  • Установите предварительный просмотр камеры для SurfaceTexture: camera.setPreviewTexture
  • Запишите эту текстуру, используя OpenGL и MediaCodex + Muxer

Недостатком этого решения является то, что размер предварительного просмотра камеры может быть меньше, чем размер видео. Это означает, что в зависимости от вашего устройства вы не можете записывать с самым высоким разрешением. Подсказка: некоторые камеры говорят, что они не поддерживают более высокие размеры предварительного просмотра, но они делают, и вы можете попытаться настроить камеру так, чтобы установить размер предварительного просмотра равным размеру видео. Если вы это сделаете, перехватите RuntimeException для camera.setParameters, а в случае сбоя используйте только поддерживаемые размеры предварительного просмотра.

Некоторые ссылки, как сделать запись из SurfaceTexture:

Bigflage: отличные примеры для MediaCodec.

Класс VideoRecorder от Lablet.

Также может быть полезно: spydroid-ipcamera передает данные из сокета MediaRecorder в виде потоков RTP, но я не нашел способа передать их в MediaCodec. (Я уже застрял, читая правильные размеры блока NAL, как они делают...)

Другие вопросы по тегам