如何将位图作为帧写入C中的Ogg Theora?

时间:2011-03-17 14:26:31

标签: c encoder ogg-theora

非常简单的编码器需要整个解决方案。编码器必须只向外部文件写入1帧Theora / OGG,并由VLC查看 根据{{​​3}}

我创建,遵循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个字节长。我的步骤有什么问题?

1 个答案:

答案 0 :(得分:0)

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

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

尝试将其替换为:

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