Как написать растровые карты в виде кадров для OGG Theora в C C ++?

StackOverflow https://stackoverflow.com/questions/1736304

  •  20-09-2019
  •  | 
  •  

Вопрос

Как написать растровые карты в виде кадров для OGG Theora в C C ++?

Некоторые примеры с источником были бы решеткой!)

Это было полезно?

Решение

Вот Libtheora Api а также пример кода.

Вот Микро Хоуто Это показывает, как использовать двоичные файлы Теоры. Как читает энкодер необработанные, несжатые данные YUV4MPEG для видео Вы также можете использовать это из своего приложения, передавая видео кадры в энкодер.

Другие советы

Все решение немного длинное, чтобы публиковать здесь как образец кода, но если вы загружаете Libtheora с xiph.org, есть пример png2theora. Все библиотечные функции, которые я собираюсь упомянуть, можно найти в документации на xiph.org для Theora и OGG.

  1. Вызовите TH_INFO_INIT (), чтобы инициализировать структуру TH_INFO, затем настройте выводы, выводя параметры, назначив соответствующие элементы в этом.
  2. Используйте эту структуру в вызове TH_ENCODE_ALLOC (), чтобы получить контекст кодера
  3. Инициализировать поток OGG, с OGG_STREAM_INIT ()
  4. Инициализировать пустую структуру th_comment с использованием th_comment_init

Итерация через следующее:

  1. Позвоните TH_ENCODE_FLUSHHEADER с контекстом кодера, пустой структурой комментариев и OGG_PACKET.
  2. Отправить полученный пакет в поток OGG с OGG_STREAM_PACKETIN ()

Пока th_encode_flushheader не вернет 0 (или код ошибки)

Теперь повторно вызовите OGG_STREAM_PAGEOUT (), каждый раз, когда записывает Page.Header, а затем Page.Bode в выходной файл, пока он не вернется 0. Теперь вызовите OGG_STREAM_FLUSH и запишите полученную страницу в файл.

Теперь вы можете написать кадры в энкодер. Вот как я это сделал:

int theora_write_frame(int outputFd, unsigned long w, unsigned long h, unsigned char *yuv_y, unsigned char *yuv_u, unsigned char *yuv_v, int last)
{
  th_ycbcr_buffer ycbcr;
  ogg_packet op;
  ogg_page og;

  unsigned long yuv_w;
  unsigned long yuv_h;

  /* Must hold: yuv_w >= w */
  yuv_w = (w + 15) & ~15;
  /* Must hold: yuv_h >= h */
  yuv_h = (h + 15) & ~15;

  //Fill out the ycbcr buffer
  ycbcr[0].width = yuv_w;
  ycbcr[0].height = yuv_h;
  ycbcr[0].stride = yuv_w;
  ycbcr[1].width = yuv_w;
  ycbcr[1].stride = ycbcr[1].width;
  ycbcr[1].height = yuv_h;
  ycbcr[2].width = ycbcr[1].width;
  ycbcr[2].stride = ycbcr[1].stride;
  ycbcr[2].height = ycbcr[1].height;

  if(encoderInfo->pixel_fmt == TH_PF_420)
  {
    //Chroma is decimated by 2 in both directions
    ycbcr[1].width = yuv_w >> 1;
    ycbcr[2].width = yuv_w >> 1;
    ycbcr[1].height = yuv_h >> 1;
    ycbcr[2].height = yuv_h >> 1;
  }else if(encoderInfo->pixel_fmt == TH_PF_422)
  {
    ycbcr[1].width = yuv_w >> 1;
    ycbcr[2].width = yuv_w >> 1;
  }else if(encoderInfo->pixel_fmt != TH_PF_422)
  {
    //Then we have an unknown pixel format
    //We don't know how long the arrays are!
    fprintf(stderr, "[theora_write_frame] Unknown pixel format in writeFrame!\n");
    return -1;
  }

  ycbcr[0].data = yuv_y;
  ycbcr[1].data = yuv_u;
  ycbcr[2].data = yuv_v;

  /* Theora is a one-frame-in,one-frame-out system; submit a frame
     for compression and pull out the packet */
  if(th_encode_ycbcr_in(encoderContext, ycbcr)) {
    fprintf(stderr, "[theora_write_frame] Error: could not encode frame\n");
    return -1;
  }

  if(!th_encode_packetout(encoderContext, last, &op)) {
    fprintf(stderr, "[theora_write_frame] Error: could not read packets\n");
    return -1;
  }

  ogg_stream_packetin(&theoraStreamState, &op);
  ssize_t bytesWritten = 0;
  int pagesOut = 0;
  while(ogg_stream_pageout(&theoraStreamState, &og)) {
    pagesOut ++;
    bytesWritten = write(outputFd, og.header, og.header_len);
    if(bytesWritten != og.header_len)
    {
      fprintf(stderr, "[theora_write_frame] Error: Could not write to file\n");
      return -1;
    }
    bytesWritten = write(outputFd, og.body, og.body_len);
    if(bytesWritten != og.body_len)
    {
      bytesWritten = fprintf(stderr, "[theora_write_frame] Error: Could not write to file\n");
      return -1;
    }
  }
  return pagesOut;
}

Где encoderinfo - это структура th_info, используемая для инициализации энкодера (статический в разделе данных для меня).

На вашем последнем кадре установка последнего кадра на TH_ENCODE_PACKETOUT () убедится, что поток заканчивается должным образом.

После того, как вы закончите, просто убедитесь, что убрать (в основном закрытие FDS). TH_INFO_CLEAR () очистит структуру TH_INFO, а TH_ENCODE_FREE () освободит ваш контекст кодера.

Очевидно, что вам нужно преобразовать растровое изображение в самолеты YUV, прежде чем вы сможете передать их в Theora_Write_frame ().

Надеюсь, это поможет. Удачи!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top