AudioDecoderACM.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:12k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /**************************************************************************************
  2.  *                                                                                    *
  3.  *                                                                                    *
  4.  **************************************************************************************/
  5. #include "AudioDecoderACM.h"
  6. /*
  7.  * ACM封装器类
  8.  *
  9.  */
  10. MediaAudioDecoderACM::MediaAudioDecoderACM()
  11. {
  12. this->out_buffer  = NULL;
  13. this->in_buffer   = NULL;
  14. this->oFormat     = NULL;
  15. this->ring        = new MediaRingBuffer();
  16. }
  17. MediaAudioDecoderACM::~MediaAudioDecoderACM()
  18. {
  19. delete this->ring;
  20. }
  21. /*
  22.  * 媒体项函数
  23.  */
  24. media_type_t  MediaAudioDecoderACM::GetType()
  25. {
  26. return MEDIA_TYPE_AUDIO_DECODER;
  27. }
  28. char  *MediaAudioDecoderACM::GetName()
  29. {
  30. if(this->hacm != NULL) {
  31. char            *name;
  32. HACMDRIVERID     dId;
  33. ACMDRIVERDETAILS details;
  34. name = (char *) new char[128];
  35. if(acmDriverID((HACMOBJ) this->hacm, &dId, 0) > 0) {
  36. return NULL;
  37. }
  38. memset(&details, 0, sizeof(ACMDRIVERDETAILS));
  39. details.cbStruct = sizeof(ACMDRIVERDETAILS);
  40. if(acmDriverDetails(dId, &details, 0) == MMSYSERR_INVALHANDLE) {
  41. return NULL;
  42. }
  43. strcpy(name, details.szLongName);
  44. return name;
  45. }
  46. return "ACM Wrapper";
  47. }
  48. MP_RESULT     MediaAudioDecoderACM::Connect(MediaItem *item)
  49. {
  50. MMRESULT      mmres;
  51. WAVEFORMATEX *inFormat;
  52. DWORD         dwOutputFormatSize;
  53. if(item && item->GetType() == MEDIA_TYPE_DECAPS) {
  54. this->decaps = (MediaItemDecaps *) item;
  55. inFormat = this->decaps->GetAudioFormat(0);
  56. if(inFormat->wFormatTag == 85 && inFormat->cbSize != 12) {
  57. MPEGLAYER3WAVEFORMAT *format;
  58. format = (MPEGLAYER3WAVEFORMAT *) inFormat;
  59. format->wfx.cbSize      = 12;
  60. format->wID             = 1;
  61. format->fdwFlags        = 2;
  62. format->nBlockSize      = 313;
  63. format->nFramesPerBlock = 1;
  64. format->nCodecDelay     = 1393;
  65. }
  66. if (acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, (LPVOID)&dwOutputFormatSize)) {
  67. return MP_RESULT_ERROR;
  68. }
  69. this->oFormat = (WAVEFORMATEX *) new WAVEFORMATEX;
  70. this->oFormat->wFormatTag = WAVE_FORMAT_PCM;
  71. if (acmFormatSuggest(NULL, inFormat, this->oFormat, dwOutputFormatSize, ACM_FORMATSUGGESTF_WFORMATTAG)) {
  72. }
  73. if (oFormat->wBitsPerSample!=8 && oFormat->wBitsPerSample!=16)
  74. oFormat->wBitsPerSample=16;
  75. if (oFormat->nChannels!=1 && oFormat->nChannels!=2)
  76. oFormat->nChannels = 2;
  77. oFormat->nBlockAlign = (oFormat->wBitsPerSample/8) * oFormat->nChannels;
  78. oFormat->nAvgBytesPerSec = oFormat->nBlockAlign * oFormat->nSamplesPerSec;
  79. oFormat->cbSize = 0;
  80. mmres = acmStreamOpen(&hacm, NULL, inFormat, 
  81.   this->oFormat, NULL, NULL, 0, ACM_STREAMOPENF_NONREALTIME);
  82. if(mmres != 0) {
  83. return MP_RESULT_ERROR;
  84. }
  85. this->inputSize  = max(2048 - (2048 % inFormat->nBlockAlign),  8*inFormat->nBlockAlign);
  86. this->outputSize = 0;
  87. if (acmStreamSize(this->hacm, this->inputSize, &this->outputSize, ACM_STREAMSIZEF_SOURCE))
  88. return MP_RESULT_ERROR;
  89. this->ring->Init();
  90. this->in_buffer  = (char *) new char[this->inputSize];
  91. this->out_buffer = (char *) new char[this->outputSize];
  92. this->acmInLeft = 0;
  93. this->acmLeft   = 0;
  94. return MP_RESULT_OK;
  95. }
  96. return MP_RESULT_ERROR;
  97. }
  98. MP_RESULT     MediaAudioDecoderACM::ReleaseConnections()
  99. {
  100. this->decaps = NULL;
  101. free(this->in_buffer);
  102. this->in_buffer = NULL;
  103. free(this->out_buffer);
  104. this->out_buffer = NULL;
  105. free(this->oFormat);
  106. this->oFormat = NULL;
  107. acmStreamClose(this->hacm, 0);
  108. return MP_RESULT_OK;
  109. }
  110. DWORD         MediaAudioDecoderACM::GetCaps()
  111. {
  112. return 0;
  113. }
  114. MP_RESULT     MediaAudioDecoderACM::Configure(HINSTANCE hInstance, HWND hwnd)
  115. {
  116. return MP_RESULT_ERROR;
  117. }
  118. WAVEFORMATEX *MediaAudioDecoderACM::GetAudioFormat()
  119. {
  120. return this->oFormat;
  121. }
  122. MP_RESULT     MediaAudioDecoderACM::EmptyAudioBuffer()
  123. {
  124. if(this->ring)
  125. this->ring->Init();
  126. this->acmLeft   = 0;
  127. this->acmInLeft = 0;
  128. return MP_RESULT_OK;
  129. }
  130. unsigned int MediaAudioDecoderACM::Decompress(void *buffer, unsigned int size)
  131. {
  132. DWORD    i, done;
  133. MMRESULT res;
  134. done = 0;
  135. if(this->hacm) {
  136. if(size < 16384) {
  137. if(this->acmLeft > 0 && !this->ring->IsFullFor(this->acmLeft)) {
  138. this->ring->Write((char *) this->out_buffer, this->acmLeft);
  139. this->acmLeft = 0;
  140. }
  141. if(this->acmLeft > 0)
  142. goto done;
  143. if(!this->acmInLeft) {
  144. if(this->decaps->ReadAudioData(0, this->in_buffer, this->inputSize) != this->inputSize) {
  145. return done;
  146. }
  147. }
  148. memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
  149. this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
  150. if(this->acmInLeft > 0) {
  151. memcpy(this->in_buffer, ((char *) this->in_buffer) + this->inputSize - this->acmInLeft, this->acmInLeft);
  152. if(this->decaps->ReadAudioData(0, ((char *) this->in_buffer) + this->acmInLeft, this->inputSize - this->acmInLeft) != (this->inputSize - this->acmInLeft) ) {
  153. return done;
  154. }
  155. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  156. this->acmHeader.cbSrcLength = this->inputSize;
  157. this->acmInLeft = 0;
  158. }
  159. else {
  160. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  161. this->acmHeader.cbSrcLength = this->inputSize;
  162. }
  163. this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
  164. this->acmHeader.cbDstLength = this->outputSize;
  165. res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
  166. if(res > 0) {
  167. return done;
  168. }
  169. res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
  170. if(res > 0) {
  171. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  172. return done;
  173. }
  174. while(!this->ring->IsFullFor(this->acmHeader.cbDstLengthUsed)) {
  175. this->ring->Write((char *) this->acmHeader.pbDst, this->acmHeader.cbDstLengthUsed);
  176. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  177. if(!this->acmInLeft) {
  178. if(this->decaps->ReadAudioData(0, this->in_buffer, this->inputSize) != this->inputSize) {
  179. return done;
  180. }
  181. }
  182. memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
  183. this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
  184. if(this->acmInLeft > 0) {
  185. memcpy(this->in_buffer, ((char *) this->in_buffer) + this->inputSize - this->acmInLeft, this->acmInLeft);
  186. if(this->decaps->ReadAudioData(0, ((char *) this->in_buffer) + this->acmInLeft, this->inputSize - this->acmInLeft) != (this->inputSize - this->acmInLeft) ) {
  187. return done;
  188. }
  189. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  190. this->acmHeader.cbSrcLength = this->inputSize;
  191. this->acmInLeft = 0;
  192. }
  193. else {
  194. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  195. this->acmHeader.cbSrcLength = this->inputSize;
  196. }
  197. this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
  198. this->acmHeader.cbDstLength = this->outputSize;
  199. res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
  200. if(res > 0) {
  201. return done;
  202. }
  203. res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
  204. if(res > 0) {
  205. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  206. return done;
  207. }
  208. this->acmInLeft = this->inputSize - this->acmHeader.cbSrcLengthUsed;
  209. }
  210. this->acmLeft = this->acmHeader.cbDstLengthUsed;
  211. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  212. done:
  213. this->ring->Read((char *) buffer, size);
  214. done += size;
  215. return done;
  216. }
  217. else {
  218. unsigned int blocks = size / 16384;
  219. for(i = 0; i < blocks; i++) {
  220. if(this->acmLeft > 0 && !this->ring->IsFullFor(this->acmLeft)) {
  221. this->ring->Write((char *) this->out_buffer, this->acmLeft);
  222. this->acmLeft = 0;
  223. }
  224. if(this->acmLeft > 0)
  225. goto done2;
  226. if(!this->acmInLeft) {
  227. if(this->decaps->ReadAudioData(0, this->in_buffer, this->inputSize) != this->inputSize) {
  228. return done;
  229. }
  230. }
  231. memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
  232. this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
  233. if(this->acmInLeft > 0) {
  234. memcpy(this->in_buffer, ((char *) this->in_buffer) + this->inputSize - this->acmInLeft, this->acmInLeft);
  235. if(this->decaps->ReadAudioData(0, ((char *) this->in_buffer) + this->acmInLeft, this->inputSize - this->acmInLeft) != (this->inputSize - this->acmInLeft) ) {
  236. return done;
  237. }
  238. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  239. this->acmHeader.cbSrcLength = this->inputSize;
  240. this->acmInLeft = 0;
  241. }
  242. else {
  243. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  244. this->acmHeader.cbSrcLength = this->inputSize;
  245. }
  246. this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
  247. this->acmHeader.cbDstLength = this->outputSize;
  248. res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
  249. if(res > 0) {
  250. return done;
  251. }
  252. res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
  253. if(res > 0) {
  254. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  255. return done;
  256. }
  257. while(!this->ring->IsFullFor(this->acmHeader.cbDstLengthUsed)) {
  258. this->ring->Write((char *) this->acmHeader.pbDst, this->acmHeader.cbDstLengthUsed);
  259. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  260. if(!this->acmInLeft) {
  261. if(this->decaps->ReadAudioData(0, this->in_buffer, this->inputSize) != this->inputSize) {
  262. return done;
  263. }
  264. }
  265. memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
  266. this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
  267. if(this->acmInLeft > 0) {
  268. memcpy(this->in_buffer, ((char *) this->in_buffer) + this->inputSize - this->acmInLeft, this->acmInLeft);
  269. if(this->decaps->ReadAudioData(0, ((char *) this->in_buffer) + this->acmInLeft, this->inputSize - this->acmInLeft) != (this->inputSize - this->acmInLeft) ) {
  270. return done;
  271. }
  272. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  273. this->acmHeader.cbSrcLength = this->inputSize;
  274. this->acmInLeft = 0;
  275. }
  276. else {
  277. this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
  278. this->acmHeader.cbSrcLength = this->inputSize;
  279. }
  280. this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
  281. this->acmHeader.cbDstLength = this->outputSize;
  282. res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
  283. if(res > 0) {
  284. return done;
  285. }
  286. res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
  287. if(res > 0) {
  288. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  289. return done;
  290. }
  291. this->acmInLeft = this->inputSize - this->acmHeader.cbSrcLengthUsed;
  292. }
  293. this->acmLeft = this->acmHeader.cbDstLengthUsed;
  294. acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
  295. done2:
  296. this->ring->Read(((char *) buffer) + i*16384, 16384);
  297. done += 16384;
  298. }
  299.  
  300. int left = size - (blocks * 16384);
  301. if(left > 0) {
  302. this->Decompress((void *) ((char *) buffer + size - left), left);
  303. done += left;
  304. }
  305. return done;
  306. }
  307. }
  308. return 0;
  309. }