PageRenderTime 61ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/gianni/vaet
C++ | 315 lines | 220 code | 56 blank | 39 comment | 33 complexity | af749437eebdeb698fe8bf82b401ae55 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, GPL-3.0
  1. /***************************************************************************
  2. op_saveprocess.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. #define __STDC_LIMIT_MACROS
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <math.h>
  20. #include <unistd.h>
  21. #include <time.h>
  22. #include <sys/time.h>
  23. #include "config.h"
  24. #include <pthread.h>
  25. #define WIN32_CLASH
  26. #include "fourcc.h"
  27. #include "avi_vars.h"
  28. #include "ADM_toolkit/toolkit.hxx"
  29. #include "subchunk.h"
  30. //#include "avilist.h"
  31. #include "ADM_audio/aviaudio.hxx"
  32. #include "ADM_audiofilter/audioprocess.hxx"
  33. #include "ADM_video/ADM_genvideo.hxx"
  34. //#include "ADM_gui/GUI_encoder.h"
  35. #include "ADM_filter/video_filters.h"
  36. #include "ADM_encoder/ADM_vidEncode.hxx"
  37. #include "oplug_avi/op_aviwrite.hxx"
  38. #include "oplug_avi/op_avisave.h"
  39. #include "ADM_encoder/adm_encoder.h"
  40. #include "oplug_avi/op_saveprocess.h"
  41. #include "ADM_osSupport/ADM_debugID.h"
  42. #define MODULE_NAME MODULE_SAVE_AVI
  43. #include "ADM_osSupport/ADM_debug.h"
  44. GenericAviSaveProcess::GenericAviSaveProcess( void )
  45. {
  46. TwoPassLogFile=NULL;
  47. _incoming=NULL;
  48. _videoProcess=1;
  49. };
  50. uint8_t
  51. GenericAviSaveProcess::setupVideo (char *name)
  52. {
  53. _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart);
  54. frametogo=_incoming->getInfo()->nb_frames;
  55. encoding_gui->setFps(_incoming->getInfo()->fps1000);
  56. // anish
  57. if(_incoming->getInfo()->width%8)
  58. {
  59. if(!GUI_Question(QT_TR_NOOP("Width is not a multiple of 8\n continue anyway ?")))
  60. return 0;
  61. }
  62. _encode = getVideoEncoder (_incoming->getInfo()->width,_incoming->getInfo()->height);
  63. if (!_encode)
  64. return 0;
  65. // init compressor
  66. TwoPassLogFile=new char[strlen(name)+6];
  67. strcpy(TwoPassLogFile,name);
  68. strcat(TwoPassLogFile,".stat");
  69. _encode->setLogFile(TwoPassLogFile,frametogo);
  70. if (!_encode->configure (_incoming))
  71. {
  72. delete _encode;
  73. _encode = NULL;
  74. GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL);
  75. return 0;
  76. };
  77. memcpy (&_bih, video_body->getBIH (), sizeof (_bih));
  78. _bih.biWidth = _incoming->getInfo ()->width;
  79. _bih.biHeight = _incoming->getInfo ()->height;
  80. _bih.biSize=sizeof(_bih);
  81. _bih.biXPelsPerMeter=_bih.biClrUsed=_bih.biYPelsPerMeter=0;
  82. _mainaviheader.dwTotalFrames= _incoming->getInfo ()->nb_frames;
  83. _mainaviheader.dwMicroSecPerFrame=0;
  84. printf("\n Saved as %ld x %ld\n",_bih.biWidth,_bih.biHeight);
  85. _bih.biCompression=fourCC::get((uint8_t *)_encode->getCodecName());
  86. encoding_gui->setCodec(_encode->getDisplayName());
  87. // init save avi
  88. //-----------------------2 Pass--------------------------------------
  89. if (_encode->isDualPass ())
  90. {
  91. uint8_t *buffer;
  92. uint32_t len, flag;
  93. FILE *tmp;
  94. uint8_t reuse=0;
  95. int r, frameDelay = 0;
  96. aprintf("\n** Dual pass encoding**\n");
  97. if((tmp=fopen(TwoPassLogFile,"rt")))
  98. {
  99. fclose(tmp);
  100. if(GUI_Question(QT_TR_NOOP("\n Reuse the existing log-file ?")))
  101. {
  102. reuse=1;
  103. }
  104. }
  105. if(!reuse)
  106. {
  107. guiSetPhasis (QT_TR_NOOP("1st Pass"));
  108. aprintf("**Pass 1:%lu\n",frametogo);
  109. buffer = new uint8_t[_incoming->getInfo ()->width *
  110. _incoming->getInfo ()->height * 3];
  111. _encode->startPass1 ();
  112. bitstream.bufferSize = _incoming->getInfo()->width * _incoming->getInfo()->height * 3;
  113. bitstream.data=buffer;
  114. for (uint32_t cf = 0; cf < frametogo; cf++)
  115. {
  116. if (guiUpdate (cf, frametogo))
  117. {
  118. abt:
  119. GUI_Error_HIG (QT_TR_NOOP("Aborting"), NULL);
  120. delete[] buffer;
  121. return 0;
  122. }
  123. for (;;)
  124. {
  125. bitstream.cleanup(cf);
  126. if (cf + frameDelay >= frametogo)
  127. {
  128. if (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH)
  129. r = _encode->encode(UINT32_MAX, &bitstream);
  130. else
  131. r = 0;
  132. }
  133. else
  134. r = _encode->encode(cf + frameDelay, &bitstream);
  135. if (!r)
  136. {
  137. printf("Encoding of frame %lu failed!\n", cf);
  138. goto abt;
  139. }
  140. if (bitstream.len == 0 && (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH))
  141. {
  142. printf("skipping frame: %u size: %i\n", cf + frameDelay, bitstream.len);
  143. frameDelay++;
  144. }
  145. else
  146. break;
  147. }
  148. encoding_gui->setFrame(cf,bitstream.len,bitstream.out_quantizer,frametogo);
  149. }
  150. encoding_gui->reset();
  151. delete[]buffer;
  152. aprintf("**Pass 1:done\n");
  153. }// End of reuse
  154. if(!_encode->startPass2 ())
  155. {
  156. printf("Pass2 ignition failed\n");
  157. return 0;
  158. }
  159. } //-------------------------/VBR-----------------------------------
  160. // init save avi
  161. // now we build the new stream !
  162. aprintf("**main pass:\n");
  163. memcpy(&_videostreamheader,video_body->getVideoStreamHeader (),sizeof(_videostreamheader));
  164. memcpy(&_videostreamheader.fccHandler ,_encode->getFCCHandler(),4);
  165. _videostreamheader.fccType =fourCC::get((uint8_t *)"vids");
  166. _videostreamheader.dwScale=1000;
  167. _videostreamheader.dwRate= _incoming->getInfo ()->fps1000;
  168. memcpy(&_mainaviheader ,video_body->getMainHeader (),sizeof(_mainaviheader));
  169. _mainaviheader.dwWidth=_bih.biWidth;
  170. _mainaviheader.dwHeight=_bih.biHeight;
  171. _videostreamheader.dwQuality=10000;
  172. uint8_t *data;
  173. uint32_t dataLen=0;
  174. _encode->hasExtraHeaderData( &dataLen,&data);
  175. if (!writter->saveBegin (name,
  176. &_mainaviheader,
  177. frameEnd - frameStart + 1,
  178. &_videostreamheader,
  179. &_bih,
  180. data,dataLen,
  181. (AVDMGenericAudioStream *) audio_filter,
  182. NULL))
  183. {
  184. return 0;
  185. }
  186. aprintf("Setup video done\n");
  187. bitstream.data=vbuffer;
  188. bitstream.bufferSize=MAXIMUM_SIZE * MAXIMUM_SIZE * 3;
  189. return 1;
  190. //---------------------
  191. }
  192. //
  193. // Just to keep gcc happy....
  194. //
  195. GenericAviSaveProcess::~GenericAviSaveProcess ()
  196. {
  197. cleanupAudio();
  198. if (_encode)
  199. delete _encode;
  200. _encode=NULL;
  201. if(TwoPassLogFile)
  202. {
  203. delete [] TwoPassLogFile;
  204. TwoPassLogFile=NULL;
  205. }
  206. }
  207. // copy mode
  208. // Basically ask a video frame and send it to writer
  209. int GenericAviSaveProcess::writeVideoChunk(uint32_t frame)
  210. {
  211. uint8_t r = 0;
  212. // CBR or CQ
  213. if (frame == 0)
  214. {
  215. encoding_gui->setCodec(_encode->getDisplayName());
  216. if (!_encode->isDualPass())
  217. guiSetPhasis (QT_TR_NOOP("Encoding"));
  218. else
  219. guiSetPhasis (QT_TR_NOOP("2nd Pass"));
  220. }
  221. bitstream.cleanup(frame);
  222. if (frame >= frametogo)
  223. {
  224. if (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH)
  225. r = _encode->encode(UINT32_MAX, &bitstream);
  226. }
  227. else
  228. r = _encode->encode(frame, &bitstream);
  229. if (!r)
  230. return -1;
  231. if (bitstream.len > 0)
  232. {
  233. _videoFlag=bitstream.flags;
  234. // check for split
  235. // check for auto split
  236. // if so, we re-write the last I frame
  237. if (muxSize)
  238. {
  239. // we overshot the limit and it is a key frame
  240. // start a new chunk
  241. if (handleMuxSize() && (_videoFlag & AVI_KEY_FRAME))
  242. {
  243. uint8_t *data;
  244. uint32_t dataLen = 0;
  245. _encode->hasExtraHeaderData(&dataLen,&data);
  246. if (!reigniteChunk(dataLen, data))
  247. return -1;
  248. }
  249. }
  250. encoding_gui->setFrame(frame >= frametogo ? frametogo - 1 : frame, bitstream.len, bitstream.out_quantizer, frametogo);
  251. if (!writter->saveVideoFrame (bitstream.len, _videoFlag, vbuffer))
  252. return -1;
  253. }
  254. return bitstream.len;
  255. }