/modules/Codec/Avidemux-EditorPlugin/avidemux-2.4.4/avidemux/ADM_outputs/oplug_avi/op_avisave.cpp
C++ | 518 lines | 378 code | 73 blank | 67 comment | 34 complexity | 710b63740b17fe87ddc823cd7823213f MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, GPL-3.0
- /***************************************************************************
- op_avisave.cpp - description
- -------------------
- begin : Fri May 3 2002
- copyright : (C) 2002 by mean
- email : fixounet@free.fr
- ***************************************************************************/
- /***************************************************************************
- * *
- * 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. *
- * *
- ***************************************************************************/
-
- /*
- * MODIFIED BY GMV 30.1.05: prepared for ODML
- */
-
- #include "config.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <unistd.h>
- #include <time.h>
- #include <sys/time.h>
- #include <pthread.h>
- #define WIN32_CLASH
- #include "fourcc.h"
- #include "avi_vars.h"
- #include "ADM_toolkit/toolkit.hxx"
- #include "subchunk.h"
- //#include "avilist.h"
- #include "ADM_video/ADM_genvideo.hxx"
- #include "ADM_filter/video_filters.h"
- #include "ADM_encoder/ADM_vidEncode.hxx"
- #include "ADM_assert.h"
- #include "ADM_audio/aviaudio.hxx"
- #include "ADM_audiofilter/audioprocess.hxx"
- #include "oplug_avi/op_aviwrite.hxx"
- #include "oplug_avi/op_avisave.h"
- #include "GUI_mux.h"
- uint32_t muxSize=4090;
- extern PARAM_MUX muxMode;
- extern int muxParam;
- #include "ADM_audiofilter/audioeng_buildfilters.h"
- #include "DIA_factory.h"
- const char *getStrFromAudioCodec( uint32_t codec);
- //_________________________
- uint8_t ADM_aviUISetMuxer( void )
- {
-
- // return DIA_setUserMuxParam ((int *) &muxMode, (int *) &muxParam, (int *) &muxSize);
- uint32_t mux_n_frame=muxParam;
- uint32_t mux_size_block=muxParam;
- uint32_t mux_mode=(uint32_t)muxMode;
-
-
- diaMenuEntry muxingType[]={
- {MUX_REGULAR,QT_TR_NOOP("Normal")},
- {MUX_N_FRAMES,QT_TR_NOOP("Mux every N video frames")},
- {MUX_N_BYTES,QT_TR_NOOP("Mux by packet size")}
- };
-
- diaElemMenu mux(&(mux_mode),QT_TR_NOOP("Muxing _type:"),3,muxingType);
- diaElemUInteger blockSize(&(muxSize),QT_TR_NOOP("_Split every MB:"),1,9000);
-
- diaElemUInteger n_frames(&(mux_n_frame),QT_TR_NOOP("Mux _every x video frames:"),1,100);
- diaElemUInteger n_block(&(mux_size_block),QT_TR_NOOP("Mux in _blocks of x bytes:"),1,50000);
-
-
- mux.link(&(muxingType[1]),1,&n_frames);
- mux.link(&(muxingType[2]),1,&n_block);
-
- diaElem *elems[4]={&mux,&n_frames,&n_block,&blockSize};
- if( diaFactoryRun(QT_TR_NOOP("AVI Muxer Options"),4,elems))
- {
- muxMode=(PARAM_MUX)mux_mode;
- switch(muxMode)
- {
- case MUX_REGULAR: muxParam=1;break;
- case MUX_N_FRAMES: muxParam=mux_n_frame;break;
- case MUX_N_BYTES: muxParam=mux_size_block;break;
- default: ADM_assert(0);
- }
- return 1;
- }
- return 0;
- };
- //_______ set the autosplit size
- uint8_t ADM_aviSetSplitSize(uint32_t size)
- {
- muxSize=size;
- return 1;
- }
- GenericAviSave::GenericAviSave ()
- {
- has_audio_track = has_audio_vbr = 0;
- vbuffer = new uint8_t[MAXIMUM_SIZE * MAXIMUM_SIZE * 3];
- // vbuffer=new ADMImage(MAXIMUM_SIZE,MAXIMUM_SIZE);
- abuffer = new uint8_t[96000];
- ADM_assert (vbuffer);
- ADM_assert (abuffer);
- audio_filter=NULL;
- audio_filter2=NULL;
- _part=0;
- dialog_work=NULL;
- _lastIPFrameSent=0xffffff;
- _incoming=NULL;
- encoding_gui=NULL;
- _videoProcess=0;
- _audioCurrent=_audioTarget=0;
- _audioTotal=0;
- _file=NULL;
- _pq=NULL;
- memset(&_context,0,sizeof(_context));
- _context.audioDone=1;
- _encode=NULL;
- }
- GenericAviSave::~GenericAviSave ()
- {
- cleanupAudio();
- delete[] vbuffer;
- delete[] abuffer;
- _incoming=NULL;
- ADM_assert(!_file);
- }
- uint8_t GenericAviSave::cleanupAudio (void)
- {
- printf("[AVI] Cleaning audio\n");
- if(_pq)
- {
- _pq->Abort();
- while(!_context.audioDone)
- {
- printf("Waiting Audio thread\n");
- ADM_usleep(500000);
- }
- if(_pq) delete _pq;
- _pq=NULL;
- }
- if(audio_filter)
- {
- deleteAudioFilter (audio_filter);
- audio_filter=NULL;
- }
- return 1;
- }
- //___________________________________________________________
- // Generic Save Avi loop
- //
- //___________________________________________________________
- //
- uint8_t GenericAviSave::saveAvi (const char *name)
- {
- uint32_t size;
- uint8_t ret=0;
- strcpy(_name,name);
- //frametogo = frameEnd - frameStart + 1;
- frametogo=0;
-
- writter = new aviWrite ();
- // 1- setup audio
- guiStart();
- if (!setupAudio ())
- {
- guiStop();
- GUI_Error_HIG (QT_TR_NOOP("Error initalizing audio filters"), NULL);
- delete writter;
- writter = NULL;
- return 0;
- }
-
- if (!setupVideo (_name))
- {
- guiStop();
- GUI_Error_HIG (QT_TR_NOOP("Error initalizing video filters"), NULL);
- delete writter;
- writter = NULL;
- // guiStop();
- return 0;
- }
-
- // 3- setup video
- frametogo=_incoming->getInfo()->nb_frames;
- fps1000=_incoming->getInfo()->fps1000;
- printf ("\n writing %lu frames\n", frametogo);
- //__________________________________
- // now go to main loop.....
- //__________________________________
- int frameDelay = 0;
- int videoSize;
- for (uint32_t cf = 0; cf < frametogo; cf++)
- {
- if (guiUpdate(cf, frametogo))
- goto abortme;
- for (;;)
- {
- videoSize = writeVideoChunk(cf + frameDelay);
- if (videoSize == 0 && _encode && (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH))
- {
- printf("skipping frame: %u size: %i\n", cf + frameDelay, videoSize);
- frameDelay++;
- }
- else
- break;
- }
- writeAudioChunk(cf);
- }
- ret=1;
- abortme:
- guiStop ();
- //__________________________________
- // and end save
- //__________________________________
- writter->setEnd ();
- delete writter;
- writter = NULL;
- // resync GUI
- printf ("\n Saving AVI (v_engine)... done\n");
- return ret;
- }
- //_________________________________________________________________
- //
- // Set up audio system
- //_________________________________________________________________
- uint8_t
- GenericAviSave::setupAudio (void)
- {
- // 1- Prepare audio filter
- //__________________________
- _audioInBuffer = 0;
- _audioTarget=_audioCurrent=0;
- _audioTotal=0;
- audio_filter=NULL;
- if(!currentaudiostream)
- {
- encoding_gui->setAudioCodec(QT_TR_NOOP("None"));
- return 1;
- }
- printf (" mux mode : %d mux param %d\n", muxMode, muxParam);
- if (audioProcessMode()) // else Raw copy mode
- {
- audio_filter = buildAudioFilter (currentaudiostream,video_body->getTime (frameStart));
- if(!audio_filter) return 0;
- encoding_gui->setAudioCodec(getStrFromAudioCodec(audio_filter->getInfo()->encoding));
- }
- else // copymode
- {
- // else prepare the incoming raw stream
- // audio copy mode here
- encoding_gui->setAudioCodec(QT_TR_NOOP("Copy"));
- audio_filter=buildAudioFilter( currentaudiostream,video_body->getTime (frameStart));
- if(!audio_filter) return 0;
- }
- /* Setup audioQ */
- pthread_t audioThread;
- _pq=new PacketQueue("AVI audioQ",5000,2*1024*1024);
- memset(&_context,0,sizeof(_context));
- _context.audioEncoder=audio_filter;
- _context.audioTargetSample=0xFFFF0000; ; //FIXME
- _context.packetQueue=_pq;
- // start audio thread
- ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&_context));
- ADM_usleep(4000);
- return 1;
- }
- //---------------------------------------------------------------------------
- uint8_t
- GenericAviSave::writeAudioChunk (uint32_t frame)
- {
- uint32_t len;
- // if there is no audio, we do nothing
- if (!audio_filter)
- return 1;
-
- double t;
-
- t=frame+1;
- t=t/fps1000;
- t=t*1000*audio_filter->getInfo()->frequency;
- _audioTarget=(uint32_t )floor(t);
- uint32_t sample,packetLen,packets=0;
- if(audio_filter->packetPerFrame()
- || audio_filter->isVBR() )
- {
- while(_audioCurrent<_audioTarget)
- {
- if(!_pq->Pop(abuffer,&packetLen,&sample))
- {
- return 0;
- }
- _audioCurrent+=sample;
- _audioTotal+=packetLen;
- writter->saveAudioFrame (packetLen,abuffer);
- encoding_gui->setAudioSize(_audioTotal);
- }
- return 1;
- }
- sample=0;
- // _audioTarget is the # of sample we want
- while(_audioCurrent<_audioTarget)
- {
- if(!_pq->Pop(abuffer+_audioInBuffer,&packetLen,&sample))
- {
- printf("AVIWR:Could not read packet\n");
- break;
- }
- _audioInBuffer+=packetLen;
- _audioTotal+=packetLen;
- _audioCurrent+=sample;
- packets++;
- }
- switch (muxMode)
- {
- case MUX_N_FRAMES:
- stored_audio_frame++;
- if (stored_audio_frame < muxParam)
- return 1;
- stored_audio_frame = 0;
- case MUX_REGULAR:
- break;
- case MUX_N_BYTES:
- if(_audioInBuffer<muxParam) return 1;
- break;
- break;
- default:
- ADM_assert (0);
- }
- if (_audioInBuffer)
- {
- writter->saveAudioFrame (_audioInBuffer, abuffer);
- encoding_gui->setAudioSize(_audioTotal);
- _audioInBuffer=0;
- }
- return 1;
-
- }
- void
- GenericAviSave::guiStart (void)
- {
- encoding_gui=new DIA_encoding(25000);
- encoding_gui->setCodec(QT_TR_NOOP("Copy"));
- encoding_gui->setFrame (0,0,2 ,100); // FXMe
- encoding_gui->setContainer(QT_TR_NOOP("AVI"));
- }
- void
- GenericAviSave::guiStop (void)
- {
- ADM_assert(encoding_gui);
- delete encoding_gui;
- encoding_gui=NULL;
- }
- void GenericAviSave::guiSetPhasis(const char *str)
- {
- ADM_assert(encoding_gui);
- encoding_gui->setPhasis(str);
-
- }
- uint8_t
- GenericAviSave::guiUpdate (uint32_t nb, uint32_t total)
- {
- ADM_assert(encoding_gui);
- //encoding_gui->setFrame (nb, 0,0, total); //FXMe
- if ( encoding_gui->isAlive () == 1)
- return 0;
- return 1;
- }
- // Return 1 if we exceed the chunk limit
- //
- uint8_t GenericAviSave::handleMuxSize ( void )
- {
- uint32_t pos;
-
- pos=writter->getPos();
- if(pos>=muxSize*1024*1024)
- {
- return 1 ;
-
- }
- return 0;
-
-
- }
- //
- // Finish the current avi and start a new one
- //
- uint8_t GenericAviSave::reigniteChunk( uint32_t dataLen, uint8_t *data )
- {
- // MOD Feb 2005 by GMV: ODML exit
- if(writter->doODML!=aviWrite::NO)return 1; // exit if odml has to be used
- // END MOD Feb 2005 by GMV
-
- // first end up the current chunk
- writter->setEnd ();
- delete writter;
- writter = NULL;
- // then create a new one
- writter = new aviWrite ();
-
- _part++;
- char n[500];
-
- sprintf(n,"%s%02d",_name,_part);
-
- printf("\n *** writing a new avi part :%s\n",n);
-
- if (!writter->saveBegin (n,
- &_mainaviheader,
- frameEnd - frameStart + 1,
- &_videostreamheader,
- &_bih,
- data,dataLen,
- audio_filter,
- audio_filter2))
- {
- GUI_Error_HIG (QT_TR_NOOP("Cannot initiate save"), NULL);
- return 0;
- }
- return 1;
- }
- /**
- Search Forward Reference frame from the current B frame
- */
- uint32_t GenericAviSave::searchForward(uint32_t startframe)
- {
- uint32_t fw=startframe;
- uint32_t flags;
- uint8_t r;
- while(1)
- {
- fw++;
- r=video_body->getFlags (fw, &flags);
- if(!(flags & AVI_B_FRAME))
- {
- return fw;
- }
- ADM_assert(r);
- if(!r)
- {
- printf("\n Could not locate last non B frame \n");
- return 0;
- }
- }
- }
- const char *getStrFromAudioCodec( uint32_t codec)
- {
- switch(codec)
- {
- case WAV_DTS: return QT_TR_NOOP("DTS");
- case WAV_PCM: return QT_TR_NOOP("PCM");
- case WAV_MP2: return QT_TR_NOOP("MP2");
- case WAV_MP3: return QT_TR_NOOP("MP3");
- case WAV_WMA: return QT_TR_NOOP("WMA");
- case WAV_LPCM: return QT_TR_NOOP("LPCM");
- case WAV_AC3: return QT_TR_NOOP("AC3");
- case WAV_OGG: return QT_TR_NOOP("Ogg Vorbis");
- case WAV_MP4: return QT_TR_NOOP("MP4");
- case WAV_AAC: return QT_TR_NOOP("AAC");
- case WAV_QDM2: return QT_TR_NOOP("QDM2");
- case WAV_AMRNB: return QT_TR_NOOP("AMR-NB");
- case WAV_MSADPCM: return QT_TR_NOOP("MSADPCM");
- case WAV_ULAW: return QT_TR_NOOP("ULAW");
- case WAV_IMAADPCM: return QT_TR_NOOP("IMA ADPCM");
- case WAV_8BITS_UNSIGNED:return QT_TR_NOOP("8-bit PCM");
- }
- return QT_TR_NOOP("Unknown codec");
- }
- //---------------------------------------
- // EOF