PageRenderTime 136ms CodeModel.GetById 30ms RepoModel.GetById 14ms app.codeStats 0ms

/modules/Codec/Avidemux-EditorPlugin/avidemux-2.4.4/avidemux/ADM_outputs/oplug_avi/op_avisave.cpp

https://bitbucket.org/gianni/vaet
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
  1. /***************************************************************************
  2. op_avisave.cpp - description
  3. -------------------
  4. begin : Fri May 3 2002
  5. copyright : (C) 2002 by mean
  6. email : fixounet@free.fr
  7. ***************************************************************************/
  8. /***************************************************************************
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. ***************************************************************************/
  16. /*
  17. * MODIFIED BY GMV 30.1.05: prepared for ODML
  18. */
  19. #include "config.h"
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <math.h>
  23. #include <unistd.h>
  24. #include <time.h>
  25. #include <sys/time.h>
  26. #include <pthread.h>
  27. #define WIN32_CLASH
  28. #include "fourcc.h"
  29. #include "avi_vars.h"
  30. #include "ADM_toolkit/toolkit.hxx"
  31. #include "subchunk.h"
  32. //#include "avilist.h"
  33. #include "ADM_video/ADM_genvideo.hxx"
  34. #include "ADM_filter/video_filters.h"
  35. #include "ADM_encoder/ADM_vidEncode.hxx"
  36. #include "ADM_assert.h"
  37. #include "ADM_audio/aviaudio.hxx"
  38. #include "ADM_audiofilter/audioprocess.hxx"
  39. #include "oplug_avi/op_aviwrite.hxx"
  40. #include "oplug_avi/op_avisave.h"
  41. #include "GUI_mux.h"
  42. uint32_t muxSize=4090;
  43. extern PARAM_MUX muxMode;
  44. extern int muxParam;
  45. #include "ADM_audiofilter/audioeng_buildfilters.h"
  46. #include "DIA_factory.h"
  47. const char *getStrFromAudioCodec( uint32_t codec);
  48. //_________________________
  49. uint8_t ADM_aviUISetMuxer( void )
  50. {
  51. // return DIA_setUserMuxParam ((int *) &muxMode, (int *) &muxParam, (int *) &muxSize);
  52. uint32_t mux_n_frame=muxParam;
  53. uint32_t mux_size_block=muxParam;
  54. uint32_t mux_mode=(uint32_t)muxMode;
  55. diaMenuEntry muxingType[]={
  56. {MUX_REGULAR,QT_TR_NOOP("Normal")},
  57. {MUX_N_FRAMES,QT_TR_NOOP("Mux every N video frames")},
  58. {MUX_N_BYTES,QT_TR_NOOP("Mux by packet size")}
  59. };
  60. diaElemMenu mux(&(mux_mode),QT_TR_NOOP("Muxing _type:"),3,muxingType);
  61. diaElemUInteger blockSize(&(muxSize),QT_TR_NOOP("_Split every MB:"),1,9000);
  62. diaElemUInteger n_frames(&(mux_n_frame),QT_TR_NOOP("Mux _every x video frames:"),1,100);
  63. diaElemUInteger n_block(&(mux_size_block),QT_TR_NOOP("Mux in _blocks of x bytes:"),1,50000);
  64. mux.link(&(muxingType[1]),1,&n_frames);
  65. mux.link(&(muxingType[2]),1,&n_block);
  66. diaElem *elems[4]={&mux,&n_frames,&n_block,&blockSize};
  67. if( diaFactoryRun(QT_TR_NOOP("AVI Muxer Options"),4,elems))
  68. {
  69. muxMode=(PARAM_MUX)mux_mode;
  70. switch(muxMode)
  71. {
  72. case MUX_REGULAR: muxParam=1;break;
  73. case MUX_N_FRAMES: muxParam=mux_n_frame;break;
  74. case MUX_N_BYTES: muxParam=mux_size_block;break;
  75. default: ADM_assert(0);
  76. }
  77. return 1;
  78. }
  79. return 0;
  80. };
  81. //_______ set the autosplit size
  82. uint8_t ADM_aviSetSplitSize(uint32_t size)
  83. {
  84. muxSize=size;
  85. return 1;
  86. }
  87. GenericAviSave::GenericAviSave ()
  88. {
  89. has_audio_track = has_audio_vbr = 0;
  90. vbuffer = new uint8_t[MAXIMUM_SIZE * MAXIMUM_SIZE * 3];
  91. // vbuffer=new ADMImage(MAXIMUM_SIZE,MAXIMUM_SIZE);
  92. abuffer = new uint8_t[96000];
  93. ADM_assert (vbuffer);
  94. ADM_assert (abuffer);
  95. audio_filter=NULL;
  96. audio_filter2=NULL;
  97. _part=0;
  98. dialog_work=NULL;
  99. _lastIPFrameSent=0xffffff;
  100. _incoming=NULL;
  101. encoding_gui=NULL;
  102. _videoProcess=0;
  103. _audioCurrent=_audioTarget=0;
  104. _audioTotal=0;
  105. _file=NULL;
  106. _pq=NULL;
  107. memset(&_context,0,sizeof(_context));
  108. _context.audioDone=1;
  109. _encode=NULL;
  110. }
  111. GenericAviSave::~GenericAviSave ()
  112. {
  113. cleanupAudio();
  114. delete[] vbuffer;
  115. delete[] abuffer;
  116. _incoming=NULL;
  117. ADM_assert(!_file);
  118. }
  119. uint8_t GenericAviSave::cleanupAudio (void)
  120. {
  121. printf("[AVI] Cleaning audio\n");
  122. if(_pq)
  123. {
  124. _pq->Abort();
  125. while(!_context.audioDone)
  126. {
  127. printf("Waiting Audio thread\n");
  128. ADM_usleep(500000);
  129. }
  130. if(_pq) delete _pq;
  131. _pq=NULL;
  132. }
  133. if(audio_filter)
  134. {
  135. deleteAudioFilter (audio_filter);
  136. audio_filter=NULL;
  137. }
  138. return 1;
  139. }
  140. //___________________________________________________________
  141. // Generic Save Avi loop
  142. //
  143. //___________________________________________________________
  144. //
  145. uint8_t GenericAviSave::saveAvi (const char *name)
  146. {
  147. uint32_t size;
  148. uint8_t ret=0;
  149. strcpy(_name,name);
  150. //frametogo = frameEnd - frameStart + 1;
  151. frametogo=0;
  152. writter = new aviWrite ();
  153. // 1- setup audio
  154. guiStart();
  155. if (!setupAudio ())
  156. {
  157. guiStop();
  158. GUI_Error_HIG (QT_TR_NOOP("Error initalizing audio filters"), NULL);
  159. delete writter;
  160. writter = NULL;
  161. return 0;
  162. }
  163. if (!setupVideo (_name))
  164. {
  165. guiStop();
  166. GUI_Error_HIG (QT_TR_NOOP("Error initalizing video filters"), NULL);
  167. delete writter;
  168. writter = NULL;
  169. // guiStop();
  170. return 0;
  171. }
  172. // 3- setup video
  173. frametogo=_incoming->getInfo()->nb_frames;
  174. fps1000=_incoming->getInfo()->fps1000;
  175. printf ("\n writing %lu frames\n", frametogo);
  176. //__________________________________
  177. // now go to main loop.....
  178. //__________________________________
  179. int frameDelay = 0;
  180. int videoSize;
  181. for (uint32_t cf = 0; cf < frametogo; cf++)
  182. {
  183. if (guiUpdate(cf, frametogo))
  184. goto abortme;
  185. for (;;)
  186. {
  187. videoSize = writeVideoChunk(cf + frameDelay);
  188. if (videoSize == 0 && _encode && (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH))
  189. {
  190. printf("skipping frame: %u size: %i\n", cf + frameDelay, videoSize);
  191. frameDelay++;
  192. }
  193. else
  194. break;
  195. }
  196. writeAudioChunk(cf);
  197. }
  198. ret=1;
  199. abortme:
  200. guiStop ();
  201. //__________________________________
  202. // and end save
  203. //__________________________________
  204. writter->setEnd ();
  205. delete writter;
  206. writter = NULL;
  207. // resync GUI
  208. printf ("\n Saving AVI (v_engine)... done\n");
  209. return ret;
  210. }
  211. //_________________________________________________________________
  212. //
  213. // Set up audio system
  214. //_________________________________________________________________
  215. uint8_t
  216. GenericAviSave::setupAudio (void)
  217. {
  218. // 1- Prepare audio filter
  219. //__________________________
  220. _audioInBuffer = 0;
  221. _audioTarget=_audioCurrent=0;
  222. _audioTotal=0;
  223. audio_filter=NULL;
  224. if(!currentaudiostream)
  225. {
  226. encoding_gui->setAudioCodec(QT_TR_NOOP("None"));
  227. return 1;
  228. }
  229. printf (" mux mode : %d mux param %d\n", muxMode, muxParam);
  230. if (audioProcessMode()) // else Raw copy mode
  231. {
  232. audio_filter = buildAudioFilter (currentaudiostream,video_body->getTime (frameStart));
  233. if(!audio_filter) return 0;
  234. encoding_gui->setAudioCodec(getStrFromAudioCodec(audio_filter->getInfo()->encoding));
  235. }
  236. else // copymode
  237. {
  238. // else prepare the incoming raw stream
  239. // audio copy mode here
  240. encoding_gui->setAudioCodec(QT_TR_NOOP("Copy"));
  241. audio_filter=buildAudioFilter( currentaudiostream,video_body->getTime (frameStart));
  242. if(!audio_filter) return 0;
  243. }
  244. /* Setup audioQ */
  245. pthread_t audioThread;
  246. _pq=new PacketQueue("AVI audioQ",5000,2*1024*1024);
  247. memset(&_context,0,sizeof(_context));
  248. _context.audioEncoder=audio_filter;
  249. _context.audioTargetSample=0xFFFF0000; ; //FIXME
  250. _context.packetQueue=_pq;
  251. // start audio thread
  252. ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&_context));
  253. ADM_usleep(4000);
  254. return 1;
  255. }
  256. //---------------------------------------------------------------------------
  257. uint8_t
  258. GenericAviSave::writeAudioChunk (uint32_t frame)
  259. {
  260. uint32_t len;
  261. // if there is no audio, we do nothing
  262. if (!audio_filter)
  263. return 1;
  264. double t;
  265. t=frame+1;
  266. t=t/fps1000;
  267. t=t*1000*audio_filter->getInfo()->frequency;
  268. _audioTarget=(uint32_t )floor(t);
  269. uint32_t sample,packetLen,packets=0;
  270. if(audio_filter->packetPerFrame()
  271. || audio_filter->isVBR() )
  272. {
  273. while(_audioCurrent<_audioTarget)
  274. {
  275. if(!_pq->Pop(abuffer,&packetLen,&sample))
  276. {
  277. return 0;
  278. }
  279. _audioCurrent+=sample;
  280. _audioTotal+=packetLen;
  281. writter->saveAudioFrame (packetLen,abuffer);
  282. encoding_gui->setAudioSize(_audioTotal);
  283. }
  284. return 1;
  285. }
  286. sample=0;
  287. // _audioTarget is the # of sample we want
  288. while(_audioCurrent<_audioTarget)
  289. {
  290. if(!_pq->Pop(abuffer+_audioInBuffer,&packetLen,&sample))
  291. {
  292. printf("AVIWR:Could not read packet\n");
  293. break;
  294. }
  295. _audioInBuffer+=packetLen;
  296. _audioTotal+=packetLen;
  297. _audioCurrent+=sample;
  298. packets++;
  299. }
  300. switch (muxMode)
  301. {
  302. case MUX_N_FRAMES:
  303. stored_audio_frame++;
  304. if (stored_audio_frame < muxParam)
  305. return 1;
  306. stored_audio_frame = 0;
  307. case MUX_REGULAR:
  308. break;
  309. case MUX_N_BYTES:
  310. if(_audioInBuffer<muxParam) return 1;
  311. break;
  312. break;
  313. default:
  314. ADM_assert (0);
  315. }
  316. if (_audioInBuffer)
  317. {
  318. writter->saveAudioFrame (_audioInBuffer, abuffer);
  319. encoding_gui->setAudioSize(_audioTotal);
  320. _audioInBuffer=0;
  321. }
  322. return 1;
  323. }
  324. void
  325. GenericAviSave::guiStart (void)
  326. {
  327. encoding_gui=new DIA_encoding(25000);
  328. encoding_gui->setCodec(QT_TR_NOOP("Copy"));
  329. encoding_gui->setFrame (0,0,2 ,100); // FXMe
  330. encoding_gui->setContainer(QT_TR_NOOP("AVI"));
  331. }
  332. void
  333. GenericAviSave::guiStop (void)
  334. {
  335. ADM_assert(encoding_gui);
  336. delete encoding_gui;
  337. encoding_gui=NULL;
  338. }
  339. void GenericAviSave::guiSetPhasis(const char *str)
  340. {
  341. ADM_assert(encoding_gui);
  342. encoding_gui->setPhasis(str);
  343. }
  344. uint8_t
  345. GenericAviSave::guiUpdate (uint32_t nb, uint32_t total)
  346. {
  347. ADM_assert(encoding_gui);
  348. //encoding_gui->setFrame (nb, 0,0, total); //FXMe
  349. if ( encoding_gui->isAlive () == 1)
  350. return 0;
  351. return 1;
  352. }
  353. // Return 1 if we exceed the chunk limit
  354. //
  355. uint8_t GenericAviSave::handleMuxSize ( void )
  356. {
  357. uint32_t pos;
  358. pos=writter->getPos();
  359. if(pos>=muxSize*1024*1024)
  360. {
  361. return 1 ;
  362. }
  363. return 0;
  364. }
  365. //
  366. // Finish the current avi and start a new one
  367. //
  368. uint8_t GenericAviSave::reigniteChunk( uint32_t dataLen, uint8_t *data )
  369. {
  370. // MOD Feb 2005 by GMV: ODML exit
  371. if(writter->doODML!=aviWrite::NO)return 1; // exit if odml has to be used
  372. // END MOD Feb 2005 by GMV
  373. // first end up the current chunk
  374. writter->setEnd ();
  375. delete writter;
  376. writter = NULL;
  377. // then create a new one
  378. writter = new aviWrite ();
  379. _part++;
  380. char n[500];
  381. sprintf(n,"%s%02d",_name,_part);
  382. printf("\n *** writing a new avi part :%s\n",n);
  383. if (!writter->saveBegin (n,
  384. &_mainaviheader,
  385. frameEnd - frameStart + 1,
  386. &_videostreamheader,
  387. &_bih,
  388. data,dataLen,
  389. audio_filter,
  390. audio_filter2))
  391. {
  392. GUI_Error_HIG (QT_TR_NOOP("Cannot initiate save"), NULL);
  393. return 0;
  394. }
  395. return 1;
  396. }
  397. /**
  398. Search Forward Reference frame from the current B frame
  399. */
  400. uint32_t GenericAviSave::searchForward(uint32_t startframe)
  401. {
  402. uint32_t fw=startframe;
  403. uint32_t flags;
  404. uint8_t r;
  405. while(1)
  406. {
  407. fw++;
  408. r=video_body->getFlags (fw, &flags);
  409. if(!(flags & AVI_B_FRAME))
  410. {
  411. return fw;
  412. }
  413. ADM_assert(r);
  414. if(!r)
  415. {
  416. printf("\n Could not locate last non B frame \n");
  417. return 0;
  418. }
  419. }
  420. }
  421. const char *getStrFromAudioCodec( uint32_t codec)
  422. {
  423. switch(codec)
  424. {
  425. case WAV_DTS: return QT_TR_NOOP("DTS");
  426. case WAV_PCM: return QT_TR_NOOP("PCM");
  427. case WAV_MP2: return QT_TR_NOOP("MP2");
  428. case WAV_MP3: return QT_TR_NOOP("MP3");
  429. case WAV_WMA: return QT_TR_NOOP("WMA");
  430. case WAV_LPCM: return QT_TR_NOOP("LPCM");
  431. case WAV_AC3: return QT_TR_NOOP("AC3");
  432. case WAV_OGG: return QT_TR_NOOP("Ogg Vorbis");
  433. case WAV_MP4: return QT_TR_NOOP("MP4");
  434. case WAV_AAC: return QT_TR_NOOP("AAC");
  435. case WAV_QDM2: return QT_TR_NOOP("QDM2");
  436. case WAV_AMRNB: return QT_TR_NOOP("AMR-NB");
  437. case WAV_MSADPCM: return QT_TR_NOOP("MSADPCM");
  438. case WAV_ULAW: return QT_TR_NOOP("ULAW");
  439. case WAV_IMAADPCM: return QT_TR_NOOP("IMA ADPCM");
  440. case WAV_8BITS_UNSIGNED:return QT_TR_NOOP("8-bit PCM");
  441. }
  442. return QT_TR_NOOP("Unknown codec");
  443. }
  444. //---------------------------------------
  445. // EOF