PageRenderTime 41ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Avidemux/avidemux/ADM_outputs/oplug_flv/oplug_flv.cpp

http://mulder.googlecode.com/
C++ | 370 lines | 275 code | 51 blank | 44 comment | 44 complexity | 871019a00f53d3f05192f21ec3d1ef31 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. oplug_flv.cpp - I/f to lavformat flash encoder
  3. -------------------
  4. copyright : (C) 2007 by mean
  5. email : fixounet@free.fr
  6. ***************************************************************************/
  7. /***************************************************************************
  8. * *
  9. * This program is free software; you can redistribute it and/or modify *
  10. * it under the terms of the GNU General Public License as published by *
  11. * the Free Software Foundation; either version 2 of the License, or *
  12. * (at your option) any later version. *
  13. * *
  14. ***************************************************************************/
  15. #define __STDC_LIMIT_MACROS
  16. #include <math.h>
  17. #include "config.h"
  18. #include "ADM_default.h"
  19. #include "ADM_threads.h"
  20. extern "C" {
  21. #include "ADM_lavcodec.h"
  22. };
  23. #include "ADM_editor/ADM_Video.h"
  24. //#include "ADM_colorspace/colorspace.h"
  25. #include "DIA_coreToolkit.h"
  26. #include "ADM_videoFilter.h"
  27. #include "ADM_videoFilter_internal.h"
  28. #include "ADM_encoder/ADM_vidEncode.hxx"
  29. #include "ADM_codecs/ADM_codec.h"
  30. #include "ADM_encoder/adm_encoder.h"
  31. #include "../oplug_mpegFF/oplug_vcdff.h"
  32. #include "ADM_userInterfaces/ADM_commonUI/DIA_encoding.h"
  33. #include "ADM_audiofilter/audioprocess.hxx"
  34. #include "ADM_audiofilter/audioeng_buildfilters.h"
  35. #include "../ADM_lavformat.h"
  36. #include "fourcc.h"
  37. #include "ADM_encoder/adm_encConfig.h"
  38. #include "ADM_encoder/ADM_vidEncode.hxx"
  39. #include "ADM_libraries/ADM_mplex/ADM_mthread.h"
  40. #include "ADM_toolkit/ADM_audioQueue.h"
  41. #include "ADM_osSupport/ADM_debugID.h"
  42. #define MODULE_NAME MODULE_MP4
  43. #include "ADM_osSupport/ADM_debug.h"
  44. extern const char *getStrFromAudioCodec( uint32_t codec);
  45. extern AVDMGenericAudioStream *mpt_getAudioStream(void);
  46. extern void UI_purge(void );
  47. extern uint32_t videoProcessMode (void);
  48. extern uint32_t frameStart,frameEnd;
  49. extern uint32_t audioProcessMode(void);
  50. extern AVDMGenericAudioStream *currentaudiostream;;
  51. static uint8_t *_buffer=NULL,*_outbuffer=NULL;
  52. extern uint8_t isVP6Compatible (uint32_t fourcc);
  53. /*
  54. * \fn Oplug_flv
  55. \brief Main function to save in flv format.
  56. It is very close to oplug_mp4 but somehow simplified as the following assumptions are made :
  57. * No b frame
  58. * No 2 pass encoding
  59. */
  60. uint8_t oplug_flv(const char *name)
  61. {
  62. AVDMGenericVideoStream *_incoming=NULL;
  63. AVDMGenericAudioStream *audio=NULL;
  64. uint8_t audioBuffer[48000];
  65. uint8_t *videoBuffer=NULL;
  66. uint32_t alen;//,flags;
  67. uint32_t size;
  68. uint32_t sample_got=0,sample;
  69. uint32_t extraDataSize=0;
  70. uint8_t *extraData=NULL;
  71. lavMuxer *muxer=NULL;
  72. aviInfo info;
  73. uint32_t width,height;
  74. DIA_encoding *encoding_gui=NULL;
  75. Encoder *_encode=NULL;
  76. uint32_t total=0;
  77. uint32_t videoExtraDataSize=0;
  78. uint8_t *videoExtraData=NULL;
  79. uint8_t *dummy,err;
  80. WAVHeader *audioinfo=NULL;
  81. int prefill=0;
  82. uint32_t displayFrame=0;
  83. ADMBitstream bitstream(0);
  84. uint8_t r=0;
  85. pthread_t audioThread;
  86. audioQueueMT context;
  87. PacketQueue *pq=NULL;//("MP4 audioQ",50,2*1024*1024);
  88. uint32_t totalAudioSize=0;
  89. int frameDelay = 0;
  90. bool receivedFrame = false;
  91. // Setup video
  92. if(videoProcessMode())
  93. {
  94. _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart);
  95. }else
  96. {
  97. _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart);
  98. }
  99. videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3];
  100. // Set global header encoding, needed for H264
  101. _encode = getVideoEncoder(1);
  102. total= _incoming->getInfo()->nb_frames;
  103. info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME
  104. //
  105. int supported=0;
  106. if(isVP6Compatible(info.fcc)) supported=1;
  107. if(fourCC::check(info.fcc,(const uint8_t *)"FLV1")) supported=1;
  108. if(!supported)
  109. {
  110. GUI_Error_HIG(QT_TR_NOOP("Unsupported video"),QT_TR_NOOP("Only FLV1 and VP6 video are supported"));
  111. goto stopit;
  112. }
  113. /* Check audio, we support only mp3 right now
  114. * 44100, 22050, 11025 only!
  115. * */
  116. if(currentaudiostream)
  117. {
  118. uint32_t audioCodec=0;
  119. uint32_t fq=currentaudiostream->getInfo()->frequency;
  120. if(audioProcessMode())
  121. {
  122. audioCodec=audioFilter_getOuputCodec();
  123. fq=audioFilter_getOuputFrequency(fq);
  124. }else
  125. { // copy
  126. audioCodec=currentaudiostream->getInfo()->encoding;
  127. }
  128. if(audioCodec!=WAV_MP3 )
  129. {
  130. GUI_Error_HIG(QT_TR_NOOP("Unsupported audio"),QT_TR_NOOP("Audio must be mp3 for flv output."));
  131. goto stopit;
  132. }
  133. if(fq!=44100 && fq!=22050 && fq!=11025)
  134. {
  135. GUI_Error_HIG(QT_TR_NOOP("Unsupported audio"),QT_TR_NOOP("Frequency must be 44100, 22050 or 11025 Hz."));
  136. goto stopit;
  137. }
  138. }
  139. encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000);
  140. bitstream.bufferSize=_incoming->getInfo()->width*_incoming->getInfo()->height*3;
  141. if (!_encode)
  142. {
  143. GUI_Error_HIG ("[FLV]",QT_TR_NOOP("Cannot initialize the video stream"));
  144. goto stopit;
  145. }
  146. // init compressor
  147. encoding_gui->setContainer(QT_TR_NOOP("FLV"));
  148. encoding_gui->setAudioCodec(QT_TR_NOOP("None"));
  149. if(!videoProcessMode())
  150. encoding_gui->setCodec(QT_TR_NOOP("Copy"));
  151. else
  152. encoding_gui->setCodec(_encode->getDisplayName());
  153. if (!_encode->configure (_incoming, 0))
  154. {
  155. GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL);
  156. goto stopit;
  157. };
  158. encoding_gui->setPhasis (QT_TR_NOOP("Encoding"));
  159. info.width=_incoming->getInfo()->width;
  160. info.height=_incoming->getInfo()->height;
  161. info.nb_frames=_incoming->getInfo()->nb_frames;
  162. info.fps1000=_incoming->getInfo()->fps1000;
  163. _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy);
  164. if(videoExtraDataSize)
  165. {
  166. printf("[FLV]We have extradata for video in copy mode (%d)\n",videoExtraDataSize);
  167. videoExtraData=new uint8_t[videoExtraDataSize];
  168. memcpy(videoExtraData,dummy,videoExtraDataSize);
  169. }
  170. ADM_assert(_encode);
  171. bitstream.data=videoBuffer;
  172. // ____________Setup audio__________________
  173. if(currentaudiostream)
  174. {
  175. audio=mpt_getAudioStream();
  176. if(!audio)
  177. {
  178. GUI_Error_HIG ("[FLV]",QT_TR_NOOP("Cannot initialize the audio stream"));
  179. goto stopit;
  180. }
  181. }
  182. if(audio)
  183. {
  184. audioinfo=audio->getInfo();
  185. audio->extraData(&extraDataSize,&extraData);
  186. if(audioProcessMode())
  187. encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding));
  188. else
  189. encoding_gui->setAudioCodec(QT_TR_NOOP("Copy"));
  190. }else
  191. {
  192. encoding_gui->setAudioCodec(QT_TR_NOOP("None"));
  193. }
  194. // ____________Setup Muxer _____________________
  195. muxer= new lavMuxer;
  196. if(!muxer->open(
  197. name,
  198. 2000000, // Muxrate
  199. MUXER_FLV,
  200. &info,videoExtraDataSize,videoExtraData,
  201. audioinfo,extraDataSize,extraData))
  202. goto stopit;
  203. //_____________ Loop _____________________
  204. encoding_gui->setContainer(QT_TR_NOOP("FLV"));
  205. if(!videoProcessMode())
  206. encoding_gui->setCodec(QT_TR_NOOP("Copy"));
  207. else
  208. encoding_gui->setCodec(_encode->getDisplayName());
  209. //
  210. UI_purge();
  211. //_____________ Start Audio thread _____________________
  212. if(audio)
  213. {
  214. pq=new PacketQueue("[FLV] audioQ",5000,2*1024*1024);
  215. memset(&context,0,sizeof(context));
  216. context.audioEncoder=audio;
  217. context.audioTargetSample=0xFFFF0000; ; //FIXME
  218. context.packetQueue=pq;
  219. // start audio thread
  220. ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context));
  221. ADM_usleep(4000);
  222. }
  223. //_____________GO !___________________
  224. for (uint32_t frame = 0; frame < total; frame++)
  225. {
  226. if (!encoding_gui->isAlive())
  227. {
  228. r = 0;
  229. break;
  230. }
  231. while(muxer->needAudio())
  232. {
  233. if(pq->Pop(audioBuffer,&alen,&sample))
  234. {
  235. if(alen)
  236. {
  237. muxer->writeAudioPacket(alen,audioBuffer,sample_got);
  238. totalAudioSize+=alen;
  239. encoding_gui->setAudioSize(totalAudioSize);
  240. sample_got+=sample;
  241. }
  242. }
  243. else
  244. {
  245. r = 0;
  246. break;
  247. }
  248. }
  249. for (;;)
  250. {
  251. bitstream.cleanup(frame);
  252. if (frame + frameDelay >= total)
  253. {
  254. if (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH)
  255. r = _encode->encode(UINT32_MAX, &bitstream);
  256. else
  257. r = 0;
  258. }
  259. else
  260. r = _encode->encode(frame + frameDelay, &bitstream);
  261. if (!r)
  262. {
  263. printf("Encoding of frame %lu failed!\n", frame);
  264. GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL);
  265. break;
  266. }
  267. else if (!receivedFrame && bitstream.len > 0)
  268. {
  269. if (!(bitstream.flags & AVI_KEY_FRAME))
  270. {
  271. GUI_Error_HIG (QT_TR_NOOP("KeyFrame error"), QT_TR_NOOP("The beginning frame is not a key frame.\nPlease move the A marker."));
  272. r = 0;
  273. break;
  274. }
  275. else
  276. receivedFrame = true;
  277. }
  278. if (bitstream.len == 0 && (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH))
  279. {
  280. printf("skipping frame: %u size: %i\n", frame + frameDelay, bitstream.len);
  281. frameDelay++;
  282. }
  283. else
  284. break;
  285. }
  286. if (!r)
  287. break;
  288. muxer->writeVideoPacket(&bitstream);
  289. encoding_gui->setFrame(frame, bitstream.len, bitstream.out_quantizer, total);
  290. }
  291. stopit:
  292. // Flush slave Q
  293. if(audio&& pq)
  294. {
  295. context.audioAbort=1;
  296. pq->Abort();
  297. // Wait for audio slave to be over
  298. while(!context.audioDone)
  299. {
  300. printf("[FLV]Waiting Audio thread\n");
  301. ADM_usleep(500000);
  302. }
  303. delete pq;
  304. }
  305. //
  306. if(muxer) muxer->close();
  307. if(encoding_gui) delete encoding_gui;
  308. if(videoBuffer) delete [] videoBuffer;
  309. if(muxer) delete muxer;
  310. if(_encode) delete _encode;
  311. if(videoExtraData) delete [] videoExtraData;
  312. // Cleanup
  313. deleteAudioFilter (audio);
  314. return r;
  315. }
  316. // EOF