Come scrivere bitmap come frame su Ogg Theora in C \ C++?Come scrivere bitmap come frame su Ogg Theora in C C++?
Alcuni esempi con sorgente sarebbe grata!)
Come scrivere bitmap come frame su Ogg Theora in C \ C++?Come scrivere bitmap come frame su Ogg Theora in C C++?
Alcuni esempi con sorgente sarebbe grata!)
Ecco il libtheora API e example code.
Ecco uno micro howto che mostra come utilizzare i file binari di theora. Poiché l'encoder legge dati non compressi "yuv4mpeg" per il video, è possibile utilizzarlo anche dall'app, collegando i frame video all'encoder.
L'intera soluzione è un po 'lunga da postare qui come esempio di codice, ma se scarichi libtheora da Xiph.org, c'è un esempio di png2theora. Tutte le funzioni della libreria che sto per menzionare possono essere trovate nella documentazione su Xiph.org per theora e ogg.
Scorrere il seguente :
Fino th_encode_flushheader restituisce 0 (o un codice di errore)
Ora, chiamare ripetutamente ogg_stream_pageout(), ogni volta che scrivendo il page.header e quindi page.body in un file di output, finché non restituisce 0. Ora chiama ogg_stream_flush e scrivi la pagina risultante nel file.
Ora è possibile scrivere i frame nell'encoder. Ecco come ho fatto:
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;
}
Dove encoderInfo è la struttura th_info utilizzato per inizializzare l'encoder (statico nella sezione dati per me).
Sull'ultimo fotogramma, l'impostazione dell'ultimo fotogramma su th_encode_packetout() garantisce che lo streaming termina correttamente.
Una volta terminato, è sufficiente assicurarsi di eseguire la pulizia (chiusura di fds principalmente). th_info_clear() cancellerà la struttura th_info e th_encode_free() libererà il contesto del tuo codificatore.
Ovviamente, è necessario convertire la bitmap in piani YUV prima di poterli passare a theora_write_frame().
Spero che questo sia di qualche aiuto. In bocca al lupo!