Подтвердить что ты не робот

Исправить файл 3GP после потоковой передачи с Android Media Recorder

Я пытаюсь передать видео с камеры Android через локальный сокет unix и записывать файл из потока в SDCard. Все работает отлично, за исключением того, что файл не воспроизводится ни с одним игроком. Это потому, что Android не заполняет некоторые пробелы в файле, потому что сокет не доступен для поиска. Насколько я понимаю, мне нужно внести некоторые изменения после окончания видеопотока. Я прочитал несколько статей здесь, здесь и здесь, но никто из них не помог мне. Я играю с шестнадцатеричным редактором, чтобы узнать, как это сделать вручную, поэтому впоследствии будет тривиально делать то же самое в коде Android.

Вот пример файла, сохраненного из потока: https://dl.dropbox.com/u/17510473/sample_not_playable.3gp

Может ли кто-нибудь исправить это, чтобы воспроизвести его и сказать, как он это сделал?

EDIT: Я удаляю заголовок 3gp файла и пишу новый:

00 00 00 18 66 74 79 70 33 67 70 34 00 00 03 00 33 67 70 34 33 67 70 36 00 00 00 00

Затем я нахожу исходное местоположение атомов mdat и moov следующей командой:

grep -aobE "ftyp|mdat|moov" sample_not_playable.3gp

И он дает мне следующий результат:

4:ftyp
28:mdat
1414676:moov

Затем сделайте 1414676 - 28 = 1,414,648 = 0x1595F8

Затем я пишу 0x1595F8 как 25-28 байт, только предшествующий mdat atom. Итак, заголовок теперь выглядит следующим образом:

00 00 00 18 66 74 79 70 33 67 70 34 00 00 03 00 33 67 70 34 33 67 70 36 00 15 95 F8

И когда я пытаюсь воспроизвести его с помощью mplayer, я получаю поврежденный видео и аудио выход. Здесь часть из вывода mplayer:

[amrwb @ 0x7f72ad652380]Frame too small (33 bytes). Truncated file?
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
[amrwb @ 0x7f72ad652380]Frame too small (33 bytes). Truncated file?
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
A:  11.0 V:   1.4 A-V:  9.650 ct:  0.023   0/  0 10%  1%  1.6% 0 0                                                        
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f72adeafc40]stream 1, offset 0x15e62b: partial file
[h263 @ 0x7f72ad652380]Bad picture start code
[h263 @ 0x7f72ad652380]header damaged
Error while decoding frame!
[h263 @ 0x7f72ad652380]Bad picture start code
[h263 @ 0x7f72ad652380]header damaged
Error while decoding frame!
[h263 @ 0x7f72ad652380]Bad picture start code
[h263 @ 0x7f72ad652380]header damaged
Error while decoding frame!
A:  11.1 V:   1.5 A-V:  9.558 ct:  0.027   0/  0  9%  1%  1.4% 0 0                                                        
[h263 @ 0x7f72ad652380]Bad picture start code
[h263 @ 0x7f72ad652380]header damaged
Error while decoding frame!

Что я делаю неправильно?

4b9b3361

Ответ 1

Что вам нужно понять, так это то, что mp4 не является живым потоковым форматом. следовательно, вы никак не сможете взломать его, чтобы сделать его в прямом эфире. Заголовок [moov atom] записывается в конце. Android создает таблицу памяти с размерами фрейма и другими параметрами, которые затем записывает в начале файла в конце записи, из-за чего ему нужна поисковая способность дескриптора файла. [который нет сокета]

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

Если вам отчаянно нужна полная кодировка файлов, потому что вы не уверены в моем предыдущем параграфе, то для кодирования используйте что-то вроде ffmpeg. Измените его, дайте сам зашифрованный вывод и снова сохраните его на жесткий диск - снова удалите часть сокета.

Невозможно сделать live потоковое воспроизведение файлов mp4 в android. Я видел, как много людей пытались это напрасно, и если вы понимаете видео/форматы, вы не можете это сделать. mp4 не предназначен для прямой трансляции. Если вы заранее не знаете размеры фрейма [что у вас нет] и точную длину кодировки, которую вы, вероятно, не знаете, t], вы не можете предварительно создать заголовок.

пс. mp4 и 3gp являются кузенами, поэтому применяется то же самое.

Многие люди путают потоковое видео с http pd и псевдопотоком. Прямая трансляция означает, что у меня нет всего файла, он создается, а также транслируется "на лету". http pd и pseudo streaming происходят с файлами, которые полностью доступны.

EDIT:

Если вы хотите зашифровать записанный файл перед сохранением в SD-карте, вам нужна поддержка кодировщика. Это подразумевает получение вашего собственного кодера. Возьмите ffmpeg, перекрестно скомпилируйте его в android. Напишите небольшой интерфейс JNI для вашего приложения. Получите это сначала без шифрования. После выполнения, когда ffmpeg переписывает поток, добавьте свой модуль шифрования. То же самое при декодировании. Создание Y3ng. Это самый чистый способ сделать это.

ИЗМЕНИТЬ 2: Смотрите spydroid, чтобы получить некоторые функции для вас. Там есть похожие.

РЕДАКТИРОВАТЬ 3: Чтобы улучшить качество ответа, я объясняю неполное обходное решение, которое также дается другими ответами:

По-прежнему можно передавать AV, анализируя mp4 по мере его создания и отправки элементарных потоков отдельно по сокету. Единственная проблема, с которой вы столкнетесь, заключается в том, что вы не получите идеальную синхронизацию AV, поскольку вы не знаете точные временные метки AV-образца. Об этом знает только андроид, и он пишет, что в заголовке mp4 в конце. Так что тебе нехорошо. Вы должны делать предположение о идеальной частоте дискретизации видеокадров, и ваш звук должен быть amr, чтобы принимать 20 мс-пакеты. В других звуковых случаях вы начнете видеть дрейф в длинных прогонах [особенно, когда вы начинаете иметь сцены с высоким движением]. Это связано с тем, что каждый генерируемый звуковой пакет не соответствует фиксированной длительности времени [кроме amr и других речевых кодеков]

Ответ 2

Прежде всего, не совсем понятно, что вы пытаетесь сделать.

Вы хотите просто сохранить видео программно в воспроизводимый файл? Если это так, вам просто нужно использовать дескриптор файла вместо unix-сокета. Этот API-интерфейс MediaRecord был разработан для работы с файлом (не Unix-сокетом) именно по причине случайного доступа. Итак, первым моим советом будет использование файлового дескриптора, и вы получите правильный файл в конце записи.

Здесь можно привести примеры: Как записать видеозапись на Android?

В случае, если вы пытаетесь написать приложение, которое передает видео с устройства, вам нужно будет анализировать поток в режиме реального времени, делить его на фреймы и отправлять кадры отдельно. И самая сложная часть - синтаксический анализ потока (некоторые видеокодеки, как пример H263, могут быть проанализированы, а другие не могут быть, особенно если данные чередуются с аудио).

Я считаю, что один из этих двух проектов реализует такие функции: http://sipdroid.org/ http://code.google.com/p/imsdroid/