PageRenderTime 53ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/Codec/Avidemux-EditorPlugin/avidemux-2.4.4/avidemux/ADM_outputs/oplug_flv/oplug_flv.cpp

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