PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Avidemux/avidemux/ADM_outputs/oplug_avi/op_saveprocess.cpp

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