AudioCodec.cpp
上传用户:lusi_8715
上传日期:2007-01-08
资源大小:199k
文件大小:13k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /**************************************************************************************
  2.  *                                                                                    *
  3.  * This application contains code from OpenDivX and is released as a "Larger Work"    *
  4.  * under that license. Consistant with that license, this application is released     *
  5.  * under the GNU General Public License.                                              *
  6.  *                                                                                    *
  7.  * The OpenDivX license can be found at: http://www.projectmayo.com/opendivx/docs.php *
  8.  * The GPL can be found at: http://www.gnu.org/copyleft/gpl.html                      *
  9.  *                                                                                    *
  10.  * Copyright (c) 2001 - Project Mayo                                                  *
  11.  *                                                                                    *
  12.  * Authors: Damien Chavarria <adrc at projectmayo.com>                                *
  13.  *                                                                                    *
  14.  **************************************************************************************/
  15. #include "AudioCodec.h"
  16. /*
  17.  * Class functions
  18.  */
  19. /*
  20.  * Private wrapper 
  21.  * around my C functions
  22.  *
  23.  */
  24. int AudioCodec::DecompressMp3(char *outmemory, int outmemsize, int *done)
  25. {
  26. if(this->last_result == MP3_OK) {
  27. this->last_result = decodeMP3(&this->mp, NULL, 0, outmemory, outmemsize, done);
  28.     
  29.     if(this->last_result == MP3_NEED_MORE) {
  30.      
  31.       if( this->decaps->ReadAudio(this->in_buffer, 16384) != -1) {
  32.   this->last_result = decodeMP3(&this->mp, this->in_buffer, 16384, outmemory, outmemsize, done);
  33.   return 1;
  34.       }
  35.       else {
  36.   return 0;
  37.       }
  38.     }
  39.     else {
  40.       return 1;
  41.     }
  42.   }
  43.   else {
  44.     
  45.     if( this->decaps->ReadAudio(this->in_buffer, 16384) != -1) {
  46.       this->last_result = decodeMP3(&this->mp, this->in_buffer, 16384, outmemory, outmemsize, done);
  47.       return 1;
  48.     }
  49.     else {
  50.       
  51.       return 0;
  52.     }
  53.   }
  54. }
  55. /*
  56.  * Constructor : tries to init the stream
  57.  *
  58.  */
  59. AudioCodec::AudioCodec(AviDecaps *decaps, WAVEFORMATEX *lpWave)
  60. {
  61. this->mpeg        = 0;
  62. this->acm         = 0;
  63. this->in_buffer   = NULL;
  64. this->out_buffer  = NULL;
  65. this->oFormat     = NULL;
  66. memset(&this->mp, 0, sizeof(this->mp));
  67. if(lpWave) {
  68. this->decaps     = decaps;
  69. if(lpWave->wFormatTag == 85 /* MP3 */) {
  70. InitMP3(&this->mp);
  71.   
  72.     this->last_result = MP3_NEED_MORE;
  73.         ring_init();
  74. this->in_buffer  = (char *) malloc(INPUT_BUFFER_SIZE);
  75. this->out_buffer = (char *) malloc(65536);
  76. if(this->DecompressMp3(this->out_buffer, 16384, &this->real_size) == MP3_ERR) {
  77. ExitMP3(&this->mp);
  78.     return;
  79. }
  80. /*
  81.  * Buffering
  82.  */
  83. while(!ring_full(this->real_size))
  84. {
  85. this->DecompressMp3(this->out_buffer, 16384, &this->real_size);
  86.         ring_write(this->out_buffer, this->real_size);
  87. }
  88. this->mpeg    = 1;
  89. /*
  90.  * and sets up the output
  91.  * format for the renderer
  92.  */
  93. this->oFormat = (WAVEFORMATEX *) malloc(sizeof(WAVEFORMATEX));
  94. memcpy(this->oFormat, lpWave, sizeof(WAVEFORMATEX));
  95. this->oFormat->wFormatTag = WAVE_FORMAT_PCM;
  96. if (oFormat->wBitsPerSample != 8 && oFormat->wBitsPerSample != 16)
  97. oFormat->wBitsPerSample = 16;
  98. if (oFormat->nChannels!=1 && oFormat->nChannels!=2)
  99. oFormat->nChannels = 2;
  100. oFormat->nBlockAlign = (oFormat->wBitsPerSample/8) * oFormat->nChannels;
  101. oFormat->nAvgBytesPerSec =  oFormat->nBlockAlign * oFormat->nSamplesPerSec;
  102. oFormat->cbSize     =  0;
  103. }
  104. else {
  105. MMRESULT  mmres;
  106. this->oFormat = (WAVEFORMATEX *) malloc(sizeof(WAVEFORMATEX));
  107. memcpy(this->oFormat, lpWave, sizeof(WAVEFORMATEX));
  108. this->oFormat->wFormatTag = WAVE_FORMAT_PCM;
  109. mmres = acmStreamOpen(&hacm, NULL, lpWave, this->oFormat, NULL, NULL, 0, 0);
  110. if(mmres != 0) {
  111. /*
  112.  * No Audio
  113.  */
  114. return;
  115. }
  116. /*
  117.  * Here we have a valid stream
  118.  *
  119.  */
  120. ring_init();
  121. this->in_buffer  = (char *) malloc(INPUT_BUFFER_SIZE);
  122. this->out_buffer = (char *) malloc(256000);
  123. this->acmInLeft = 0;
  124. this->acmLeft   = 0;
  125. this->acm       = 1;
  126. //Decompress(this->out_buffer, 0);
  127. }
  128. }
  129. }
  130. /*
  131.  * Destructor: Cleanup.
  132.  *
  133.  */
  134. AudioCodec::~AudioCodec()
  135. {
  136. if(this->in_buffer != NULL) {
  137. free(this->in_buffer);
  138. }
  139. if(this->out_buffer) {
  140. free(this->out_buffer);
  141. }
  142. if(this->oFormat) {
  143. free(this->oFormat);
  144. }
  145. }
  146. /*
  147.  * Return TRUE is codec is
  148.  * ready to decompress
  149.  */
  150. BOOL AudioCodec::IsOK()
  151. {
  152. return (this->mpeg == 1 || this->acm == 1);
  153. }
  154. /*
  155.  * Return the output format
  156.  * (used by the renderer)
  157.  *
  158.  */
  159. WAVEFORMATEX *AudioCodec::GetFormat()
  160. {
  161. return this->oFormat;
  162. }
  163. /*
  164.  * Empty all buffers
  165.  *
  166.  */
  167. int AudioCodec::EmptyBuffers()
  168. {
  169. ring_init();
  170. if(this->mpeg) {
  171. this->last_result = MP3_NEED_MORE;
  172. ExitMP3(&this->mp);
  173. InitMP3(&this->mp);
  174. }
  175. return 1;
  176. }
  177. /*
  178.  * decompress size octets of
  179.  * audio to buffer
  180.  *
  181.  */
  182. int AudioCodec::Decompress(void *buffer, int size)
  183. {
  184. int  i;
  185. if(this->mpeg) {
  186. char msg[256];
  187. if(size == 0)
  188. return 1;
  189. if(size < 4096) {
  190. /*
  191.  * we only read once
  192.  */
  193. while(!ring_full(this->real_size)) {
  194.     
  195. if(this->DecompressMp3(this->out_buffer, 16384, &this->real_size) == 1) {
  196. ring_write(this->out_buffer, this->real_size);
  197. }
  198. else {
  199. return 0;
  200. }
  201. }
  202.   
  203. ring_read((char *) buffer, size);
  204. }
  205. else {
  206. int blocks = size / 4096;
  207. for(i = 0; i < blocks; i++) {
  208. while(!ring_full(this->real_size)) {
  209.     
  210. if(this->DecompressMp3(this->out_buffer, 16384, &this->real_size) == 1) {
  211. ring_write(this->out_buffer, this->real_size);
  212. }
  213. else {
  214. return 0;
  215. }
  216. }
  217.   
  218. ring_read(((char *) buffer) + i*4096, 4096);
  219. }
  220. /*
  221.  * the last bit
  222.  */
  223. int left = size - (blocks * 4096);
  224. if(left > 0)
  225. ring_read(((char *) buffer) + (blocks - 1)*4096, left);
  226. }
  227. }
  228. else {
  229. if(this->acm) {
  230. MMRESULT res;
  231. if(size < 4096) {
  232. if(this->acmLeft > 0 && !ring_full(this->acmLeft)) {
  233. /*
  234.  * Copy what we have left
  235.  */
  236. ring_write((char *) this->out_buffer, this->acmLeft);
  237. this->acmLeft = 0;
  238. }
  239. if(this->acmLeft > 0)
  240. goto done;
  241. if(!this->acmInLeft)
  242. this->decaps->ReadAudio(this->in_buffer, 2048);
  243. memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
  244. this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
  245. if(this->acmInLeft > 0) {
  246. this->acmHeader.pbSrc       = ((unsigned char *) this->in_buffer) + 2048 - this->acmInLeft;
  247. this->acmHeader.cbSrcLength = this->acmInLeft;
  248. this->acmInLeft = 0;
  249. }
  250. else {
  251. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  252. this->acmHeader.cbSrcLength = 2048;
  253. }
  254. this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
  255. this->acmHeader.cbDstLength = 256000;
  256. res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
  257. if(res > 0) {
  258. MessageBox(NULL, "Cannot prepare header!", "", MB_OK);
  259. }
  260. res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
  261. if(res > 0) {
  262. MessageBox(NULL, "Could not convert", "", MB_OK);
  263. }
  264. while(!ring_full(this->acmHeader.cbDstLengthUsed)) {
  265. /*
  266.  * We store it
  267.  */
  268. ring_write((char *) this->acmHeader.pbDst, this->acmHeader.cbDstLengthUsed);
  269. /*
  270.  * unprepare and start again
  271.  */
  272. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  273. if(!this->acmInLeft)
  274. this->decaps->ReadAudio(this->in_buffer, 2048);
  275. memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
  276. this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
  277. if(this->acmInLeft > 0) {
  278. this->acmHeader.pbSrc       = ((unsigned char *) this->in_buffer) + 2048 - this->acmInLeft;
  279. this->acmHeader.cbSrcLength = this->acmInLeft;
  280. this->acmInLeft = 0;
  281. }
  282. else {
  283. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  284. this->acmHeader.cbSrcLength = 2048;
  285. }
  286. this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
  287. this->acmHeader.cbDstLength = 256000;
  288. res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
  289. if(res > 0) {
  290. MessageBox(NULL, "Cannot prepare header!", "", MB_OK);
  291. }
  292. res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
  293. if(res > 0) {
  294. MessageBox(NULL, "Could not convert", "", MB_OK);
  295. }
  296. this->acmInLeft = 2048 - this->acmHeader.cbSrcLengthUsed;
  297. }
  298. this->acmLeft = this->acmHeader.cbDstLengthUsed;
  299. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  300. done:
  301. ring_read((char *) buffer, size);
  302. return 1;
  303. }
  304. else {
  305. int blocks = size / 4096;
  306. for(i = 0; i < blocks; i++) {
  307. if(this->acmLeft > 0 && !ring_full(this->acmLeft)) {
  308. /*
  309.  * Copy what we have left
  310.  */
  311. ring_write((char *) this->out_buffer, this->acmLeft);
  312. this->acmLeft = 0;
  313. }
  314. if(this->acmLeft > 0)
  315. goto done2;
  316. if(!this->acmInLeft)
  317. this->decaps->ReadAudio(this->in_buffer, 2048);
  318. memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
  319. this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
  320. if(this->acmInLeft > 0) {
  321. this->acmHeader.pbSrc       = ((unsigned char *) this->in_buffer) + 2048 - this->acmInLeft;
  322. this->acmHeader.cbSrcLength = this->acmInLeft;
  323. this->acmInLeft = 0;
  324. }
  325. else {
  326. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  327. this->acmHeader.cbSrcLength = 2048;
  328. }
  329. this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
  330. this->acmHeader.cbDstLength = 256000;
  331. res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
  332. if(res > 0) {
  333. MessageBox(NULL, "Cannot prepare header!", "", MB_OK);
  334. }
  335. res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
  336. if(res > 0) {
  337. MessageBox(NULL, "Could not convert", "", MB_OK);
  338. }
  339. while(!ring_full(this->acmHeader.cbDstLengthUsed)) {
  340. /*
  341.  * We store it
  342.  */
  343. ring_write((char *) this->acmHeader.pbDst, this->acmHeader.cbDstLengthUsed);
  344. /*
  345.  * unprepare and start again
  346.  */
  347. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  348. if(!this->acmInLeft)
  349. this->decaps->ReadAudio(this->in_buffer, 2048);
  350. memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
  351. this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
  352. if(this->acmInLeft > 0) {
  353. this->acmHeader.pbSrc       = ((unsigned char *) this->in_buffer) + 2048 - this->acmInLeft;
  354. this->acmHeader.cbSrcLength = this->acmInLeft;
  355. this->acmInLeft = 0;
  356. }
  357. else {
  358. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  359. this->acmHeader.cbSrcLength = 2048;
  360. }
  361. this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
  362. this->acmHeader.cbDstLength = 256000;
  363. res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
  364. if(res > 0) {
  365. MessageBox(NULL, "Cannot prepare header!", "", MB_OK);
  366. }
  367. res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
  368. if(res > 0) {
  369. MessageBox(NULL, "Could not convert", "", MB_OK);
  370. }
  371. this->acmInLeft = 2048 - this->acmHeader.cbSrcLengthUsed;
  372. }
  373. this->acmLeft = this->acmHeader.cbDstLengthUsed;
  374. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  375. done2:
  376. ring_read(((char *) buffer) + i*4096, 4096);
  377. }
  378. /*
  379.  * The last bit
  380.  */
  381.  
  382. int left = size - (blocks * 4096);
  383. if(left > 0)
  384. ring_read(((char *) buffer) + (blocks - 1)*4096, left);
  385. }
  386. }
  387. }
  388. return 1;
  389. }
  390. /*
  391.  * Returns the codec Name
  392.  *
  393.  */
  394. char *AudioCodec::GetCodecName()
  395. {
  396. if(this->mpeg == 1) {
  397. return "MPEG-1 Layer-3 audio codec";
  398. }
  399. else {
  400. if(this->hacm != NULL) {
  401. char            *name;
  402. HACMDRIVERID     dId;
  403. ACMDRIVERDETAILS details;
  404. name = (char *) malloc(128);
  405. if(acmDriverID((HACMOBJ) this->hacm, &dId, 0) > 0) {
  406. return NULL;
  407. }
  408. memset(&details, 0, sizeof(ACMDRIVERDETAILS));
  409. details.cbStruct = sizeof(ACMDRIVERDETAILS);
  410. if(acmDriverDetails(dId, &details, 0) == MMSYSERR_INVALHANDLE) {
  411. return NULL;
  412. }
  413. strcpy(name, details.szLongName);
  414. return name;
  415. }
  416. }
  417. return NULL;
  418. }
  419. /*
  420.  * Closes the decding engine
  421.  *
  422.  */
  423. int AudioCodec::Close()
  424. {
  425. if(this->mpeg) {
  426. ExitMP3(&this->mp);
  427. }
  428. return 1;
  429. }