Pregunta

¿Cómo escribir mapas de bits como marcos para ogg teora en c c ++?

¡Algunos ejemplos con fuente serían rejilla!)

¿Fue útil?

Solución

Aquí esta la API de Libtheora y código de ejemplo.

Aquí está un Micro Howto Eso muestra cómo usar los binarios teora. Mientras el codificador lee Datos de 'YUV4MPEG' brutos, sin comprimir para video También podría usar eso desde su aplicación, vitiendo los marcos de video al codificador.

Otros consejos

Toda la solución es un poco larga para publicar aquí como una muestra de código, pero si descarga LibTheora de xiph.org, hay un ejemplo de PNG2Theora. Todas las funciones de la biblioteca que estoy a punto de mencionar se pueden encontrar en la documentación en xiph.org para Theora y OGG.

  1. Llame a th_info_init () para inicializar una estructura th_info, luego configure sus parámetros de salida asignando a los miembros apropiados en eso.
  2. Use esa estructura en una llamada a th_encode_alloc () para obtener un contexto del codificador
  3. Inicializar una secuencia OGG, con OGG_STREAM_INIT ()
  4. Inicializar una estructura en blanco TH_COMMent usando th_comment_init

Iterar a través de lo siguiente:

  1. Llame a th_encode_flushheader con el contexto del codificador, la estructura de comentarios en blanco y un ogg_packet.
  2. Envíe el paquete resultante al flujo OGG con OGG_STREAM_PACKETIN ()

Hasta que th_encode_flushheader devuelva 0 (o un código de error)

Ahora, llame repetidamente a OGG_STREAM_PAGEOUT (), cada vez que escribe la página.header y luego Page.Body a un archivo de salida, hasta que devuelva 0. Ahora llame a OGG_STREAM_FLUSH y escriba la página resultante en el archivo.

Ahora puede escribir marcos al codificador. Así es como lo hice:

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;
}

Donde coderInfo es la estructura th_info utilizada para inicializar el codificador (estático en la sección de datos para mí).

En su último cuadro, configurar el último cuadro en th_encode_packetout () se asegurará de que la secuencia termine correctamente.

Una vez terminado, solo asegúrese de limpiar (cerrar FDS principalmente). th_info_clar () borrará la estructura th_info, y th_encode_free () liberará el contexto del codificador.

Obviamente, deberá convertir su mapa de bits en planos YUV antes de poder pasarlos a Theora_Write_Frame ().

Espero que esto sea de alguna ayuda. ¡Buena suerte!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top