Как написать растровые изображения в качестве фреймов для Ogg Theora в C \ C++?Как писать растровые изображения в качестве фреймов для Ogg Theora в C C++?
Некоторые примеры с источником будет натереть!)
Как написать растровые изображения в качестве фреймов для Ogg Theora в C \ C++?Как писать растровые изображения в качестве фреймов для Ogg Theora в C C++?
Некоторые примеры с источником будет натереть!)
Вот libtheora API и example code.
Вот micro howto, в котором показано, как использовать теоретические двоичные файлы. Поскольку кодировщик считывает необработанные, несжатые данные «yuv4mpeg» для видео, вы также можете использовать это из своего приложения, связав видеокадры с кодировщиком.
Все решение немного длиннее для публикации здесь в качестве образца кода, но если вы загружаете libtheora с Xiph.org, то есть пример png2theora. Все библиотечные функции, о которых я расскажу, можно найти в документации по Xiph.org для теорем и ogg.
перебирать следующее :
Пока th_encode_flushheader не возвращает 0 (или код ошибки)
Теперь, неоднократно называют ogg_stream_pageout(), каждый раз писать page.header а затем page.body в выходной файл, пока он не вернет 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().
Надеюсь, это поможет. Удачи!