Удаление видеокадров - PullRequest
       2

Удаление видеокадров

0 голосов
/ 19 ноября 2010

мой вопрос довольно прост, я думаю.И это больше о математике, чем кодировании.Я получаю 15 кадров в секунду с веб-камеры.Но я должен отбросить некоторые из них.Например, если клиент запрашивает 8 кадров в секунду - я пропускаю каждый второй кадр, и это нормально.Но как мне отказаться, если запрашиваются 12 или 6 кадров в секунду?

Я думаю, что есть какой-то общий алгоритм для распределения значений.Большое спасибо!

Ответы [ 5 ]

3 голосов
/ 23 ноября 2010

По сути, вам нужно углубиться в концепцию FPS.

FPS X означает, что кадр отображается для отображения каждые 1 / X с, и он остается видимым на дисплее в течение 1 / X с. Обычно кадры обновляются на дисплее при каждой вертикальной синхронизации устройства отображения.

Теперь с помощью этой информации преобразование частоты кадров можно визуализировать как декодирование декодера во временное отображение на входном FPS, а сэмплер - отображение кадров на конечном дисплее на выходном FPS. Сэмплер производит выборку кадров с временного дисплея, на котором декодер обновляет кадры. Эта логика должна обеспечивать синхронизацию между декодером и сэмплером так, чтобы сэмплер не заканчивал выборкой частично обновленных кадров.

Эта логика работает как для уменьшения, так и для увеличения FPS.

Это может быть реализовано как одиночный буфер с синхронизированным доступом. Теперь позвольте декодеру записать в этот буфер на входном FPS, а сэмплер выберет кадр из этого буфера и отобразит на выходе fps.

Это обеспечит равномерное обновление экрана и отображение последнего доступного кадра при вертикальной синхронизации.

3 голосов
/ 19 ноября 2010

Способ, которым я видел это (например, в gstreamer), состоит в том, чтобы иметь два асинхронных цикла, один из которых принимает кадры с камеры, а другой отправляет кадры клиенту. У последнего цикла есть только последний захваченный кадр с камеры, доступный для него, и поэтому кадры, которые не «подхвачены» клиентом, автоматически отбрасываются, поскольку они перезаписываются следующим входящим кадром.

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

2 голосов
/ 19 ноября 2010

Опуская каждый 2-й кадр на 8 кадров в секунду, если у вас 15 кадров в секунду, вы вводите ошибку.

Это очень простой алгоритм, который будет работать во всех случаях:

#include <iostream>

double t = 0.0;

const double fps1 = 15.0;
const double fps2 = 12.0;

const double t1 = 1.0 / fps1;
const double t2 = 1.0 / fps2;

// true - drop the frame
// false - do NOT drop the frame
bool NextTick()
{
  t += t1;
  if ( t > t2 )
  {
    t -= t2;
    return false;
  }
  return true;
}

int main()
{
  for ( unsigned int i =0;i<20;++i)
  {
      if ( NextTick() )
      {
          std::cout<<"dropping the frame"<<std::endl;
      }
      else
      {
          std::cout<<"display the frame"<<std::endl;
      }
  }
}
1 голос
/ 19 ноября 2010

Имейте кольцевой буфер, достаточно большой, чтобы держать 1 полную секунду видео.

В этот буфер записывают каждый видеокадр. Обновите переменную, указывающую на то, что было записано в.

В отдельном потоке используйте таймер для задержки периода 1000 / требуемый_фпс (84 мс для 12 к / с), выберите последний записанный кадр и отправьте его.

0 голосов
/ 22 ноября 2010

Что вы можете сказать о таком решении:

У меня 15 статических байтовых констант с 0 и 1.1 - показать кадр, 0 - нет.Когда я получаю кадр, я увеличиваю счетчик cnt = [0..15] и смотрю, куда он указывает - ноль или единица.Вот так я решаю, показывать или удалять кадр.

Я думаю, что это решение проще и быстрее, чем внедрение нового потока.

...