LibAV - какой подход для захвата аудио и видео в реальном времени?
Я использую libav для кодирования необработанных кадров RGB24 в h264 и мультиплексирования в flv. Это работает все отлично, и я потратил более 48 часов без каких-либо проблем! Мой следующий шаг - добавить аудио в поток. Я буду записывать живое аудио и хочу кодировать его в реальном времени, используя speex, mp3 или nelly moser.
Справочная информация
Я новичок в цифровом аудио и, следовательно, могу делать что-то не так. Но в основном мое приложение получает "плавающий" буфер с чередованием аудио. Эта функция "audioIn" вызывается используемой платформой приложения. Буфер содержит 256 выборок на канал, а у меня 2 канала. Поскольку я могу смешивать терминологию, вот как я использую данные:
// input = array with audio samples
// bufferSize = 256
// nChannels = 2
void audioIn(float * input, int bufferSize, int nChannels) {
// convert from float to S16
short* buf = new signed short[bufferSize * 2];
for(int i = 0; i < bufferSize; ++i) { // loop over all samples
int dx = i * 2;
buf[dx + 0] = (float)input[dx + 0] * numeric_limits<short>::max(); // convert frame of the first channel
buf[dx + 1] = (float)input[dx + 1] * numeric_limits<short>::max(); // convert frame of the second channel
}
// add this to the libav wrapper.
av.addAudioFrame((unsigned char*)buf, bufferSize, nChannels);
delete[] buf;
}
Теперь, когда у меня есть буфер, где каждая выборка составляет 16 бит, я передаю это short* buffer
к моей обертке av.addAudioFrame()
функция. В этой функции я создаю буфер, прежде чем кодировать аудио. Из того, что я прочитал, AVCodecContext
аудио кодера устанавливает frame_size
, Этот frame_size должен соответствовать количеству выборок в буфере при вызове avcodec_encode_audio2()
, Почему я так думаю, это из-за того, что здесь задокументировано.
Затем, особенно строка: если она не установлена, frame->nb_samples
должен быть равен avctx->frame_size
для всех кадров, кроме последнего.*(Пожалуйста, исправьте меня здесь, если я ошибаюсь по этому поводу).
После кодировки звоню av_interleaved_write_frame()
на самом деле написать кадр. Когда я использую mp3 в качестве кодека, мое приложение работает в течение 1-2 минут, а затем мой сервер, который получает видео / аудио поток (flv, tcp), отключается с сообщением "Frame too large: 14485504
Msgstr "Это сообщение сгенерировано, потому что rtmp-сервер получает слишком большой кадр. И это, вероятно, связано с тем, что я неправильно чередую с libav.
Вопросы:
Там есть некоторые биты, в которых я не уверен, даже когда просматриваю исходный код libav, и поэтому я надеюсь, что у кого-то есть рабочий пример кодирования звука, который исходит из буфера, который исходит из "внешней" libav (то есть от вашего собственного приложение). т.е. как вы создаете буфер, который достаточно велик для кодировщика? Как заставить потоковую передачу "в реальном времени" работать, когда вам нужно ждать, пока этот буфер заполнится?
Как я уже писал выше, мне нужно отслеживать буфер, прежде чем я смогу кодировать. Есть ли у кого-то еще код, который делает это? Я использую AVAudioFifo сейчас. Функции, которые кодируют аудио и заполняют / читают буфер, также находятся здесь: https://gist.github.com/62f717bbaa69ac7196be
Я скомпилировал с --enable-debug=3 и отключил оптимизацию, но я не вижу никакой отладочной информации. Как я могу сделать libav более многословным?
Спасибо!