如何用 C 将位图作为框架写入 Ogg Theora?
需要非常简单的编码器的完整解决方案。编码器必须仅写入 1 帧 Theora/OGG 到外部文件,并通过 VLC 查看 根据 如何将位图作为帧写入 Ogg C\C++ 中的 Theora?
我创建,遵循 Thalex 手册此代码(当然在我创建位图之前):
/*
####################################################################################
##
## fill ycbcr with bitmap
##
####################################################################################
*/
ycbcr[0].width = 640;
ycbcr[0].height = 480;
ycbcr[0].stride = 640;
ycbcr[0].data = (unsigned char*)Y_luma;
ycbcr[1].width = 320;
ycbcr[1].height = 240;
ycbcr[1].stride = 320;
ycbcr[1].data = (unsigned char*)Cb_chroma;
ycbcr[2].width = 320;
ycbcr[2].height = 240;
ycbcr[2].stride = 320;
ycbcr[2].data = (unsigned char*)Cr_chroma;
/*
####################################################################################
##
## Call th_info_init() to initialise a th_info structure, then set up you output
## parameters by assigning the appropriate members in that
##
####################################################################################
*/
th_info_init(&ti);
ti.frame_width = 640;
ti.frame_height = 480;
ti.pic_width = 640;
ti.pic_height = 480;
ti.pic_x = 0;
ti.pic_y = 0;
ti.fps_numerator = 1;
ti.fps_denominator = 1;
ti.aspect_numerator = 1;
ti.aspect_denominator = 1;
ti.colorspace = TH_CS_UNSPECIFIED;
ti.target_bitrate = 500;
ti.quality = 50;
ti.keyframe_granule_shift = 0;
ti.pixel_fmt = TH_PF_420;
/*
####################################################################################
##
## Use that structure in a call to th_encode_alloc() to get an encoder context
##
####################################################################################
*/
td = th_encode_alloc(&ti);
if(td==NULL)
{
printf("-E- negative return code initializing encoder!");
th_info_clear(&ti);
return false;
}
/*
####################################################################################
##
## Initialise a blank th_comment structure using th_comment_init
##
####################################################################################
*/
th_comment_init(&tc);
/*
####################################################################################
##
## Initialise an ogg stream, with ogg_stream_init()
##
####################################################################################
*/
ogg_stream_init(&to,rand());
if (th_encode_flushheader(td,&tc,&op)<=0)
{
printf("-E- Internal Theora Library Error!");
return false;
}
/*
####################################################################################
##
## Call th_encode_flushheader with the the encoder context, the blank comment
## structure and an ogg_packet.
##
####################################################################################
*/
if (th_encode_flushheader(td,&tc,&op)<=0)
{
printf("-E- Internal Theora Library Error!");
return false;
}
/* 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(td, ycbcr)) {
fprintf(stderr, "-E- Error: could not encode frame\n");
return -1;
}
if(!th_encode_packetout(td, 1, &op)) {
fprintf(stderr, "-E- [theora_write_frame] Error: could not read packets\n");
return -1;
}
/*
####################################################################################
##
## Send the resulting packet to the ogg stream with ogg_stream_packetin()
##
####################################################################################
*/
ogg_page og;
ogg_stream_packetin(&to,&op);
if (ogg_stream_pageout(&to,&og)!=1)
{
printf("-E- Internal Ogg library Error!");
return false;
}
/*
####################################################################################
##
## Until th_encode_flushheader returns 0 (or an error code)
## Now, repeatedly call ogg_stream_pageout(), every time writing the page.header and then page.body
## to an output file, until it returns 0.
## Now call ogg_stream_flush and write the resulting page to the file.
####################################################################################
*/
//int ret;
for(;;)
{
ret=th_encode_flushheader(td,&tc,&op);
if(ret<0)
{
printf("-E- Internal Theora library error.");
if (td!=NULL)
{
th_encode_free(td);
td=NULL;
}
th_comment_clear(&tc);
th_info_clear(&ti);
return false;
}
else if(!ret)
{ fwrite (og.header, 1 , sizeof(og.header) , fout );
fwrite (og.body, 1 , sizeof(og.body) , fout );
break;
}
ogg_stream_packetin(&to,&op);
}
int result;
for(;;){
int result = ogg_stream_flush(&to,&og);
if(result<0){
printf("-E- Internal Ogg library error.");
return false;
}
if(result==0)break;
fwrite(og.body,1,sizeof(og.body),fout);
}
但是生成的 ogg 文件只有 12 个字节长。我的步骤有什么问题吗?
Need entire solution for very simple encoder. Encoder must write to external file only 1 frame Theora/OGG, and viewed by VLC
acording to How to write bitmaps as frames to Ogg Theora in C\C++?
i create, follow Thalex manual this code (before i create bitmap of course):
/*
####################################################################################
##
## fill ycbcr with bitmap
##
####################################################################################
*/
ycbcr[0].width = 640;
ycbcr[0].height = 480;
ycbcr[0].stride = 640;
ycbcr[0].data = (unsigned char*)Y_luma;
ycbcr[1].width = 320;
ycbcr[1].height = 240;
ycbcr[1].stride = 320;
ycbcr[1].data = (unsigned char*)Cb_chroma;
ycbcr[2].width = 320;
ycbcr[2].height = 240;
ycbcr[2].stride = 320;
ycbcr[2].data = (unsigned char*)Cr_chroma;
/*
####################################################################################
##
## Call th_info_init() to initialise a th_info structure, then set up you output
## parameters by assigning the appropriate members in that
##
####################################################################################
*/
th_info_init(&ti);
ti.frame_width = 640;
ti.frame_height = 480;
ti.pic_width = 640;
ti.pic_height = 480;
ti.pic_x = 0;
ti.pic_y = 0;
ti.fps_numerator = 1;
ti.fps_denominator = 1;
ti.aspect_numerator = 1;
ti.aspect_denominator = 1;
ti.colorspace = TH_CS_UNSPECIFIED;
ti.target_bitrate = 500;
ti.quality = 50;
ti.keyframe_granule_shift = 0;
ti.pixel_fmt = TH_PF_420;
/*
####################################################################################
##
## Use that structure in a call to th_encode_alloc() to get an encoder context
##
####################################################################################
*/
td = th_encode_alloc(&ti);
if(td==NULL)
{
printf("-E- negative return code initializing encoder!");
th_info_clear(&ti);
return false;
}
/*
####################################################################################
##
## Initialise a blank th_comment structure using th_comment_init
##
####################################################################################
*/
th_comment_init(&tc);
/*
####################################################################################
##
## Initialise an ogg stream, with ogg_stream_init()
##
####################################################################################
*/
ogg_stream_init(&to,rand());
if (th_encode_flushheader(td,&tc,&op)<=0)
{
printf("-E- Internal Theora Library Error!");
return false;
}
/*
####################################################################################
##
## Call th_encode_flushheader with the the encoder context, the blank comment
## structure and an ogg_packet.
##
####################################################################################
*/
if (th_encode_flushheader(td,&tc,&op)<=0)
{
printf("-E- Internal Theora Library Error!");
return false;
}
/* 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(td, ycbcr)) {
fprintf(stderr, "-E- Error: could not encode frame\n");
return -1;
}
if(!th_encode_packetout(td, 1, &op)) {
fprintf(stderr, "-E- [theora_write_frame] Error: could not read packets\n");
return -1;
}
/*
####################################################################################
##
## Send the resulting packet to the ogg stream with ogg_stream_packetin()
##
####################################################################################
*/
ogg_page og;
ogg_stream_packetin(&to,&op);
if (ogg_stream_pageout(&to,&og)!=1)
{
printf("-E- Internal Ogg library Error!");
return false;
}
/*
####################################################################################
##
## Until th_encode_flushheader returns 0 (or an error code)
## Now, repeatedly call ogg_stream_pageout(), every time writing the page.header and then page.body
## to an output file, until it returns 0.
## Now call ogg_stream_flush and write the resulting page to the file.
####################################################################################
*/
//int ret;
for(;;)
{
ret=th_encode_flushheader(td,&tc,&op);
if(ret<0)
{
printf("-E- Internal Theora library error.");
if (td!=NULL)
{
th_encode_free(td);
td=NULL;
}
th_comment_clear(&tc);
th_info_clear(&ti);
return false;
}
else if(!ret)
{ fwrite (og.header, 1 , sizeof(og.header) , fout );
fwrite (og.body, 1 , sizeof(og.body) , fout );
break;
}
ogg_stream_packetin(&to,&op);
}
int result;
for(;;){
int result = ogg_stream_flush(&to,&og);
if(result<0){
printf("-E- Internal Ogg library error.");
return false;
}
if(result==0)break;
fwrite(og.body,1,sizeof(og.body),fout);
}
But the resulting ogg file is only 12 bytes long. What is wrong in my steps?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是不正确的。
sizeof(og.body)
是一个编译时常量,测量struct ogg_page
中成员body
的大小,它是一个指针(因此通常为 4 或 8 个字节)。尝试将其替换为:
This is incorrect.
sizeof(og.body)
is a compile-time constant measuring the size of the memberbody
instruct ogg_page
, which is a pointer (so usually 4 or 8 bytes).Try replacing that with: