diff options
| author | iovar <iovar@f606c939-3180-4ac9-a4b8-4b8779d57d0a> | 2006-12-10 10:03:43 +0000 | 
|---|---|---|
| committer | iovar <iovar@f606c939-3180-4ac9-a4b8-4b8779d57d0a> | 2006-12-10 10:03:43 +0000 | 
| commit | 8eebfc55196d58b8cf957d92dc5959675de4dc8b (patch) | |
| tree | 5f1b03e1094ef4c579a0e5d3c9f8e35e27581980 /recordmydesktop/src/flush_to_ogg.c | |
| parent | bf02a88599e0e03d822eae3d30afdacd67c98457 (diff) | |
multiplexing of vorbis-theora streams corrected
git-svn-id: https://recordmydesktop.svn.sourceforge.net/svnroot/recordmydesktop/trunk@228 f606c939-3180-4ac9-a4b8-4b8779d57d0a
Diffstat (limited to 'recordmydesktop/src/flush_to_ogg.c')
| -rw-r--r-- | recordmydesktop/src/flush_to_ogg.c | 152 | 
1 files changed, 117 insertions, 35 deletions
| diff --git a/recordmydesktop/src/flush_to_ogg.c b/recordmydesktop/src/flush_to_ogg.c index 8fa762f..2390810 100644 --- a/recordmydesktop/src/flush_to_ogg.c +++ b/recordmydesktop/src/flush_to_ogg.c @@ -26,55 +26,137 @@  #include <recordmydesktop.h> +//we copy the page because the next call to ogg_stream_pageout +//will invalidate it. But we must have pages from both streams at every time in +//order to do correct multiplexing +void ogg_page_cp(ogg_page *new,ogg_page *old){ +    int i=0; +    register unsigned char *newp,*oldp; + +    new->header_len=old->header_len; +    new->header=malloc(new->header_len); +    new->body_len=old->body_len; +    new->body=malloc(new->body_len); + +    newp=new->header; +    oldp=old->header; +    for(i=0;i<new->header_len;i++) +        *(newp++)=*(oldp++); +    newp=new->body; +    oldp=old->body; +    for(i=0;i<new->body_len;i++) +        *(newp++)=*(oldp++); + +} +//free our copy +void ogg_page_cp_free(ogg_page *pg){ +    pg->header_len=pg->body_len=0; +    free(pg->header); +    free(pg->body); +} +  void *FlushToOgg(ProgData *pdata){      int videoflag=0,audioflag=0;      double video_bytesout=0,audio_bytesout=0; -    ogg_page videopage,audiopage; -    while(pdata->running){ -        pthread_mutex_lock(&pdata->libogg_mutex); -        videoflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_ts,&videopage); -        pthread_mutex_unlock(&pdata->libogg_mutex); -        if(videoflag){ -            video_bytesout+=fwrite(videopage.header,1,videopage.header_len,pdata->enc_data->fp); -            video_bytesout+=fwrite(videopage.body,1,videopage.body_len,pdata->enc_data->fp); -            videoflag=0; -            if(!pdata->args.nosound){ +    ogg_page    videopage,//owned by libogg +                videopage_copy,//owned by the application +                audiopage,//owned by libogg +                audiopage_copy;//owned by the application + +    double audiotime=0; +    double videotime=0; +    int working=1, +        th_st_fin=0, +        v_st_fin=(pdata->args.nosound); +    while(working){ +        int audio_or_video=0; +        if(pdata->running){ +            pthread_mutex_lock(&pdata->libogg_mutex); +            if(!videoflag){ +                videoflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_ts,&videopage); +                videotime=(videoflag)?theora_granule_time(&pdata->enc_data->m_th_st,ogg_page_granulepos(&videopage)):-1; +                if(videoflag)ogg_page_cp(&videopage_copy,&videopage); +            } +            if(!pdata->args.nosound) +                if(!audioflag){ +                    audioflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_vs,&audiopage); +                    audiotime=(audioflag)?vorbis_granule_time(&pdata->enc_data->m_vo_dsp,ogg_page_granulepos(&audiopage)):-1; +                    if(audioflag)ogg_page_cp(&audiopage_copy,&audiopage); +                } +            pthread_mutex_unlock(&pdata->libogg_mutex); +        } +        else{ +            if(!th_st_fin && !videoflag){                  pthread_mutex_lock(&pdata->libogg_mutex); -                audioflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_vs,&audiopage); +                videoflag=ogg_stream_flush(&pdata->enc_data->m_ogg_ts,&videopage); +                videotime=(videoflag)?theora_granule_time(&pdata->enc_data->m_th_st,ogg_page_granulepos(&videopage)):-1; +                if(videoflag)ogg_page_cp(&videopage_copy,&videopage);                  pthread_mutex_unlock(&pdata->libogg_mutex); -                if(audioflag){ -                    audio_bytesout+=fwrite(audiopage.header,1,audiopage.header_len,pdata->enc_data->fp); -                    audio_bytesout+=fwrite(audiopage.body,1,audiopage.body_len,pdata->enc_data->fp); -                    audioflag=0; -                } +                //we need the last page to properly close the stream +                if(!videoflag)SyncEncodeImageBuffer(pdata); +            } +            if(!pdata->args.nosound && !v_st_fin &&!audioflag){ +                pthread_mutex_lock(&pdata->libogg_mutex); +                audioflag=ogg_stream_flush(&pdata->enc_data->m_ogg_vs,&audiopage); +                audiotime=(audioflag)?vorbis_granule_time(&pdata->enc_data->m_vo_dsp,ogg_page_granulepos(&audiopage)):-1; +                if(audioflag)ogg_page_cp(&audiopage_copy,&audiopage); +                pthread_mutex_unlock(&pdata->libogg_mutex); +                //we need the last page to properly close the stream +                if(!audioflag)SyncEncodeSoundBuffer(pdata,NULL);              }          } -        else +        if(th_st_fin)videoflag=0; +        if(v_st_fin)audioflag=0; +        if((!audioflag && !v_st_fin && !pdata->args.nosound) || (!videoflag && !th_st_fin)){              usleep(10000); +            continue; +        } +        if(!audioflag){ +            audio_or_video=1; +        } +        else if(!videoflag) { +            audio_or_video=0; +        } +        else{ +            if(audiotime<videotime) +                audio_or_video=0; +            else +                audio_or_video=1; +        } +        if(audio_or_video==1){ +            video_bytesout+=fwrite(videopage_copy.header,1,videopage_copy.header_len,pdata->enc_data->fp); +            video_bytesout+=fwrite(videopage_copy.body,1,videopage_copy.body_len,pdata->enc_data->fp); +            videoflag=0; +            if(!pdata->running){ +                pthread_mutex_lock(&pdata->libogg_mutex); +                if(ogg_page_eos(&videopage_copy)) +                    th_st_fin=1; +                pthread_mutex_unlock(&pdata->libogg_mutex); +            } +            ogg_page_cp_free(&videopage_copy); +        } +        else{ +            audio_bytesout+=fwrite(audiopage_copy.header,1,audiopage_copy.header_len,pdata->enc_data->fp); +            audio_bytesout+=fwrite(audiopage_copy.body,1,audiopage_copy.body_len,pdata->enc_data->fp); +            audioflag=0; +            if(!pdata->running){ +                pthread_mutex_lock(&pdata->libogg_mutex); +                if(ogg_page_eos(&audiopage_copy)) +                    v_st_fin=1; +                pthread_mutex_unlock(&pdata->libogg_mutex); +            } +            ogg_page_cp_free(&audiopage_copy); +        } +        working=(!th_st_fin || !v_st_fin);      }      //last packages -    pdata->enc_data->m_ogg_ts.e_o_s=1; -    videoflag=ogg_stream_flush(&pdata->enc_data->m_ogg_ts,&videopage); -    if(videoflag){ -        video_bytesout+=fwrite(videopage.header,1,videopage.header_len,pdata->enc_data->fp); -        video_bytesout+=fwrite(videopage.body,1,videopage.body_len,pdata->enc_data->fp); -        videoflag=0; -    } -    if(!pdata->args.nosound){ -        pdata->enc_data->m_ogg_vs.e_o_s=1; -        do{ -            audioflag=ogg_stream_flush(&pdata->enc_data->m_ogg_vs,&audiopage); -            if(audioflag){ -                audio_bytesout+=fwrite(audiopage.header,1,audiopage.header_len,pdata->enc_data->fp); -                audio_bytesout+=fwrite(audiopage.body,1,audiopage.body_len,pdata->enc_data->fp); -                audioflag=0; -            } -        }while(!ogg_page_eos(&audiopage)); -    } + +    pthread_mutex_lock(&pdata->libogg_mutex);      ogg_stream_clear(&pdata->enc_data->m_ogg_ts);      if(!pdata->args.nosound)          ogg_stream_clear(&pdata->enc_data->m_ogg_vs); +    pthread_mutex_unlock(&pdata->libogg_mutex);  //this always gives me a segfault :(  //     theora_clear(&pdata->enc_data->m_th_st); | 
