⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acmcodec.cxx

📁 mgcp协议源代码。支持多种编码:g711
💻 CXX
字号:
/* * acmcodec.cxx * * Microsoft Windows Audio Compression Manager codec interface * * Open H323 Library * * Copyright (c) 1999-2000 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Open H323 Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Contributor(s): ______________________________________. * * $Log: acmcodec.cxx,v $ * Revision 1.13  2000/06/22 00:25:14  robertj * Fixed problems with G.723.1 packet sizes. * * Revision 1.12  2000/05/10 04:05:33  robertj * Changed capabilities so has a function to get name of codec, instead of relying on PrintOn. * * Revision 1.11  2000/05/02 04:32:26  robertj * Fixed copyright notice comment. * * Revision 1.10  2000/03/21 03:06:48  robertj * Changes to make RTP TX of exact numbers of frames in some codecs. * * Revision 1.9  1999/12/31 00:05:36  robertj * Added Microsoft ACM G.723.1 codec capability. * * Revision 1.8  1999/11/19 08:08:21  robertj * Removed MS G.723.1 codec as cannot be used by other applications. * * Revision 1.7  1999/10/14 12:01:42  robertj * Fixed error in transmit packet size, far too large! * * Revision 1.6  1999/10/08 09:59:02  robertj * Rewrite of capability for sending multiple audio frames * * Revision 1.5  1999/10/08 04:58:37  robertj * Added capability for sending multiple audio frames in single RTP packet * * Revision 1.4  1999/09/23 07:25:12  robertj * Added open audio and video function to connection and started multi-frame codec send functionality. * * Revision 1.3  1999/09/23 07:06:35  robertj * More attempts at accessing G.723.1 codec via ACM * * Revision 1.2  1999/09/22 04:15:50  robertj * Fixed incorrect bandwidth requirement * * Revision 1.1  1999/09/21 14:24:07  robertj * Added Windows ACM support. * */#include <ptlib.h>#include "acmcodec.h"#include "h245.h"#include "rtp.h"struct EnumCallbackParameter{  EnumCallbackParameter(unsigned formatTag = WAVE_FORMAT_UNKNOWN);  UINT             searchFormatTag;  HACMDRIVERID     driverId;  POrdinalToString codecNames;  PWaveFormat      waveFormat;};#define new PNEW///////////////////////////////////////////////////////////////////////////////EnumCallbackParameter::EnumCallbackParameter(unsigned formatTag){  searchFormatTag = formatTag;  driverId = NULL;  DWORD maxWaveFormatSize = 0;  acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &maxWaveFormatSize);  if (maxWaveFormatSize < sizeof(WAVEFORMATEX))    maxWaveFormatSize = sizeof(WAVEFORMATEX); // for MS-PCM  waveFormat.SetSize(maxWaveFormatSize);}static BOOL GetFormatName(unsigned dwFormatTag, POrdinalToString & codecNames){  if (codecNames.Contains(dwFormatTag))    return TRUE;  ACMFORMATTAGDETAILS aftd;  memset(&aftd, 0, sizeof(aftd));  aftd.cbStruct = sizeof(aftd);  aftd.dwFormatTag = dwFormatTag;  MMRESULT result = acmFormatTagDetails(NULL, &aftd, ACM_FORMATTAGDETAILSF_FORMATTAG);  if (result != 0) {    PTRACE(1, "ACM\tError in ACM format details: error=" << result);    return FALSE;  }  codecNames.SetAt(dwFormatTag, aftd.szFormatTag);  return TRUE;}static BOOL CALLBACK FormatEnumCallback(HACMDRIVERID hDriverId,                                        LPACMFORMATDETAILS pafd,                                        DWORD dwInstance,                                        DWORD /*fdwSupport*/){  EnumCallbackParameter & param = *(EnumCallbackParameter *)dwInstance;  if (param.searchFormatTag == 0) {  // Are just getting all the format names available.    PTRACE(4, "ACM\tEnumerated tag: " << pafd->dwFormatTag           << " WAVEFORMAT=" << param.waveFormat);    return GetFormatName(pafd->dwFormatTag, param.codecNames);  }  if (param.searchFormatTag != pafd->dwFormatTag) // Is format we are looking for?    return TRUE;  GetFormatName(pafd->dwFormatTag, param.codecNames);  param.driverId = hDriverId;  return FALSE; // Stop searching}static BOOL CALLBACK DriverEnumCallback(HACMDRIVERID hDriverId,                                        DWORD dwInstance,                                        DWORD fdwSupport){  if ((fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC) == 0)    return TRUE;  // Open the driver.  HACMDRIVER hDriver = NULL;  MMRESULT result = acmDriverOpen(&hDriver, hDriverId, 0);  if (result != 0) {    PTRACE(1, "ACM\tError opening ACM driver: error=" << result);    return FALSE;  }#if PTRACING  ACMDRIVERDETAILS add;  memset(&add, 0, sizeof(add));  add.cbStruct = sizeof(add);  result = acmDriverDetails(hDriverId, &add, 0);  if (result != 0) {    PTRACE(1, "ACM\tError in ACM driver details: error=" << result);    return FALSE;  }  PTRACE(4, "ACM\tEnumerated driver: " << hDriverId         << ", \"" << add.szLongName         << "\", fdwSupport=0x" << hex << add.fdwSupport << dec         << ", cFormatTags=" << add.cFormatTags         << ", \"" << add.szFeatures << '"');#endif  EnumCallbackParameter & param = *(EnumCallbackParameter *)dwInstance;  ACMFORMATDETAILS afd;  memset(&afd, 0, sizeof(afd));  afd.cbStruct = sizeof(afd);  afd.pwfx = param.waveFormat;  afd.pwfx->wFormatTag = (WORD)param.searchFormatTag;  afd.cbwfx = param.waveFormat.GetSize();  afd.dwFormatTag = param.searchFormatTag;  result = acmFormatEnum(hDriver, &afd, FormatEnumCallback, dwInstance, 0);#if PTRACING  if (result != 0)    PTRACE(1, "ACM\tError in ACM format enumeration: error=" << result);#endif  acmDriverClose(hDriver, 0);  return param.driverId == NULL;}///////////////////////////////////////////////////////////////////////////////H323_ACMCapability::H323_ACMCapability(H323EndPoint & endpoint, unsigned tag)  : H323NonStandardAudioCapability(256, 256, endpoint, NULL, 0){  formatTag = tag;  EnumCallbackParameter param(formatTag);  MMRESULT result = acmDriverEnum(DriverEnumCallback, (DWORD)&param, 0);  if (result != 0) {    PTRACE(1, "ACM\tError enumerating ACM drivers: error=" << result);    return;  }  if (param.driverId != NULL)    formatName = param.codecNames(formatTag);  rtpPayloadType = RTP_DataFrame::DynamicBase;}PObject * H323_ACMCapability::Clone() const{  return new H323_ACMCapability(*this);}PString H323_ACMCapability::GetFormatName() const{  return "Windows ACM " + formatName;}H323Codec * H323_ACMCapability::CreateCodec(H323Codec::Direction direction) const{  EnumCallbackParameter param(formatTag);  MMRESULT result = acmDriverEnum(DriverEnumCallback, (DWORD)&param, 0);  if (result != 0) {    PTRACE(1, "Codec\tCould not find Windows ACM format " << formatTag           << ": error=" << result);    return NULL;  }  return new H323_ACMCodec(direction, param.waveFormat, rtpPayloadType);}BOOL H323_ACMCapability::IsValid() const{  return !formatName;}PStringArray H323_ACMCapability::GetCodecNames(){  PStringArray nameArray;  EnumCallbackParameter param;  MMRESULT result = acmDriverEnum(DriverEnumCallback, (DWORD)&param, 0);  if (result != 0)    PTRACE(1, "ACM\tError enumerating ACM drivers: error=" << result);  else {    PSortedStringList sorted;    PINDEX i;    for (i = 0; i < param.codecNames.GetSize(); i++)      sorted.AppendString(psprintf("%5u: %s",                                   (PINDEX)param.codecNames.GetKeyAt(i),                                   (const char *)param.codecNames.GetDataAt(i)));    nameArray.SetSize(sorted.GetSize());    for (i = 0; i < sorted.GetSize(); i++)      nameArray[i] = sorted[i];  }  return nameArray;}/////////////////////////////////////////////////////////////////////////////H323_ACMG7231Capability::H323_ACMG7231Capability()  : H323AudioCapability(8, 3){  maxFrameSize = 24;}PObject * H323_ACMG7231Capability::Clone() const{  return new H323_ACMG7231Capability();}PString H323_ACMG7231Capability::GetFormatName() const{  return "Microsoft ACM G.723.1";}unsigned H323_ACMG7231Capability::GetSubType() const{  return H245_AudioCapability::e_g7231;}H323Codec * H323_ACMG7231Capability::CreateCodec(H323Codec::Direction direction) const{  static const struct {    WAVEFORMATEX wf;    BYTE extra[10];  } g7231format = {    { 66, 1, 8000, 800, 24, 0, 10 },    {  2, 0, 0xce, 0x9a, 0x32, 0xf7, 0xa2, 0xae, 0xde, 0xac }  };  PWaveFormat waveFormat;  waveFormat.SetFormat(&g7231format, sizeof(g7231format));  return new H323_ACMCodec(direction, waveFormat, RTP_DataFrame::G7231);}BOOL H323_ACMG7231Capability::OnSendingPDU(H245_AudioCapability & pdu,                                           unsigned packetSize) const{  pdu.SetTag(H245_AudioCapability::e_g7231);  H245_AudioCapability_g7231 & g7231 = pdu;  g7231.m_maxAl_sduAudioFrames = packetSize;  g7231.m_silenceSuppression = TRUE;  return TRUE;}BOOL H323_ACMG7231Capability::OnReceivedPDU(const H245_AudioCapability & pdu,                                            unsigned & packetSize){  if (pdu.GetTag() != H245_AudioCapability::e_g7231)    return FALSE;  const H245_AudioCapability_g7231 & g7231 = pdu;  packetSize = g7231.m_maxAl_sduAudioFrames;  return TRUE;}BOOL H323_ACMG7231Capability::IsValid() const{  EnumCallbackParameter param(66);  return acmDriverEnum(DriverEnumCallback, (DWORD)&param, 0) == 0 &&         param.codecNames.GetSize() > 0;}/////////////////////////////////////////////////////////////////////////////H323_ACMCodec::H323_ACMCodec(Direction dir,                             const PWaveFormat & fmt,                             RTP_DataFrame::PayloadTypes rtpType)  : H323FramedAudioCodec(dir, 240, fmt->nBlockAlign),    waveFormat(fmt){  rtpPayloadType = rtpType;  hStream = NULL;  PTRACE(3, "Codec\tWindows ACM " << (dir == Encoder ? "en" : "de")         << "coder created: wFormatTag=" << waveFormat->wFormatTag);}H323_ACMCodec::~H323_ACMCodec(){  if (hStream != NULL)    acmStreamClose(hStream, 0);}BOOL H323_ACMCodec::Open(H323Connection & connection){  PWaveFormat srcFormat, dstFormat;  if (direction == Encoder) {    srcFormat.SetFormat(1, 8000, 16);    dstFormat = waveFormat;  }  else {    srcFormat = waveFormat;    dstFormat.SetFormat(1, 8000, 16);  }  MMRESULT result = acmStreamOpen(&hStream,                                  NULL, // driver                                  srcFormat, // source format                                  dstFormat, // destination format                                  NULL, // no filter                                  NULL, // no callback                                  0, // instance data (not used)                                  0); // flags  if (result != 0) {    PTRACE(1, "Codec\tCould not open Windows ACM stream: error=" << result);    return FALSE;  }  return H323FramedAudioCodec::Open(connection);}static const unsigned G7231PacketSizes[4] = { 24, 20, 4, 1 };BOOL H323_ACMCodec::EncodeFrame(BYTE * buffer, unsigned & length){  if (hStream == NULL)    return FALSE;  ACMSTREAMHEADER header;  memset(&header, 0, sizeof(header));  header.cbStruct = sizeof(header);  header.pbSrc = (BYTE *)sampleBuffer.GetPointer();  header.cbSrcLength = samplesPerFrame*2;  header.pbDst = buffer;  header.cbDstLength = bytesPerFrame;  // prep the header  MMRESULT result = acmStreamPrepareHeader(hStream, &header, 0);  if (result != 0) {    PTRACE(1, "Codec\tError in encode acmStreamPrepareHeader: error=" << result);    return FALSE;  }  result = acmStreamConvert(hStream, &header, 0);  if (result != 0) {    PTRACE(1, "Codec\tError in encode acmStreamConvert: error=" << result);    return FALSE;  }  if (rtpPayloadType != RTP_DataFrame::G7231)    length = bytesPerFrame;  else    length = G7231PacketSizes[buffer[0]&3];  return TRUE;}BOOL H323_ACMCodec::DecodeFrame(const BYTE * buffer, unsigned length, unsigned & written){  if (hStream == NULL)    return FALSE;  ACMSTREAMHEADER header;  memset(&header, 0, sizeof(header));  header.cbStruct = sizeof(header);  header.pbSrc = (BYTE *)buffer;  if (rtpPayloadType != RTP_DataFrame::G7231)    header.cbSrcLength = bytesPerFrame;  else    header.cbSrcLength = G7231PacketSizes[buffer[0]&3];  if (header.cbSrcLength > length)    header.cbSrcLength = length;  header.pbDst = (BYTE *)sampleBuffer.GetPointer();  header.cbDstLength = samplesPerFrame*2;  // prep the header  MMRESULT result = acmStreamPrepareHeader(hStream, &header, 0);   if (result != 0) {    PTRACE(1, "Codec\tError in decode acmStreamPrepareHeader: error=" << result);    return FALSE;  }  result = acmStreamConvert(hStream, &header, 0);  if (result != 0) {    PTRACE(1, "Codec\tError in decode acmStreamConvert: error=" << result);    return FALSE;  }  written = header.cbSrcLength;  return TRUE;}/////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -