Android - Включите встроенные функции StageFright в мой собственный проект - PullRequest
14 голосов
/ 23 марта 2012

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

Я успешно записал AAC (в контейнере MP4), используя MediaRecorder , и успешно передал аудио с использованием класса AudioRecord . Но мне нужно иметь возможность кодировать звук во время его потоковой передачи, но ни один из этих классов, похоже, не помогает мне в этом.

Я немного исследовал и обнаружил, что большинство людей, у которых есть эта проблема, используют нативную библиотеку, такую ​​как ffmpeg .

Но мне было интересно, поскольку Android уже включает StageFright , который имеет собственный код, который может выполнять кодирование и декодирование (например, AAC-кодирование и AAC-декодирование ), есть ли способ использовать этот нативный код в моем приложении? Как я могу это сделать?

Было бы замечательно, если бы мне нужно было только реализовать некоторые классы JNI с их собственным кодом. Кроме того, поскольку это библиотека Android, проблем с лицензированием не возникнет (поправьте меня, если я ошибаюсь).

1 Ответ

17 голосов
/ 03 мая 2012

да, вы можете использовать libstagefright, это очень мощно.

Поскольку stagefright не предоставляется NDK, вам придется проделать дополнительную работу.

Существует два способа:

(1) создать свой проект с использованием полного исходного кода Androidдерево.Этот способ установки занимает несколько дней, когда он готов, он очень прост, и вы можете в полной мере воспользоваться stagefright.

(2) вы можете просто скопировать включаемый файл в ваш проект, он находится внутри этой папки:

android-4.0.4_r1.1 / frameworks / base / include / media / stagefright

, тогда у вас будет возможность экспортировать библиотечную функцию путем динамической загрузки libstagefright.so, и вы можете связать ее с jniпроект.

Для кодирования / декодирования с использованием statgefright это очень просто, может подойти несколько сотен строк.

Я использовал stagefright для захвата скриншотов для создания видео, которое будет доступно внаш Android VNC-сервер, который скоро будет выпущен.

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

class ImageSource : public MediaSource {
   ImageSource(int width, int height, int colorFormat)
    : mWidth(width),
      mHeight(height),
      mColorFormat(colorFormat)
   {
   }

   virtual status_t read(
        MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
       // here you can fill the buffer with your pixels
   }

   ...
};

int width = 720;
int height = 480;
sp<MediaSource> img_source = new ImageSource(width, height, colorFormat);

sp<MetaData> enc_meta = new MetaData;
// enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
// enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
enc_meta->setInt32(kKeyWidth, width);
enc_meta->setInt32(kKeyHeight, height);
enc_meta->setInt32(kKeySampleRate, kFramerate);
enc_meta->setInt32(kKeyBitRate, kVideoBitRate);
enc_meta->setInt32(kKeyStride, width);
enc_meta->setInt32(kKeySliceHeight, height);
enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
enc_meta->setInt32(kKeyColorFormat, colorFormat);

sp<MediaSource> encoder =
    OMXCodec::Create(
            client.interface(), enc_meta, true, image_source);

sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/screenshot.mp4");
writer->addSource(encoder);

// you can add an audio source here if you want to encode audio as well
// 
//sp<MediaSource> audioEncoder =
//    OMXCodec::Create(client.interface(), encMetaAudio, true, audioSource);
//writer->addSource(audioEncoder);

writer->setMaxFileDuration(kDurationUs);
CHECK_EQ(OK, writer->start());
while (!writer->reachedEOS()) {
    fprintf(stderr, ".");
    usleep(100000);
}
err = writer->stop();
...