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

多媒体编程

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////////////////////
  2. #include "stdafx.h"
  3. #include "globals.h"
  4. #include "CPI_Stream.h"
  5. #include "CPI_Player_CoDec.h"
  6. #include "CPI_ID3.h"
  7. #include "ogg/ogg.h"
  8. #include "vorbis/codec.h"
  9. #include "vorbis/vorbisfile.h"
  10. ////////////////////////////////////////////////////////////////////////////////
  11. //
  12. // This is the CoDec module - the basic idea is that the file will be opened and
  13. // data will be sucked through the CoDec via calls to CPI_CoDec__GetPCMBlock
  14. //
  15. //
  16. ////////////////////////////////////////////////////////////////////////////////
  17. ////////////////////////////////////////////////////////////////////////////////
  18. //
  19. typedef struct __CPs_CoDec_Ogg
  20. {
  21. //    HANDLE m_pInStream;
  22.     CPs_InStream* m_pInStream;
  23.     CPs_FileInfo m_FileInfo;
  24.     HINSTANCE oggInstance;
  25.     OggVorbis_File vf;
  26.     int current_section;
  27. } CPs_CoDec_Ogg;
  28. //
  29. //
  30. ////////////////////////////////////////////////////////////////////////////////
  31. ////////////////////////////////////////////////////////////////////////////////
  32. //
  33. //
  34. // Module functions
  35. void CPP_OMOGG_Uninitialise(CPs_CoDecModule* pModule);
  36. BOOL CPP_OMOGG_OpenFile(CPs_CoDecModule* pModule, const char* pcFilename, DWORD dwCookie, HWND hWndOwner);
  37. void CPP_OMOGG_CloseFile(CPs_CoDecModule* pModule);
  38. void CPP_OMOGG_Seek(CPs_CoDecModule* pModule, const int iNumerator, const int iDenominator);
  39. void CPP_OMOGG_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo* pInfo);
  40. //
  41. BOOL CPP_OMOGG_GetPCMBlock(CPs_CoDecModule* pModule, void* pBlock, DWORD* pdwBlockSize);
  42. int CPP_OMOGG_GetCurrentPos_secs(CPs_CoDecModule* pModule);
  43. //
  44. ////////////////////////////////////////////////////////////////////////////////
  45. ////////////////////////////////////////////////////////////////////////////////
  46. //
  47. //
  48. //
  49. void CP_InitialiseCodec_OGG(CPs_CoDecModule* pCoDec)
  50. {
  51.     CPs_CoDec_Ogg *pContext;
  52.     // Setup functions
  53.     pCoDec->Uninitialise = CPP_OMOGG_Uninitialise;
  54.     pCoDec->OpenFile = CPP_OMOGG_OpenFile;
  55.     pCoDec->CloseFile = CPP_OMOGG_CloseFile;
  56.     pCoDec->Seek = CPP_OMOGG_Seek;
  57.     pCoDec->GetFileInfo = CPP_OMOGG_GetFileInfo;
  58.     pCoDec->GetPCMBlock = CPP_OMOGG_GetPCMBlock;
  59.     pCoDec->GetCurrentPos_secs = CPP_OMOGG_GetCurrentPos_secs;
  60.     // Setup private data
  61.     pCoDec->m_pModuleCookie = malloc(sizeof(CPs_CoDec_Ogg));
  62.     pContext = (CPs_CoDec_Ogg*)pCoDec->m_pModuleCookie;
  63. //    pContext->m_pInStream = NULL;
  64. pContext->m_pInStream=NULL;
  65.     CPFA_InitialiseFileAssociations(pCoDec);
  66.     CPFA_AddFileAssociation(pCoDec, "OGG", 0L);
  67. }
  68. //
  69. //
  70. //
  71. void CPP_OMOGG_Uninitialise(CPs_CoDecModule* pModule)
  72. {
  73.     CPs_CoDec_Ogg *pContext = (CPs_CoDec_Ogg*)pModule->m_pModuleCookie;
  74.     CP_CHECKOBJECT(pContext);
  75. //    CP_ASSERT(pContext->m_pInStream == NULL)
  76.     CP_ASSERT(pContext->m_pInStream == NULL)
  77.     free(pContext);
  78.     CPFA_EmptyFileAssociations(pModule);
  79. }
  80. CPs_InStream* gInStream=NULL;
  81. size_t CPP_OMOGG_cbRead(void *buffer, size_t size, size_t amount, void *file)
  82. {
  83. size_t result=0;
  84. gInStream->Read(gInStream, buffer, size*amount, &result);
  85.     return result;
  86. }
  87. int CPP_OMOGG_cbSeek(void *file, ogg_int64_t newpos, int set) 
  88. {
  89. if(!gInStream->IsSeekable(gInStream)) return -1;
  90. if(set==SEEK_END)
  91. newpos=gInStream->GetLength(gInStream);
  92. gInStream->Seek(gInStream, (UINT)newpos);
  93. return (int)newpos;
  94. }
  95. int CPP_OMOGG_cbClose(void *file)
  96. {
  97. gInStream->Uninitialise(gInStream);
  98. return 1;
  99. }
  100. long CPP_OMOGG_cbTell(void *file)
  101. {
  102. return gInStream->Tell(gInStream);
  103. }
  104. //
  105. //
  106. //
  107. BOOL CPP_OMOGG_OpenFile(CPs_CoDecModule* pModule, const char* pcFilename, DWORD dwCookie, HWND hWndOwner)
  108. {
  109.     vorbis_info *pInfo = NULL;
  110. CPs_CoDec_Ogg *pContext = (CPs_CoDec_Ogg*)pModule->m_pModuleCookie;
  111. CP_CHECKOBJECT(pContext);
  112.     // If we have a stream open - close it
  113.     if(pContext->m_pInStream != NULL)
  114.     {
  115.         CP_TRACE0("Already had a stream open, closing it");
  116.         ov_clear(&pContext->vf);
  117.         pContext->m_pInStream = NULL;
  118.     }
  119.     // Open our new stream
  120.     CP_TRACE1("Openfile "%s"", pcFilename);
  121.     pContext->m_pInStream = CP_CreateInStream(pcFilename, hWndOwner);
  122.     if(!pContext->m_pInStream)
  123.     {
  124.         CP_TRACE0("CPI_CoDec__OpenFile: failed");
  125.         return FALSE;
  126.     }
  127. gInStream = pContext->m_pInStream;
  128. /*   pContext->m_pInStream = fopen(pcFilename, "rb");
  129.     if(pContext->m_pInStream == NULL)
  130.     {
  131.         CP_TRACE0("Failed to open file");
  132.         return FALSE; // Failure
  133.     }
  134. */
  135.   
  136.     memset(&pContext->vf, 0, sizeof(pContext->vf));
  137. {
  138. ov_callbacks callbacks = {
  139.     (size_t (*)(void *, size_t, size_t, void *)) CPP_OMOGG_cbRead,
  140.     (int (*)(void *, ogg_int64_t, int))   CPP_OMOGG_cbSeek,
  141.     (int (*)(void *))                  CPP_OMOGG_cbClose,
  142.     (long (*)(void *))              CPP_OMOGG_cbTell
  143.   };
  144.   if( ov_open_callbacks((void *)(gInStream), &pContext->vf, NULL, 0, callbacks) <0)
  145. //    if(ov_open(pContext->m_pInStream, &pContext->vf, NULL, 0) < 0)
  146.     {
  147.         CP_TRACE0("Input does not appear to be an Ogg bitstream.");
  148.         pContext->m_pInStream->Uninitialise(pContext->m_pInStream);
  149.         pContext->m_pInStream = NULL;
  150.         return FALSE;
  151.     }
  152.     if (ov_streams(&pContext->vf) != 1)
  153.     {
  154.         CP_TRACE1("Can't deal with multiple streams yet. Streams:%d", ov_streams(&pContext->vf));
  155.         ov_clear(&pContext->vf);
  156.         pContext->m_pInStream->Uninitialise(pContext->m_pInStream);
  157.         pContext->m_pInStream = NULL;
  158.         return FALSE;
  159.     }
  160.     pInfo = ov_info(&pContext->vf, -1);
  161.     if (pInfo == NULL)
  162.     {
  163.         CP_TRACE0("Unable to get ogg info.");
  164.         ov_clear(&pContext->vf);
  165.         pContext->m_pInStream->Uninitialise(pContext->m_pInStream);
  166.         pContext->m_pInStream = NULL;
  167.         return FALSE;
  168.     }
  169.     if (pInfo->channels > 2)
  170.     {
  171.         CP_TRACE1("Can't deal with more than 2 channels yet. Channels:%d", pInfo->channels);
  172.         ov_clear(&pContext->vf);
  173.         pContext->m_pInStream->Uninitialise(pContext->m_pInStream);
  174.         pContext->m_pInStream = NULL;
  175.         return FALSE;
  176.     }
  177.     // Load m_FileInfo
  178.     pContext->m_FileInfo.m_b16bit = TRUE; //?
  179.     pContext->m_FileInfo.m_iBitRate_Kbs = ov_bitrate(&pContext->vf, -1) / 1000;
  180.     pContext->m_FileInfo.m_iFileLength_Secs = (int)ov_time_total(&pContext->vf, -1);
  181.     pContext->m_FileInfo.m_iFreq_Hz = pInfo->rate;
  182.     pContext->m_FileInfo.m_bStereo = (pInfo->channels == 2);
  183. }
  184.     return TRUE; // Success
  185. }
  186. //
  187. //
  188. //
  189. void CPP_OMOGG_CloseFile(CPs_CoDecModule* pModule)
  190. {
  191.     CPs_CoDec_Ogg *pContext = (CPs_CoDec_Ogg*)pModule->m_pModuleCookie;
  192.     CP_CHECKOBJECT(pContext);
  193.     // If we have a stream open - close it
  194.     if(pContext->m_pInStream != NULL)
  195.     {
  196.         ov_clear(&pContext->vf);
  197.         pContext->m_pInStream = NULL;
  198.     }
  199. }
  200. //
  201. //
  202. //
  203. void CPP_OMOGG_Seek(CPs_CoDecModule* pModule, const int iNumerator, const int iDenominator)
  204. {
  205.     CPs_CoDec_Ogg *pContext = (CPs_CoDec_Ogg*)pModule->m_pModuleCookie;
  206.     CP_CHECKOBJECT(pContext);
  207.     // No error handling. If there is an error, there will be no seek
  208.     ov_pcm_seek(&pContext->vf, (ogg_int64_t) (((float)iNumerator/(float)iDenominator) * (float)ov_pcm_total(&pContext->vf, -1)));
  209. }
  210. //
  211. //
  212. //
  213. BOOL CPP_OMOGG_GetPCMBlock(CPs_CoDecModule* pModule, void* pBlock, DWORD* pdwBlockSize)
  214. {
  215.     int ret;
  216.     BOOL CONTINUE = TRUE;
  217.     DWORD bytes_read = *pdwBlockSize;
  218.     CPs_CoDec_Ogg *pContext = (CPs_CoDec_Ogg*)pModule->m_pModuleCookie;
  219.     CP_CHECKOBJECT(pContext);
  220.     // Read PCM data from decoder. Little endian (0), 16-Bit (2), Signed (1)
  221.     bytes_read = 0;
  222.     while (bytes_read < *pdwBlockSize)
  223.     {
  224.         ret = ov_read(&pContext->vf, (unsigned char *)pBlock + bytes_read, *pdwBlockSize - bytes_read, 0, 2, 1, &pContext->current_section);
  225.         if (ret == 0)
  226.         {
  227.             *pdwBlockSize = bytes_read;
  228.             CONTINUE = FALSE;
  229.             break;
  230.         } else if (ret < 0)
  231.         {
  232.             CP_TRACE0("Hole in OGG/VORBIS datastream, ignoring...");
  233.         } else {
  234.             bytes_read += ret;
  235.         }
  236.     }
  237.     return CONTINUE; //More data to come
  238. }
  239. //
  240. //
  241. //
  242. void CPP_OMOGG_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo* pInfo)
  243. {
  244.     CPs_CoDec_Ogg *pContext = (CPs_CoDec_Ogg*)pModule->m_pModuleCookie;
  245.     CP_CHECKOBJECT(pContext);
  246.     memcpy(pInfo, &pContext->m_FileInfo, sizeof(*pInfo));
  247. }
  248. //
  249. //
  250. //
  251. int CPP_OMOGG_GetCurrentPos_secs(CPs_CoDecModule* pModule)
  252. {
  253.     CPs_CoDec_Ogg *pContext = (CPs_CoDec_Ogg*)pModule->m_pModuleCookie;
  254.     CP_CHECKOBJECT(pContext);
  255.     return (int)ov_time_tell(&pContext->vf);;
  256. }
  257. //
  258. //
  259. //