#c #ffmpeg #callback
#c #ffmpeg #обратный вызов
Вопрос:
Я выделяю контекст AVIO с моей собственной read_packet()
реализацией. Только моя реализация такова, что я могу вернуться с count
меньшим, чем требуемый ввод buf_size
. Это разрешено? Или мы должны заполнять буфер как можно больше при каждом вызове read_packet()
функции выхода?
// initialization
[...snip...]
m_avio_context.reset(avio_alloc_context(
avio_buffer
, avio_buffer_size
, 0 // write flag
, this // opaque
, amp;FFMPEGDecoder::decoder_read_static
, nullptr // write func.
, nullptr)); // seek func.
[...snip...]
// implementation of static function
int FFMPEGDecoder::decoder_read_static(void * opaque, std::uint8_t * buf, int size)
{
return reinterpret_cast<FFMPEGDecoder *>(opaque)->decoder_read(buf, size);
}
// the actual read_packet()
int FFMPEGDecoder::decoder_read(std::uint8_t * buf, int size)
{
// in flushing mode, we won't receive any more packets
//
if(m_flushing)
{
return 0;
}
// m_packet is my own packet implementation (an std::vector<>)
//
while(m_packet == nullptr
|| static_cast<std::size_t>(m_read_pos) >= m_packet->size())
{
if(!m_incoming_packets.pop_front(m_packet, -1))
{
return 0;
}
if(m_packet->is_flush())
{
m_flushing = true;
return 0;
}
m_read_pos = 0;
}
// the number of bytes to copy size `size` or less if there are
// less bytes available in my m_packet
//
int const copy(std::min(static_cast<std::size_t>(size), m_packet->size() - m_read_pos));
memcpy(buf, m_packet->data().data() m_read_pos, copy);
m_read_pos = copy;
return copy;
}
Я не ищу способ заполнить буфер, я собираюсь реализовать его таким образом сейчас. Я ищу подтверждение (или нет), что библиотеки FFMPEG не способны принимать меньше size
байтов buf
при read_packet()
вызове нашего.
Вы знаете?
Комментарии:
1. Я размышляю здесь, но при декодировании видео, особенно в (живых) потоках, вы можете заранее не знать, что будет поступать из следующего потока, это может зависеть от содержимого текущих декодированных пакетов (например, В транспортном потоке могут быть необязательные заголовки, метаданные и т. Д.). Я не знаю, но для меня логично, чтобы «размер» был максимальным или около того, потому что фактическое количество зависит от декодирования и конкретной структуры данных, обнаруженных в необработанном вводе. Подсказкой для меня также является эта строка: ffmpeg.org/doxygen/3.1/avio__reading_8c_source.html 45:buf_size = FFMIN(buf_size, bd->размер)
2. Однако этот код заканчивается один раз
buf_size = 0
, что означает «конец файла» (т. Е. Они выполняются через один буфер; в моем случае я выполняю много буферов). Но, похоже, моя проблема была в другом месте, где я использовал поле неправильного размера (так много размеров!)3. Что-то еще, что кажется связанным с документами PyAV (это оболочка, но низкоуровневая): pyav.org/docs/develop/api /… см. Поле «задержка»: «Кодер или декодер требует промывки с нулевым вводом в конце, чтобы выдать полный и правильный вывод. (…) Декодеры: декодеримеет ненулевую задержку и должен быть передан с помощью avpkt->data = NULL, avpkt-> size = 0 в конце, чтобы получить отложенные данные до тех пор, пока декодер больше не будет возвращать кадры (…) Кодировщик должен быть передан с нулевыми данными в конце кодирования, пока кодировщикбольше не возвращает данные.
4. Также этот пример синтаксического анализа: pyav.org/docs/develop/cookbook/basics.html#parsing codec = av.CodecContext.create(‘h264’, ‘r’) при значении True: фрагмент = fh.read(1 << 16) пакеты = codec.parse(фрагмент) печать («Проанализированы {} пакеты из {} байт:».формат (len (пакеты), len (фрагмент))) для пакета в пакетах: (…) Файл считывается порциями по 64 КБ, пакеты анализируются и т.д., конечный может быть <64 КБ. Я предполагаю, что контекст кодека отслеживает совпадения между последовательными фрагментами и сохраняет его в другом буфере. В любом случае он должен запоминать текущие ключевые кадры и т. Д.
5. @Twenkid Да, конечный автомат сложный… Моя проблема была не в конце, это произошло бы по пути, появляются некоторые пробелы, когда звук переходит в 0s. Я мог бы еще раз протестировать и посмотреть, работает ли он сейчас без моего дополнительного цикла … похоже, что это сработает, но я думаю, что это также может зависеть от используемого декодера. С WAV-файлом это может работать нормально, с AAC или OGG это может привести к сбою… кто знает. Это плохо документировано.