Cómo escribir mapas de bits como marcos en Ogg Theora en C \ C++?Cómo escribir mapas de bits como marcos en Ogg Theora en C C++?
Algunos ejemplos serían fuente con rejilla!)
Cómo escribir mapas de bits como marcos en Ogg Theora en C \ C++?Cómo escribir mapas de bits como marcos en Ogg Theora en C C++?
Algunos ejemplos serían fuente con rejilla!)
Aquí está la libtheora API y example code.
Aquí hay un micro howto que muestra cómo usar los binarios theora. Como el codificador lee datos raw, descomprimidos 'yuv4mpeg' para el video, puede usarlo desde su aplicación, conectando los marcos de video al codificador.
La solución completa es un poco larga para publicar aquí como un ejemplo de código, pero si descarga libtheora de Xiph.org, hay un ejemplo png2theora. Todas las funciones de la biblioteca que voy a mencionar se pueden encontrar en la documentación en Xiph.org para theora y ogg.
Iterar a través del siguiente :
Hasta th_encode_flushheader devuelve 0 (o un código de error)
Ahora, en repetidas ocasiones llamar ogg_stream_pageout(), cada vez que escribir el page.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 cuadros en el codificador. Aquí es cómo 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;
}
Dónde encoderInfo es la estructura th_info utilizado para inicializar el codificador (estática en la sección de datos para mí).
En su último cuadro, establecer el último cuadro en th_encode_packetout() se asegurará de que la secuencia finalice correctamente.
Una vez hecho esto, solo asegúrese de limpiar (cerrar fds principalmente). th_info_clear() borrará la estructura th_info, y th_encode_free() liberará el contexto del codificador.
Obviamente, necesitará 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!