/*********************************************************************************
*                             recordMyDesktop                                    *
**********************************************************************************
*                                                                                *
*             Copyright (C) 2006  John Varouhakis                                *
*                                                                                *
*                                                                                *
*    This program is free software; you can redistribute it and/or modify        *
*    it under the terms of the GNU General Public License as published by        *
*    the Free Software Foundation; either version 2 of the License, or           *
*    (at your option) any later version.                                         *
*                                                                                *
*    This program is distributed in the hope that it will be useful,             *
*    but WITHOUT ANY WARRANTY; without even the implied warranty of              *
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
*    GNU General Public License for more details.                                *
*                                                                                *
*    You should have received a copy of the GNU General Public License           *
*    along with this program; if not, write to the Free Software                 *
*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   *
*                                                                                *
*                                                                                *
*                                                                                *
*    For further information contact me at johnvarouhakis@gmail.com              *
**********************************************************************************/


#include <recordmydesktop.h>

void InitEncoder(ProgData *pdata,EncData *enc_data_t){
    int y1,y2;
    (pdata)->enc_data=enc_data_t;
    srand(time(NULL));
    y1=rand();
    y2=rand();
    y2+=(y1==y2);

    ogg_stream_init(&(enc_data_t)->m_ogg_ts,y1);
    if(!pdata->args.nosound)
        ogg_stream_init(&(enc_data_t)->m_ogg_vs,y2);
    
    (enc_data_t)->fp=fopen((pdata)->args.filename,"w");
    if((enc_data_t)->fp==NULL){
        fprintf(stderr,"Cannot open file %s for writting!\n",(pdata)->args.filename);
        exit(13);
    }    
    theora_info_init(&(enc_data_t)->m_th_inf);
    (enc_data_t)->m_th_inf.frame_width=(pdata)->brwin.rgeom.width;
    (enc_data_t)->m_th_inf.frame_height=(pdata)->brwin.rgeom.height;
    (enc_data_t)->m_th_inf.width=(((enc_data_t)->m_th_inf.frame_width + 15) >>4)<<4;
    (enc_data_t)->m_th_inf.height=(((enc_data_t)->m_th_inf.frame_height + 15) >>4)<<4;
    (enc_data_t)->m_th_inf.offset_x=(((enc_data_t)->m_th_inf.width-(enc_data_t)->m_th_inf.frame_width)/2)&~1;
    (enc_data_t)->m_th_inf.offset_y=(((enc_data_t)->m_th_inf.height-(enc_data_t)->m_th_inf.frame_height)/2)&~1;
    (enc_data_t)->m_th_inf.fps_numerator=((pdata)->args.fps*100.0);
    (enc_data_t)->m_th_inf.fps_denominator=100;
    (enc_data_t)->m_th_inf.aspect_numerator=1;//(pdata)->brwin.rgeom.width;
    (enc_data_t)->m_th_inf.aspect_denominator=1;//(pdata)->brwin.rgeom.height;
    (enc_data_t)->m_th_inf.colorspace=OC_CS_UNSPECIFIED;
    (enc_data_t)->m_th_inf.pixelformat=OC_PF_420;
    (enc_data_t)->m_th_inf.target_bitrate=(pdata)->args.v_bitrate;
    (enc_data_t)->m_th_inf.quality=(pdata)->args.v_quality;
    (enc_data_t)->m_th_inf.dropframes_p=(pdata)->args.dropframes;
    (enc_data_t)->m_th_inf.quick_p=1;
    (enc_data_t)->m_th_inf.keyframe_auto_p=1;
    (enc_data_t)->m_th_inf.keyframe_frequency=64;
    (enc_data_t)->m_th_inf.keyframe_frequency_force=64;
    (enc_data_t)->m_th_inf.keyframe_data_target_bitrate=(enc_data_t)->m_th_inf.quality*1.5;
    (enc_data_t)->m_th_inf.keyframe_auto_threshold=80;
    (enc_data_t)->m_th_inf.keyframe_mindistance=8;
    (enc_data_t)->m_th_inf.noise_sensitivity=1;
    (enc_data_t)->m_th_inf.sharpness=2;

    theora_encode_init(&(enc_data_t)->m_th_st,&(enc_data_t)->m_th_inf);



    if(!pdata->args.nosound){
        int ret;
        vorbis_info_init(&(enc_data_t)->m_vo_inf);
        ret = vorbis_encode_init_vbr(&(enc_data_t)->m_vo_inf,pdata->args.channels,pdata->args.frequency,(float)pdata->args.s_quality*0.1);
        if(ret){
            fprintf(stderr,"Error while setting up vorbis stream quality!\n");
            exit(2);
        }
        vorbis_comment_init(&(enc_data_t)->m_vo_cmmnt);
        vorbis_analysis_init(&(enc_data_t)->m_vo_dsp,&(enc_data_t)->m_vo_inf);
        vorbis_block_init(&(enc_data_t)->m_vo_dsp,&(enc_data_t)->m_vo_block);
    }

    
    theora_encode_header(&(enc_data_t)->m_th_st,&(enc_data_t)->m_ogg_pckt1);
    ogg_stream_packetin(&(enc_data_t)->m_ogg_ts,&(enc_data_t)->m_ogg_pckt1);
    if(ogg_stream_pageout(&(enc_data_t)->m_ogg_ts,&(enc_data_t)->m_ogg_pg)!=1){
        fprintf(stderr,"Internal Ogg library error.\n");
        exit(2);
    }
    fwrite((enc_data_t)->m_ogg_pg.header,1,(enc_data_t)->m_ogg_pg.header_len,(enc_data_t)->fp);
    fwrite((enc_data_t)->m_ogg_pg.body,1,(enc_data_t)->m_ogg_pg.body_len,(enc_data_t)->fp);

    theora_comment_init(&(enc_data_t)->m_th_cmmnt);
    theora_comment_add_tag(&(enc_data_t)->m_th_cmmnt,"recordMyDesktop",VERSION);
    theora_encode_comment(&(enc_data_t)->m_th_cmmnt,&(enc_data_t)->m_ogg_pckt1);
    ogg_stream_packetin(&(enc_data_t)->m_ogg_ts,&(enc_data_t)->m_ogg_pckt1);
    theora_encode_tables(&(enc_data_t)->m_th_st,&(enc_data_t)->m_ogg_pckt1);
    ogg_stream_packetin(&(enc_data_t)->m_ogg_ts,&(enc_data_t)->m_ogg_pckt1);


    if(!pdata->args.nosound){
        ogg_packet header;
        ogg_packet header_comm;
        ogg_packet header_code;
    
        vorbis_analysis_headerout(&(enc_data_t)->m_vo_dsp,&(enc_data_t)->m_vo_cmmnt,&header,&header_comm,&header_code);
        ogg_stream_packetin(&(enc_data_t)->m_ogg_vs,&header); 
        if(ogg_stream_pageout(&(enc_data_t)->m_ogg_vs,&(enc_data_t)->m_ogg_pg)!=1){
            fprintf(stderr,"Internal Ogg library error.\n");
            exit(2);
        }
        fwrite((enc_data_t)->m_ogg_pg.header,1,(enc_data_t)->m_ogg_pg.header_len,(enc_data_t)->fp);
        fwrite((enc_data_t)->m_ogg_pg.body,1,(enc_data_t)->m_ogg_pg.body_len,(enc_data_t)->fp);
    
        ogg_stream_packetin(&(enc_data_t)->m_ogg_vs,&header_comm);
        ogg_stream_packetin(&(enc_data_t)->m_ogg_vs,&header_code);
    }



    while(1){
        int result = ogg_stream_flush(&(enc_data_t)->m_ogg_ts,&(enc_data_t)->m_ogg_pg);
        if(result<0){
            fprintf(stderr,"Internal Ogg library error.\n");
            exit(2);
        }
        if(result==0)break;
        fwrite((enc_data_t)->m_ogg_pg.header,1,(enc_data_t)->m_ogg_pg.header_len,(enc_data_t)->fp);
        fwrite((enc_data_t)->m_ogg_pg.body,1,(enc_data_t)->m_ogg_pg.body_len,(enc_data_t)->fp);
    }

    if(!pdata->args.nosound){
        while(1){
            int result=ogg_stream_flush(&(enc_data_t)->m_ogg_vs,&(enc_data_t)->m_ogg_pg);
            if(result<0){
                fprintf(stderr,"Internal Ogg library error.\n");
                exit(2);
            }
            if(result==0)break;
            fwrite((enc_data_t)->m_ogg_pg.header,1,(enc_data_t)->m_ogg_pg.header_len,(enc_data_t)->fp);
            fwrite((enc_data_t)->m_ogg_pg.body,1,(enc_data_t)->m_ogg_pg.body_len,(enc_data_t)->fp);
        }
    }



    (enc_data_t)->yuv.y=(unsigned char *)malloc((enc_data_t)->m_th_inf.height*(enc_data_t)->m_th_inf.width);
    (enc_data_t)->yuv.u=(unsigned char *)malloc((enc_data_t)->m_th_inf.height*(enc_data_t)->m_th_inf.width/4);
    (enc_data_t)->yuv.v=(unsigned char *)malloc((enc_data_t)->m_th_inf.height*(enc_data_t)->m_th_inf.width/4);
    (enc_data_t)->yuv.y_width=(enc_data_t)->m_th_inf.width;
    (enc_data_t)->yuv.y_height=(enc_data_t)->m_th_inf.height;
    (enc_data_t)->yuv.y_stride=(enc_data_t)->m_th_inf.width;

    (enc_data_t)->yuv.uv_width=(enc_data_t)->m_th_inf.width/2;
    (enc_data_t)->yuv.uv_height=(enc_data_t)->m_th_inf.height/2;
    (enc_data_t)->yuv.uv_stride=(enc_data_t)->m_th_inf.width/2;
    (enc_data_t)->x_offset=(enc_data_t)->m_th_inf.offset_x;
    (enc_data_t)->y_offset=(enc_data_t)->m_th_inf.offset_y;
    theora_info_clear(&(enc_data_t)->m_th_inf);

}