📄 tsampleformat.cpp.svn-base
字号:
/* * Copyright (c) 2004-2006 Milan Cutka * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include "stdafx.h"#include "TsampleFormat.h"#include "ffdshow_mediaguids.h"#include "vorbis/vorbisformat.h"#include "dsutil.h"const int TsampleFormat::standardChannelMasks[]={ SPEAKER_FRONT_CENTER, SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT, SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_CENTER, SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT, SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT, SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT};TsampleFormat::TsampleFormat(const WAVEFORMATEX &wfex,bool wfextcheck,const GUID *subtype):pcm_be(false){ init(wfex,wfextcheck,subtype);}void TsampleFormat::init(const WAVEFORMATEX &wfex,bool wfextcheck,const GUID *subtype){ if (wfextcheck && wfex.wFormatTag==WAVE_FORMAT_EXTENSIBLE) init(*(const WAVEFORMATEXTENSIBLE*)&wfex,subtype); else { freq=wfex.nSamplesPerSec; setChannels(wfex.nChannels,0); if (wfex.wFormatTag==WAVE_FORMAT_IEEE_FLOAT) sf=SF_FLOAT32; else if (wfex.wFormatTag==WAVE_FORMAT_DOLBY_AC3_SPDIF) sf=SF_AC3; else if (subtype) { if (*subtype==MEDIASUBTYPE_IN32 || *subtype==MEDIASUBTYPE_in32 || *subtype==MEDIASUBTYPE_IN24 || *subtype==MEDIASUBTYPE_in24 || *subtype==MEDIASUBTYPE_FL32 || *subtype==MEDIASUBTYPE_fl32 || *subtype==MEDIASUBTYPE_FL64 || *subtype==MEDIASUBTYPE_fl64) { if (*subtype==MEDIASUBTYPE_IN32 || *subtype==MEDIASUBTYPE_in32) sf=SF_PCM32; else if (*subtype==MEDIASUBTYPE_IN24 || *subtype==MEDIASUBTYPE_in24) sf=SF_PCM24; else if (*subtype==MEDIASUBTYPE_FL32 || *subtype==MEDIASUBTYPE_fl32) sf=SF_FLOAT32; else if (*subtype==MEDIASUBTYPE_FL64 || *subtype==MEDIASUBTYPE_fl64) sf=SF_FLOAT64; Textradata extradata(wfex); if (extradata.data) { const uint8_t *enda=(const uint8_t*)memnstr(extradata.data,extradata.size,"enda"); //TODO: properly parse headers if (enda && *(uint16_t*)(enda+4)==0) pcm_be=true; } } else if (*subtype==MEDIASUBTYPE_twos || *subtype==MEDIASUBTYPE_TWOS) { sf=SF_PCM16; pcm_be=true; } } else switch (wfex.wBitsPerSample) { case 8:sf=SF_PCM8;break; case 0: case 16: default:sf=SF_PCM16;break; case 20:sf=SF_LPCM20;break; case 24:sf=SF_PCM24;break; case 32:sf=SF_PCM32;break; } dolby=DOLBY_NO; }}TsampleFormat::TsampleFormat(const WAVEFORMATEXTENSIBLE &wfexten,const GUID *subtype):pcm_be(false){ init(wfexten,subtype);}void TsampleFormat::init(const WAVEFORMATEXTENSIBLE &wfexten,const GUID *subtype){ init(wfexten.Format,false,subtype); setChannels(wfexten.Format.nChannels,wfexten.dwChannelMask); if (wfexten.SubFormat==MEDIASUBTYPE_IEEE_FLOAT) sf=SF_FLOAT32;}TsampleFormat::TsampleFormat(const VORBISFORMAT &vf):pcm_be(false){ init(vf);}void TsampleFormat::init(const VORBISFORMAT &vf){ freq=vf.nSamplesPerSec; sf=SF_PCM16; setChannels(vf.nChannels,0); dolby=DOLBY_NO;}TsampleFormat::TsampleFormat(const VORBISFORMAT2 &vf2):pcm_be(false){ init(vf2);}void TsampleFormat::init(const VORBISFORMAT2 &vf2){ freq=vf2.SamplesPerSec; switch (vf2.BitsPerSample) { case 0: case 16: default:sf=SF_PCM16;break; case 24:sf=SF_PCM24;break; case 32:sf=SF_PCM32;break; } setChannels(vf2.Channels,0); dolby=DOLBY_NO;}TsampleFormat::TsampleFormat(const VORBISFORMATILL &vfIll):pcm_be(false){ init(vfIll);}void TsampleFormat::init(const VORBISFORMATILL &vfIll){ freq=vfIll.samplesPerSec; sf=SF_PCM16; setChannels(vfIll.numChannels,0); dolby=DOLBY_NO;}TsampleFormat::TsampleFormat(const AM_MEDIA_TYPE &mt):pcm_be(false){ if (mt.formattype==FORMAT_VorbisFormat) init(*(const VORBISFORMAT*)mt.pbFormat); else if (mt.formattype==FORMAT_VorbisFormat2) init(*(const VORBISFORMAT2*)mt.pbFormat); else if (mt.formattype==FORMAT_VorbisFormatIll) init(*(const VORBISFORMATILL*)mt.pbFormat); else if (mt.formattype==FORMAT_WaveFormatEx) init(*(const WAVEFORMATEX*)mt.pbFormat,true,&mt.subtype); else { nchannels=NULL; sf=SF_NULL; }}int TsampleFormat::sf_bestMatch(int sfIn,int wantedSFS){ const int *bestsfs=NULL; switch (sfIn) { case SF_PCM16: { static const int best[]= { SF_PCM32, SF_PCM24, SF_FLOAT32, SF_NULL }; bestsfs=best; break; } case SF_PCM24: { static const int best[]= { SF_PCM32, SF_PCM16, SF_FLOAT32, SF_NULL }; bestsfs=best; break; } case SF_PCM32: { static const int best[]= { SF_PCM16, SF_PCM24, SF_FLOAT32, SF_NULL }; bestsfs=best; break; } case SF_PCM8: { static const int best[]= { SF_PCM16, SF_PCM32, SF_NULL }; bestsfs=best; break; } case SF_FLOAT32: { static const int best[]= { SF_PCM32, SF_PCM16, SF_PCM24, SF_NULL }; bestsfs=best; break; } default:return SF_NULL; } while (*bestsfs) { if (*bestsfs&wantedSFS) return *bestsfs; bestsfs++; } return SF_NULL;}DWORD TsampleFormat::getPCMformat(const CMediaType &mtIn,DWORD def){ if (*mtIn.FormatType()!=FORMAT_WaveFormatEx) return def; const WAVEFORMATEX *wfex=(const WAVEFORMATEX*)mtIn.Format(); if (wfex->wFormatTag!=WAVE_FORMAT_EXTENSIBLE && wfex->wFormatTag!=WAVE_FORMAT_PCM && wfex->wFormatTag!=WAVE_FORMAT_IEEE_FLOAT && mtIn.subtype!=MEDIASUBTYPE_RAW) return def; TsampleFormat sf(mtIn); switch (sf.sf) { case SF_NULL:return def; case SF_PCM8:return WAVE_FORMAT_PCM8; case SF_PCM16:return WAVE_FORMAT_PCM16; case SF_PCM24:return WAVE_FORMAT_PCM24; case SF_PCM32:return WAVE_FORMAT_PCM32; case SF_FLOAT32:return WAVE_FORMAT_FLOAT32; case SF_FLOAT64:return WAVE_FORMAT_FLOAT64; } return def; }WAVEFORMATEXTENSIBLE TsampleFormat::toWAVEFORMATEXTENSIBLE(bool alwayextensible) const{ WAVEFORMATEXTENSIBLE wfex; memset(&wfex,0,sizeof(wfex)); WAVEFORMATEX *wfe=&wfex.Format; if (sf==SF_FLOAT32) wfe->wFormatTag=(WORD)WAVE_FORMAT_IEEE_FLOAT; else if (sf==SF_LPCM16) wfe->wFormatTag=(WORD)WAVE_FORMAT_UNKNOWN; else wfe->wFormatTag=(WORD)WAVE_FORMAT_PCM; wfe->nChannels=WORD(nchannels); wfe->nSamplesPerSec=freq; wfe->wBitsPerSample=(WORD)bitsPerSample(); wfe->nBlockAlign=WORD(wfe->nChannels*wfe->wBitsPerSample/8); wfe->nAvgBytesPerSec=wfe->nSamplesPerSec*wfe->nBlockAlign; // FIXME: 24/32 bit only seems to work with WAVE_FORMAT_EXTENSIBLE int dwChannelMask; if (channelmask==0 && (sf==TsampleFormat::SF_PCM24 || sf==TsampleFormat::SF_PCM32 || nchannels>2)) dwChannelMask=makeChannelMask2(); else dwChannelMask=channelmask; if (!alwayextensible && dwChannelMask==standardChannelMasks[nchannels-1]) dwChannelMask=0; if (dwChannelMask) { wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.cbSize=sizeof(wfex)-sizeof(wfex.Format); wfex.dwChannelMask=dwChannelMask; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.SubFormat=sf==SF_FLOAT32?MEDIASUBTYPE_IEEE_FLOAT:MEDIASUBTYPE_PCM; } return wfex;}CMediaType TsampleFormat::toCMediaType(bool alwaysextensible) const{ CMediaType mt; /*if (sf==SF_LPCM16) mt.majortype=MEDIATYPE_MPEG2_PES; else*/ mt.majortype=MEDIATYPE_Audio; if (sf==SF_FLOAT32) mt.subtype=MEDIASUBTYPE_IEEE_FLOAT; else if (sf==SF_LPCM16) mt.subtype=MEDIASUBTYPE_DVD_LPCM_AUDIO; else mt.subtype=MEDIASUBTYPE_PCM; mt.formattype=FORMAT_WaveFormatEx; WAVEFORMATEXTENSIBLE wfex=toWAVEFORMATEXTENSIBLE(alwaysextensible); mt.SetFormat((BYTE*)&wfex,sizeof(wfex.Format)+wfex.Format.cbSize); return mt;}CMediaType TsampleFormat::createMediaTypeSPDIF(void){ CMediaType mt=TsampleFormat(SF_PCM16,48000,2).toCMediaType(); ((WAVEFORMATEX*)mt.pbFormat)->wFormatTag=WAVE_FORMAT_DOLBY_AC3_SPDIF; return mt;}const char_t* TsampleFormat::getSpeakerName(int speaker,bool shrt){ switch (speaker) { case SPEAKER_FRONT_LEFT:return shrt?_l("L"):_l("front left"); case SPEAKER_FRONT_RIGHT:return shrt?_l("R"):_l("front right"); case SPEAKER_FRONT_CENTER:return shrt?_l("C"):_l("front center"); case SPEAKER_LOW_FREQUENCY:return _l("LFE"); case SPEAKER_BACK_LEFT:return shrt?_l("SL"):_l("back left"); case SPEAKER_BACK_RIGHT:return shrt?_l("SR"):_l("back right"); case SPEAKER_FRONT_LEFT_OF_CENTER:return _l("front left of center"); case SPEAKER_FRONT_RIGHT_OF_CENTER:return _l("front right of center"); case SPEAKER_BACK_CENTER:return _l("back center"); case SPEAKER_SIDE_LEFT:return _l("side left"); case SPEAKER_SIDE_RIGHT:return _l("side right"); case SPEAKER_TOP_CENTER:return _l("top center"); case SPEAKER_TOP_FRONT_LEFT:return _l("top front left"); case SPEAKER_TOP_FRONT_CENTER:return _l("top front center"); case SPEAKER_TOP_FRONT_RIGHT:return _l("top front right"); case SPEAKER_TOP_BACK_LEFT:return _l("top back left"); case SPEAKER_TOP_BACK_CENTER:return _l("top back center"); case SPEAKER_TOP_BACK_RIGHT:return _l("top back right"); default:return _l("unknown"); }}void TsampleFormat::getSpeakersDescr(char_t *buf,size_t buflen,bool shrt) const{ buf[0]='\0'; for (unsigned int i=0;i<nchannels;i++) strncatf(buf,buflen,_l("%s,"),getSpeakerName(speakers[i],shrt)); buf[buflen-1]='\0'; size_t len=strlen(buf); if (len && buf[len-1]==',') buf[len-1]='\0';}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -