如何用 C 将位图作为框架写入 Ogg Theora?

发布于 2024-10-23 14:25:58 字数 6829 浏览 6 评论 0原文

需要非常简单的编码器的完整解决方案。编码器必须仅写入 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

檐上三寸雪 2024-10-30 14:25:58
fwrite(og.body,1,sizeof(og.body),fout);

这是不正确的。 sizeof(og.body) 是一个编译时常量,测量 struct ogg_page 中成员 body 的大小,它是一个指针(因此通常为 4 或 8 个字节)。

尝试将其替换为:

fwrite(og.body, og.body_len, 1, fout);
fwrite(og.body,1,sizeof(og.body),fout);

This is incorrect. sizeof(og.body) is a compile-time constant measuring the size of the member body in struct ogg_page, which is a pointer (so usually 4 or 8 bytes).

Try replacing that with:

fwrite(og.body, og.body_len, 1, fout);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文