From ef66a823bbe715d7a96e9aace7dbf37100ede824 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sat, 10 Feb 2007 15:18:08 +0000 Subject: [PATCH] Ac3 for Windows --- audio.h | 1 + audiomvp.h | 1 + audiowin.cc | 34 ++- demuxer.cc | 93 ++++++- demuxer.h | 15 +- draintarget.h | 6 + dssourcefilter.cc | 604 ++++++++++++++++++++++++---------------------- dssourcefilter.h | 76 +++--- dssourcepin.cc | 385 +++++++++++++++++++++-------- dssourcepin.h | 89 +++---- player.cc | 9 +- player.h | 3 +- stream.cc | 3 +- stream.h | 2 +- vaudioselector.cc | 33 ++- vaudioselector.h | 8 +- videowin.cc | 233 ++++++++++-------- videowin.h | 6 +- vvideorec.cc | 9 +- 19 files changed, 1008 insertions(+), 602 deletions(-) diff --git a/audio.h b/audio.h index 0baaeb2..3eba642 100644 --- a/audio.h +++ b/audio.h @@ -57,6 +57,7 @@ class Audio : public DrainTarget virtual int setVolume(int volume)=0; virtual int mute()=0; virtual int unMute()=0; + virtual bool supportsAc3()=0; int volumeUp(); int volumeDown(); diff --git a/audiomvp.h b/audiomvp.h index 40694ab..fdd6f17 100644 --- a/audiomvp.h +++ b/audiomvp.h @@ -87,6 +87,7 @@ class AudioMVP : public Audio int setVolume(int volume); int mute(); int unMute(); + bool supportsAc3() { return false; } //Writing Data to Audiodevice virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); diff --git a/audiowin.cc b/audiowin.cc index 7bae0be..8de6da6 100644 --- a/audiowin.cc +++ b/audiowin.cc @@ -24,7 +24,6 @@ - AudioWin::AudioWin() { initted = 0; @@ -39,7 +38,6 @@ AudioWin::AudioWin() AudioWin::~AudioWin() { - } int AudioWin::init(UCHAR tstreamType) @@ -113,7 +111,7 @@ int AudioWin::unPause() int AudioWin::reset() { - + if (!initted){return 0;} return ((VideoWin*)Video::getInstance())->dsreset(); } @@ -168,11 +166,11 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, /*First Check, if we have an audio sample*/ VideoWin *vw=(VideoWin*)Video::getInstance(); - if (!vw->isdsinited()) return 0; + if (!vw->isdsinited()) return 0; if (vw->InIframemode()) { - samplepos=0; - MILLISLEEP(10); - return 0; //Not in iframe mode! + samplepos=0; + MILLISLEEP(10); + return 0; //Not in iframe mode! } IMediaSample* ms=NULL; REFERENCE_TIME reftime1=0; @@ -181,7 +179,12 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, UINT headerstrip=0; if (packet.disconti) { firstsynched=false; - vw->DeliverVideoMediaSample(); + vw->DeliverAudioMediaSample(); + } + + if (packet.type!=vw->lastAType()){//Format Change //Push data out ! + firstsynched=false; + vw->DeliverAudioMediaSample(); } @@ -191,6 +194,7 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, */ if (*samplepos==0) {//stripheader headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; + if (packet.type == MPTYPE_AC3) headerstrip+=4; //skip ac3 bytes *samplepos+=headerstrip; if ( packet.synched ) { vw->DeliverAudioMediaSample();//write out old data @@ -205,7 +209,7 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, } else { if (!firstsynched) {// *samplepos=packet.length;//if we have not processed at least one - + return packet.length;//synched packet ignore it! } } @@ -235,6 +239,7 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, } ms->GetPointer(&ms_buf); + if (ms_pos==0) {//will only be changed on first packet if (packet.disconti) { ms->SetDiscontinuity(TRUE); @@ -257,9 +262,14 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, // ms->SetSyncPoint(TRUE); } } + if (packet.type!=vw->lastAType()) { + vw->changeAType(packet.type,ms); + ms->SetDiscontinuity(TRUE); + } memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy); + ms->SetActualDataLength(haveToCopy+ms_pos); *samplepos+=haveToCopy; @@ -278,6 +288,11 @@ void AudioWin::ResetTimeOffsets() { return vw->ResetTimeOffsets(); } +bool AudioWin::supportsAc3(){ + VideoWin *vw=(VideoWin*)Video::getInstance(); + return vw->supportsAc3(); +} + #ifdef DEV int AudioWin::test() { @@ -286,4 +301,3 @@ int AudioWin::test() #endif - diff --git a/demuxer.cc b/demuxer.cc index 1a78046..f615964 100644 --- a/demuxer.cc +++ b/demuxer.cc @@ -51,6 +51,7 @@ Demuxer::Demuxer() arcnt = 0; vid_seeking = aud_seeking = false; video_pts = audio_pts = 0; + ispre_1_3_19 = false; } Demuxer::~Demuxer() @@ -91,11 +92,16 @@ void Demuxer::reset() horizontal_size = vertical_size = 0; aspect_ratio = (enum AspectRatio) 0; frame_rate = bit_rate = 0; + ispre_1_3_19 = false; for (int i = 0; i <= (PESTYPE_AUDMAX - PESTYPE_AUD0); i++) { avail_mpaudchan[i] = false; } + for (int i = 0; i <= (PESTYPE_SUBSTREAM_AC3MAX - PESTYPE_SUBSTREAM_AC30); i++) + { + avail_ac3audchan[i] = false; + } } int Demuxer::shutdown() @@ -208,7 +214,7 @@ int Demuxer::PESPacket::submit() { if (dx->video_current == -1) dx->video_current = packetType; if (dx->video_current == packetType && !dx->vid_seeking) - sent = dx->videostream.put(data+submitted, size-submitted); + sent = dx->videostream.put(data+submitted, size-submitted, MPTYPE_VIDEO); else sent = size-submitted; } @@ -220,10 +226,25 @@ int Demuxer::PESPacket::submit() //Log::getInstance()->log("PESPacket", Log::DEBUG, "%i", dx->audio_current); if (dx->audio_current == packetType && !dx->aud_seeking) - sent = dx->audiostream.put(data+submitted, size-submitted); + sent = dx->audiostream.put(data+submitted, size-submitted, MPTYPE_MPEG_AUDIO); else sent = size-submitted; } + else if (packetType == PESTYPE_PRIVATE_1) + { + if (substream >= PESTYPE_SUBSTREAM_AC30 && substream <= PESTYPE_SUBSTREAM_AC3MAX) + { + dx->avail_ac3audchan[substream-PESTYPE_SUBSTREAM_AC30]=true; + if (substream == dx->audio_current) + { + sent = dx->audiostream.put(data+submitted,size-submitted,(dx->ispre_1_3_19)?MPTYPE_AC3_PRE13:MPTYPE_AC3); + } + else + { + sent = size-submitted; + } + } + } else { sent = size-submitted; @@ -267,6 +288,67 @@ void Demuxer::PESPacket::parseDetails() } } } + else if (packetType == PESTYPE_PRIVATE_1) //Private Stream + { + //Inspired by vdr's device.c + int payload_begin = data[8]+9; + unsigned char substream_id = data[payload_begin]; + unsigned char substream_type = substream_id & 0xF0; + unsigned char substream_index = substream_id & 0x1F; +pre_1_3_19_Recording: //This is for old recordings stuff + if (dx->ispre_1_3_19) + { + substream_id = PESTYPE_PRIVATE_1; + substream_type = 0x80; + substream_index = 0; + } + switch (substream_type) + { + case 0x20://SPU + case 0x30://SPU + break; + case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there? + break; + case 0x80: //ac3, currently only one ac3 track per recording supported + substream=substream_type+substream_index; + + // Extract audio PTS if it exists + if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS + { + dx->audio_pts = pts = ( (ULLONG)(data[9] & 0x0E) << 29 ) | + ( (ULLONG)(data[10]) << 22 ) | + ( (ULLONG)(data[11] & 0xFE) << 14 ) | + ( (ULLONG)(data[12]) << 7 ) | + ( (ULLONG)(data[13] & 0xFE) >> 1 ); + // We continue to seek on the audio if the video PTS that we + // are trying to match is ahead of the audio PTS by at most + // SEEK_THRESHOLD. We consider the possibility of PTS wrap. + if (dx->aud_seeking && !dx->vid_seeking && + !( (dx->video_pts_seek > dx->audio_pts && + dx->video_pts_seek - dx->audio_pts < SEEK_THRESHOLD) + || + (dx->video_pts_seek < dx->audio_pts && + dx->video_pts_seek + (1LL<<33) - + dx->audio_pts < SEEK_THRESHOLD) )) + { + dx->aud_seeking = 0; + Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving audio sync: Audio PTS = %llu", dx->audio_pts); + } + } + break; + default: + if (!dx->ispre_1_3_19) + { + dx->ispre_1_3_19=true; //switching to compat mode + goto pre_1_3_19_Recording; + } + else + { + substream=0; + } + break; + } + } else if (packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX) { // Extract video PTS if it exists @@ -379,12 +461,17 @@ bool* Demuxer::getmpAudioChannels() return avail_mpaudchan; } +bool* Demuxer::getac3AudioChannels() +{ + return avail_ac3audchan; +} + int Demuxer::getselAudioChannel() { return audio_current; } -void Demuxer::setmpAudioChannel(int aud_channel) +void Demuxer::setAudioChannel(int aud_channel) { audio_current = aud_channel; } diff --git a/demuxer.h b/demuxer.h index 0baa815..104ed96 100644 --- a/demuxer.h +++ b/demuxer.h @@ -56,12 +56,14 @@ protected: UINT length, size; bool closed; UCHAR packetType; + UCHAR substream; //for ac3 ULLONG pts; bool seq_header; UINT submitted; virtual void parseDetails(); UINT findPictureHeader(); + static const ULLONG PTS_INVALID; }; friend class PESPacket; @@ -89,8 +91,9 @@ protected: virtual ULONG getPacketNum() {return 0;} bool* getmpAudioChannels(); //Maybe virtual ? + bool* getac3AudioChannels(); //Maybe virtual ? int getselAudioChannel(); - void setmpAudioChannel(int aud_channel); + void setAudioChannel(int aud_channel); int getHorizontalSize() { return horizontal_size; } int getVerticalSize() { return vertical_size; } @@ -166,8 +169,18 @@ protected: PESTYPE_VID13, PESTYPE_VID14, PESTYPE_VID15, PESTYPE_VIDMAX = PESTYPE_VID15 }; + enum PESTYPE_SUBSTREAM + { + PESTYPE_SUBSTREAM_AC30 = 0x80, + PESTYPE_SUBSTREAM_AC31,PESTYPE_SUBSTREAM_AC32, PESTYPE_SUBSTREAM_AC33, + PESTYPE_SUBSTREAM_AC34,PESTYPE_SUBSTREAM_AC35,PESTYPE_SUBSTREAM_AC36, + PESTYPE_SUBSTREAM_AC37, + PESTYPE_SUBSTREAM_AC3MAX = PESTYPE_SUBSTREAM_AC37 + }; + bool ispre_1_3_19; bool avail_mpaudchan[PESTYPE_AUDMAX-PESTYPE_AUD0+1]; + bool avail_ac3audchan[PESTYPE_SUBSTREAM_AC3MAX-PESTYPE_SUBSTREAM_AC30+1]; }; #endif diff --git a/draintarget.h b/draintarget.h index 74d5862..2e473be 100644 --- a/draintarget.h +++ b/draintarget.h @@ -24,11 +24,17 @@ #include "defines.h" #include +#define MPTYPE_VIDEO 0x00 +#define MPTYPE_MPEG_AUDIO 0x01 +#define MPTYPE_AC3 0x02 +#define MPTYPE_AC3_PRE13 0x03 //old vdr recording compatmode + struct MediaPacket { ULONG pos_buffer; //position in stream buffer ULONG length; //length of the packet // The fields below are not needed by the MVP + UCHAR type; #ifdef WIN32 ULLONG recording_byte_pos; //position in recording ULLONG pts; diff --git a/dssourcefilter.cc b/dssourcefilter.cc index 13948b7..4720bf9 100644 --- a/dssourcefilter.cc +++ b/dssourcefilter.cc @@ -24,104 +24,105 @@ class DsSFEnumPins: public IEnumPins { public: - DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos=0); - virtual ~DsSFEnumPins(); - virtual HRESULT STDMETHODCALLTYPE Next(ULONG numpin,IPin **pins,ULONG *fetched); - virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); - virtual HRESULT STDMETHODCALLTYPE Reset(); - virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPins **enuma); - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); - virtual ULONG STDMETHODCALLTYPE AddRef(); + DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos=0); + virtual ~DsSFEnumPins(); + virtual HRESULT STDMETHODCALLTYPE Next(ULONG numpin,IPin **pins,ULONG *fetched); + virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); + virtual HRESULT STDMETHODCALLTYPE Reset(); + virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPins **enuma); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE Release(); protected: - DsSourcePin* audiopin; - DsSourcePin* videopin; - DsSourceFilter *filter; - ULONG curpos; - volatile long refs; + DsSourcePin* audiopin; + DsSourcePin* videopin; + DsSourceFilter *filter; + ULONG curpos; + volatile long refs; }; DsSFEnumPins::DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos){ - audiopin=audio; - videopin=video; - curpos=pos; - filter=filt; - filt->AddRef(); - refs=0; - + audiopin=audio; + videopin=video; + curpos=pos; + filter=filt; + filt->AddRef(); + refs=0; + } DsSFEnumPins::~DsSFEnumPins(){ - filter->Release(); - + filter->Release(); + } HRESULT STDMETHODCALLTYPE DsSFEnumPins::Next(ULONG numpin,IPin **pins,ULONG *fetched) { - int i; - if (fetched==NULL) return E_POINTER; - if (pins==NULL) return E_POINTER; - *fetched=0; - - for (i=0;(iAddRef(); pins[i]=(IPin*)audiopin;break; - case 1: videopin->AddRef(); pins[i]=(IPin*)videopin;break; - }; - (*fetched)++; - curpos++; - } - if ((*fetched)!=numpin) return S_FALSE; - return S_OK; + int i; + if (fetched==NULL) return E_POINTER; + if (pins==NULL) return E_POINTER; + *fetched=0; + + for (i=0;(iAddRef(); pins[i]=(IPin*)audiopin;break; + case 1: videopin->AddRef(); pins[i]=(IPin*)videopin;break; + }; + (*fetched)++; + curpos++; + } + if ((*fetched)!=numpin) return S_FALSE; + return S_OK; } HRESULT STDMETHODCALLTYPE DsSFEnumPins::Skip(ULONG numpin){ - curpos+=numpin; - if (curpos>2) return S_FALSE; - return S_OK; + curpos+=numpin; + if (curpos>2) return S_FALSE; + return S_OK; } HRESULT STDMETHODCALLTYPE DsSFEnumPins::Reset(){ - curpos=0; - return S_OK; + curpos=0; + return S_OK; } HRESULT STDMETHODCALLTYPE DsSFEnumPins::Clone(IEnumPins **enuma){ - if (enuma==NULL) return E_POINTER; - *enuma=new DsSFEnumPins(audiopin,videopin,filter,curpos); - (*enuma)->AddRef(); - return S_OK; + if (enuma==NULL) return E_POINTER; + *enuma=new DsSFEnumPins(audiopin,videopin,filter,curpos); + (*enuma)->AddRef(); + return S_OK; } HRESULT STDMETHODCALLTYPE DsSFEnumPins::QueryInterface(REFIID id,void ** object){ - if (object==NULL) return E_POINTER; - if (id==IID_IUnknown ||id == IID_IEnumPins) { - *object=(IUnknown*)this; - ((IUnknown*)object)->AddRef(); - return NOERROR; - } else { - *object=NULL; - return E_NOINTERFACE; - } + if (object==NULL) return E_POINTER; + + if (id==IID_IUnknown ||id == IID_IEnumPins) { + *object=(IUnknown*)this; + ((IUnknown*)object)->AddRef(); + return NOERROR; + } else { + *object=NULL; + return E_NOINTERFACE; + } } ULONG STDMETHODCALLTYPE DsSFEnumPins::AddRef(){ - InterlockedIncrement(&refs); - long tempref=refs; - if (tempref>1) return tempref; - else return 1; + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; } ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){ - long tempref=InterlockedDecrement(&refs); - - if (tempref==0) { - refs++; - delete this; - return NULL; - } else { - if (tempref>1) return tempref; - else return 1; - } + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } } @@ -132,305 +133,322 @@ ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){ DsSourceFilter::DsSourceFilter() { - //add audio pin - HRESULT res; - audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true); - videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false); - filtergraph=NULL; - clock=NULL; - mystate=State_Stopped; - laststart=0; - refs=0; - InitializeCriticalSection(&filterlock); + //add audio pin + HRESULT res; + audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true); + videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false); + filtergraph=NULL; + clock=NULL; + mystate=State_Stopped; + laststart=0; + refs=0; + InitializeCriticalSection(&filterlock); } DsSourceFilter::~DsSourceFilter() { - if (audiopin) delete audiopin; - if (videopin) delete videopin; - if (clock) { - clock->Release(); - clock=NULL; - } - DeleteCriticalSection(&filterlock); - + if (audiopin) delete audiopin; + if (videopin) delete videopin; + if (clock) { + clock->Release(); + clock=NULL; + } + DeleteCriticalSection(&filterlock); + } HRESULT STDMETHODCALLTYPE DsSourceFilter::GetClassID(CLSID *clsid){ - if (clsid==NULL) return E_POINTER; - *clsid=_uuidof(this); - return S_OK; + if (clsid==NULL) return E_POINTER; + *clsid=_uuidof(this); + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryInterface(REFIID id,void ** object){ - if (object==NULL) return E_POINTER; - if (id==IID_IUnknown) { - *object=(IUnknown*)this; - AddRef(); - return NOERROR; - } else if (id==IID_IBaseFilter) { - *object=(IBaseFilter*)this; - AddRef(); - return NOERROR; - } else if (id==IID_IMediaFilter) { - *object=(IMediaFilter*)this; - AddRef(); - return NOERROR; - }else { - *object=NULL; - return E_NOINTERFACE; - } + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown) { + *object=(IUnknown*)this; + AddRef(); + return NOERROR; + } else if (id==IID_IBaseFilter) { + *object=(IBaseFilter*)this; + AddRef(); + return NOERROR; + } else if (id==IID_IMediaFilter) { + *object=(IMediaFilter*)this; + AddRef(); + return NOERROR; + }else { + *object=NULL; + return E_NOINTERFACE; + } } ULONG STDMETHODCALLTYPE DsSourceFilter::AddRef(){ - InterlockedIncrement(&refs); - long tempref=refs; - if (tempref>1) return tempref; - else return 1; + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; } ULONG STDMETHODCALLTYPE DsSourceFilter::Release(){ - long tempref=InterlockedDecrement(&refs); - - if (tempref==0) { - refs++; - delete this; - return NULL; - } else { - if (tempref>1) return tempref; - else return 1; - } + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } } /*IBaseFilter*/ HRESULT STDMETHODCALLTYPE DsSourceFilter::EnumPins(IEnumPins **enumar){ - if (enumar==NULL) return E_POINTER; - *enumar=new DsSFEnumPins(audiopin,videopin, this); - (*enumar)->AddRef(); - return S_OK; + if (enumar==NULL) return E_POINTER; + *enumar=new DsSFEnumPins(audiopin,videopin, this); + (*enumar)->AddRef(); + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::FindPin(LPCWSTR iden,IPin **pin){ - if (pin==NULL) return E_POINTER; - EnterCriticalSection(&filterlock); - - if (wcscmp(AUDIOPIN_NAME,iden)==NULL) { - *pin=(IPin*)audiopin; - (*pin)->AddRef(); - LeaveCriticalSection(&filterlock); - return S_OK; - } - if (wcscmp(VIDEOPIN_NAME,iden)==NULL) { - *pin=(IPin*)videopin; - (*pin)->AddRef(); - LeaveCriticalSection(&filterlock); - return S_OK; - } - - *pin=NULL; - LeaveCriticalSection(&filterlock); + if (pin==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + + if (wcscmp(AUDIOPIN_NAME,iden)==NULL) { + *pin=(IPin*)audiopin; + (*pin)->AddRef(); + LeaveCriticalSection(&filterlock); + return S_OK; + } + if (wcscmp(VIDEOPIN_NAME,iden)==NULL) { + *pin=(IPin*)videopin; + (*pin)->AddRef(); + LeaveCriticalSection(&filterlock); + return S_OK; + } + + *pin=NULL; + LeaveCriticalSection(&filterlock); return VFW_E_NOT_FOUND; } HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryFilterInfo(FILTER_INFO *info){ - if (info==NULL) return E_POINTER; - wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR)); - info->pGraph=filtergraph; - if (info->pGraph!=NULL) info->pGraph->AddRef(); - return NOERROR; + if (info==NULL) return E_POINTER; + wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR)); + info->pGraph=filtergraph; + if (info->pGraph!=NULL) info->pGraph->AddRef(); + return NOERROR; } HRESULT STDMETHODCALLTYPE DsSourceFilter::JoinFilterGraph(IFilterGraph *graph,LPCWSTR name){ - //Should we lock - EnterCriticalSection(&filterlock); - filtergraph=graph; - //filtergraph->AddRef(); - //We ignore the name - LeaveCriticalSection(&filterlock); - - return S_OK; + //Should we lock + EnterCriticalSection(&filterlock); + filtergraph=graph; + //filtergraph->AddRef(); + //We ignore the name + LeaveCriticalSection(&filterlock); + + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryVendorInfo(LPWSTR *vendinf) { - return E_NOTIMPL; + return E_NOTIMPL; } /*IMediaFilter*/ HRESULT STDMETHODCALLTYPE DsSourceFilter::GetState(DWORD timeout,FILTER_STATE *state){ - if (state==NULL) return E_POINTER; - EnterCriticalSection(&filterlock); - *state=mystate; - LeaveCriticalSection(&filterlock); - return S_OK; + if (state==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + *state=mystate; + LeaveCriticalSection(&filterlock); + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::SetSyncSource(IReferenceClock *uhr){ - EnterCriticalSection(&filterlock); - //MessageBox(0,"Sets ync","",0); - if (clock!=NULL) { - clock->Release(); - } - if (uhr!=NULL) { - uhr->AddRef(); - } - clock=uhr; - LeaveCriticalSection(&filterlock); - - return S_OK; + EnterCriticalSection(&filterlock); + if (clock!=NULL) { + clock->Release(); + } + if (uhr!=NULL) { + uhr->AddRef(); + } + clock=uhr; + LeaveCriticalSection(&filterlock); + + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::GetSyncSource(IReferenceClock **uhr){ - if (uhr==NULL) return E_POINTER; - EnterCriticalSection(&filterlock); - if (clock!=NULL) clock->AddRef(); - *uhr=clock; - LeaveCriticalSection(&filterlock); - - return S_OK; + if (uhr==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + if (clock!=NULL) clock->AddRef(); + *uhr=clock; + LeaveCriticalSection(&filterlock); + + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::Stop(){ - EnterCriticalSection(&filterlock); - HRESULT aphres=S_OK; - HRESULT vphres=S_OK; - - if (audiopin->IsConnected()){ - aphres=audiopin->Inactive(); - } - if (videopin->IsConnected()){ - vphres=videopin->Inactive(); - } - - mystate=State_Stopped; - LeaveCriticalSection(&filterlock); - if (aphres!=S_OK) return aphres; - if (vphres!=S_OK) return vphres; - return S_OK; + EnterCriticalSection(&filterlock); + HRESULT aphres=S_OK; + HRESULT vphres=S_OK; + + if (audiopin->IsConnected()){ + aphres=audiopin->Inactive(); + } + if (videopin->IsConnected()){ + vphres=videopin->Inactive(); + } + + mystate=State_Stopped; + LeaveCriticalSection(&filterlock); + if (aphres!=S_OK) return aphres; + if (vphres!=S_OK) return vphres; + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::Pause(){ - EnterCriticalSection(&filterlock); - HRESULT aphres; - HRESULT vphres; - - if (audiopin->IsConnected()){ - aphres=audiopin->Active(); - if (aphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return aphres; - } - } - if (videopin->IsConnected()){ - vphres=videopin->Active(); - if (vphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return vphres; - } - } - - mystate=State_Paused; - LeaveCriticalSection(&filterlock); - - - return S_OK; + EnterCriticalSection(&filterlock); + HRESULT aphres; + HRESULT vphres; + + if (audiopin->IsConnected()){ + aphres=audiopin->Active(); + if (aphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return aphres; + } + } + if (videopin->IsConnected()){ + vphres=videopin->Active(); + if (vphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return vphres; + } + } + + mystate=State_Paused; + LeaveCriticalSection(&filterlock); + + + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::Run(REFERENCE_TIME start){ - - HRESULT aphres; - HRESULT vphres; - EnterCriticalSection(&filterlock); - - if (mystate==State_Stopped) { - HRESULT phres=Pause(); - if (phres!=S_OK){ - LeaveCriticalSection(&filterlock); - return phres; - } - } - - laststart=start; - - - if (audiopin->IsConnected()){ - aphres=audiopin->Run(start); - if (aphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return aphres; - } - } - - if (videopin->IsConnected()){ - vphres=videopin->Run(start); - if (vphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return vphres; - } - } - - mystate=State_Running; - LeaveCriticalSection(&filterlock); - - - return S_OK; + + HRESULT aphres; + HRESULT vphres; + EnterCriticalSection(&filterlock); + + if (mystate==State_Stopped) { + HRESULT phres=Pause(); + if (phres!=S_OK){ + LeaveCriticalSection(&filterlock); + return phres; + } + } + + laststart=start; + + + if (audiopin->IsConnected()){ + aphres=audiopin->Run(start); + if (aphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return aphres; + } + } + + if (videopin->IsConnected()){ + vphres=videopin->Run(start); + if (vphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return vphres; + } + } + + mystate=State_Running; + LeaveCriticalSection(&filterlock); + + + return S_OK; } int DsSourceFilter::GetPinCount() { - return 2; //audio and video + return 2; //audio and video } int DsSourceFilter::getCurrentAudioMediaSample(IMediaSample** ms) { - if (!audiopin || !IsActive()) { - return 0; - } - if (audiopin->getCurrentMediaSample(ms)!=S_OK) { - return 0; - } - return 1; + if (!audiopin || !IsActive()) { + return 0; + } + if (audiopin->getCurrentMediaSample(ms)!=S_OK) { + return 0; + } + return 1; } int DsSourceFilter::getCurrentVideoMediaSample(IMediaSample** ms) { - if (!videopin || !IsActive()) { - return 0; - } - if (videopin->getCurrentMediaSample(ms)!=S_OK) { - return 0; - } - return 1; + if (!videopin || !IsActive()) { + return 0; + } + if (videopin->getCurrentMediaSample(ms)!=S_OK) { + return 0; + } + return 1; } int DsSourceFilter::DeliverAudioMediaSample(IMediaSample* ms) { - if (!audiopin || !IsActive()) { - ms->Release(); - return 0; - } - if (audiopin->deliver(ms)!=S_OK) { - ms->Release(); - return 0; - } - ms->Release(); - return 1; + if (!audiopin || !IsActive()) { + ms->Release(); + return 0; + } + if (audiopin->deliver(ms)!=S_OK) { + ms->Release(); + return 0; + } + ms->Release(); + return 1; } +bool DsSourceFilter::supportsAc3() +{ + if (!audiopin || !IsActive()) { + return false; + } + return audiopin->supportsAc3(); +} + int DsSourceFilter::DeliverVideoMediaSample(IMediaSample* ms) { - if (!videopin || !IsActive()) { - ms->Release(); - return 0; - } - if (videopin->deliver(ms)!=S_OK) { - ms->Release(); - return 0; - } - ms->Release(); - return 1; + if (!videopin || !IsActive()) { + ms->Release(); + return 0; + } + if (videopin->deliver(ms)!=S_OK) { + ms->Release(); + return 0; + } + ms->Release(); + return 1; } +bool DsSourceFilter::changeAType(int type,IMediaSample* ms) +{ + if (!audiopin ) { + return false; + } + audiopin->SetPinMode(type); + audiopin->SetMsToMt(ms); + + return true; +} diff --git a/dssourcefilter.h b/dssourcefilter.h index 9adb656..ba3f12e 100644 --- a/dssourcefilter.h +++ b/dssourcefilter.h @@ -28,55 +28,57 @@ [uuid("EB87AB22-7A95-49c3-8CCE-2F6D61A87009")] class DsSourceFilter: public IBaseFilter { -friend class DsSourcePin; +friend class DsSourcePin; public: - DsSourceFilter(); - ~DsSourceFilter(); - virtual int GetPinCount(); - int getCurrentAudioMediaSample(IMediaSample** ms); - int DeliverAudioMediaSample(IMediaSample* ms); - int getCurrentVideoMediaSample(IMediaSample** ms); - int DeliverVideoMediaSample(IMediaSample* ms); - REFERENCE_TIME getStartOffset(){return laststart;}; - BOOL IsActive() {EnterCriticalSection(&filterlock); - FILTER_STATE tempstate=mystate;LeaveCriticalSection(&filterlock); - return (tempstate==State_Running) || (tempstate==State_Paused);}; + DsSourceFilter(); + ~DsSourceFilter(); + virtual int GetPinCount(); + int getCurrentAudioMediaSample(IMediaSample** ms); + int DeliverAudioMediaSample(IMediaSample* ms); + int getCurrentVideoMediaSample(IMediaSample** ms); + int DeliverVideoMediaSample(IMediaSample* ms); + REFERENCE_TIME getStartOffset(){return laststart;}; + BOOL IsActive() {EnterCriticalSection(&filterlock); + FILTER_STATE tempstate=mystate;LeaveCriticalSection(&filterlock); + return (tempstate==State_Running) || (tempstate==State_Paused);}; /* IUnknown */ - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); - virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE Release(); /*IPersist*/ - virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *clsid); + virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *clsid); /*IBaseFilter*/ - virtual HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **enumar); - virtual HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR iden,IPin **pin); - virtual HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *info); - virtual HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *graph,LPCWSTR name); - virtual HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *vendinf); + virtual HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **enumar); + virtual HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR iden,IPin **pin); + virtual HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *info); + virtual HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *graph,LPCWSTR name); + virtual HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *vendinf); /*IMediaFilter*/ - virtual HRESULT STDMETHODCALLTYPE GetState(DWORD timeout,FILTER_STATE *state); - virtual HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *uhr); - virtual HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **uhr); - virtual HRESULT STDMETHODCALLTYPE Stop(); - virtual HRESULT STDMETHODCALLTYPE Pause(); - virtual HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME start); + virtual HRESULT STDMETHODCALLTYPE GetState(DWORD timeout,FILTER_STATE *state); + virtual HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *uhr); + virtual HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **uhr); + virtual HRESULT STDMETHODCALLTYPE Stop(); + virtual HRESULT STDMETHODCALLTYPE Pause(); + virtual HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME start); - DsSourcePin *GetAudioPin() {return audiopin;}; - DsSourcePin *GetVideoPin() {return videopin;}; + DsSourcePin *GetAudioPin() {return audiopin;}; + DsSourcePin *GetVideoPin() {return videopin;}; + bool supportsAc3(); + bool changeAType(int type,IMediaSample* ms); protected: - DsSourcePin *audiopin; - DsSourcePin *videopin; - IFilterGraph* filtergraph; - IReferenceClock* clock; - FILTER_STATE mystate; - REFERENCE_TIME laststart; - CRITICAL_SECTION filterlock; - - volatile long refs; + DsSourcePin *audiopin; + DsSourcePin *videopin; + IFilterGraph* filtergraph; + IReferenceClock* clock; + FILTER_STATE mystate; + REFERENCE_TIME laststart; + CRITICAL_SECTION filterlock; + + volatile long refs; }; diff --git a/dssourcepin.cc b/dssourcepin.cc index a55016e..8840e28 100644 --- a/dssourcepin.cc +++ b/dssourcepin.cc @@ -21,7 +21,7 @@ #include "dssourcefilter.h" #include #include - +#include "draintarget.h" class DsSFEnumMediaTypes: public IEnumMediaTypes { public: @@ -60,11 +60,11 @@ HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE * for (i=0;(iGetMediaType(curpos+i,pins[i])!=S_OK) { - CoTaskMemFree(pins[i]); - pins[i]=NULL; - return S_FALSE; - } curpos++; + if (parent->GetMediaType(curpos+i,pins[i])!=S_OK) { + CoTaskMemFree(pins[i]); + pins[i]=NULL; + return S_FALSE; + } curpos++; if (fetched!=NULL) (*fetched)++; } return S_OK; @@ -141,8 +141,15 @@ DsSourcePin::DsSourcePin(DsSourceFilter *pFilter, connected=NULL; connectedinput=NULL; allocator=NULL; - - + if (isaudiopin) + { + pinmode=MPTYPE_MPEG_AUDIO; + //pinmode=MPTYPE_AC3; + } + else + { + pinmode=MPTYPE_VIDEO; + } } @@ -186,7 +193,6 @@ HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;} if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;} - bool gotmt=false; if (mtype!=NULL) { @@ -214,34 +220,36 @@ HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE AM_MEDIA_TYPE * emtype; ULONG fetched=0; pinempf->AddRef(); + + while (emt->Next(1,&emtype,&fetched)==S_OK) { if (CheckMediaType(emtype)==S_OK){ -/* PIN_INFO pini; - pinempf->QueryPinInfo(&pini); - if (pini.pFilter!=NULL) { - FILTER_INFO filti; - pini.pFilter->QueryFilterInfo(&filti); - - if (filti.pGraph!=NULL) filti.pGraph->Release(); - char buffer[MAX_FILTER_NAME*2]; - wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2); - MessageBox(0,buffer,"Filter",0); - pini.pFilter->Release(); - }*/ + /* PIN_INFO pini; + pinempf->QueryPinInfo(&pini); + if (pini.pFilter!=NULL) { + FILTER_INFO filti; + pini.pFilter->QueryFilterInfo(&filti); + + if (filti.pGraph!=NULL) filti.pGraph->Release(); + char buffer[MAX_FILTER_NAME*2]; + wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2); + MessageBox(0,buffer,"Filter",0); + pini.pFilter->Release(); + }*/ if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) { connected=pinempf; CopyMType(&medtype,emtype); - if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - - CoTaskMemFree(emtype); + if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); + + CoTaskMemFree(emtype); gotmt=true; break; } } if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - CoTaskMemFree(emtype); + CoTaskMemFree(emtype); } emt->Release(); if (gotmt==false) { @@ -252,14 +260,14 @@ HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE connected=pinempf; CopyMType(&medtype,emtype); if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - CoTaskMemFree(emtype); + CoTaskMemFree(emtype); gotmt=true; break; } } if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - CoTaskMemFree(emtype); + CoTaskMemFree(emtype); } emt->Release(); if (gotmt==false) { @@ -417,6 +425,8 @@ HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){ HRESULT DsSourcePin::deliver(IMediaSample * ms){ //EnterCriticalSection(&m_pFilter->filterlock); HRESULT hres; + + if (connectedinput!=NULL)hres= connectedinput->Receive(ms); else hres= VFW_E_NOT_CONNECTED; //LeaveCriticalSection(&m_pFilter->filterlock); @@ -424,69 +434,228 @@ HRESULT DsSourcePin::deliver(IMediaSample * ms){ } -HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt) +void DsSourcePin::SetMsToMt(IMediaSample *ms) { + ms->SetMediaType(&medtype); +} + +bool DsSourcePin::supportsAc3() { + if (!isaudiopin) + { + return false; //Haha a video pin that supports ac3 + } + if (!IsConnected()) + { + return false; //Graph is not build, please wait + } + if (connected==NULL) + { + return false; //Graph is not build, please wait + } + IPinConnection *pinconn=NULL; //according to docs, this is the prefered method + if (connected->QueryInterface(IID_IPinConnection,(void**)&pinconn)==S_OK) { + AM_MEDIA_TYPE test; + GetMediaType(10,&test); + if (pinconn->DynamicQueryAccept(&test)==S_OK) + { + pinconn->Release(); + CoTaskMemFree(test.pbFormat); + return true; + } else { + pinconn->Release(); + CoTaskMemFree(test.pbFormat); + return false; + } + } + AM_MEDIA_TYPE test; + GetMediaTypeAc3(0,&test); + if (connected->QueryAccept(&test)==S_OK) + { + CoTaskMemFree(test.pbFormat); + return true; + } + CoTaskMemFree(test.pbFormat); + return false; + +} + + +HRESULT DsSourcePin::GetMediaTypeMpegAudio(int iPosition, AM_MEDIA_TYPE *pmt) { HRESULT hr; + switch (iPosition) + { + /* case 0: { + ZeroMemory(pmt,sizeof(*pmt)); + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype=MEDIATYPE_Audio; + MPEG1WAVEFORMAT wfe; + ZeroMemory(&wfe,sizeof(wfe)); + wfe.wfx.cbSize=22; + wfe.wfx.nSamplesPerSec=48000; + wfe.wfx.nChannels=2; + wfe.wfx.nAvgBytesPerSec=32000; + wfe.wfx.nBlockAlign=768; + wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG; + wfe.wfx.wBitsPerSample=0; + wfe.fwHeadLayer=2; + wfe.dwHeadBitrate=256000; + wfe.fwHeadMode=ACM_MPEG_STEREO; + wfe.fwHeadModeExt=1; + wfe.wHeadEmphasis=1; + wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT; + pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO; + pmt->formattype=FORMAT_WaveFormatEx; + pmt->cbFormat=sizeof(wfe); + pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); + memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); + pmt->lSampleSize=0; + hr=S_OK; + } break;*/ + case 0: + { + ZeroMemory(pmt,sizeof(*pmt)); + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype = MEDIATYPE_Audio; + WAVEFORMATEX wfe; + ZeroMemory(&wfe,sizeof(wfe)); + wfe.cbSize = 22; + wfe.nSamplesPerSec = 48000; + wfe.nChannels = 2; + wfe.nAvgBytesPerSec = 32000; + wfe.nBlockAlign = 768; + wfe.wFormatTag = WAVE_FORMAT_UNKNOWN; + wfe.wBitsPerSample = 0; + pmt->subtype = MEDIASUBTYPE_MPEG2_AUDIO; + pmt->formattype = FORMAT_WaveFormatEx; + pmt->cbFormat = sizeof(wfe); + pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe)); + memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); + pmt->lSampleSize=0; + hr=S_OK; + } break; + case 1: { + ZeroMemory(pmt,sizeof(*pmt)); + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype = MEDIATYPE_Audio; + MPEG1WAVEFORMAT wfe; + ZeroMemory(&wfe,sizeof(wfe)); + wfe.wfx.cbSize = 22; + wfe.wfx.nSamplesPerSec = 48000; + wfe.wfx.nChannels = 2; + wfe.wfx.nAvgBytesPerSec = 32000; + wfe.wfx.nBlockAlign = 768; + wfe.wfx.wFormatTag = WAVE_FORMAT_UNKNOWN; + wfe.wfx.wBitsPerSample = 0; + /* wfe.fwHeadLayer=2; + wfe.dwHeadBitrate=256000; + wfe.fwHeadMode=ACM_MPEG_STEREO; + wfe.fwHeadModeExt=1; + wfe.wHeadEmphasis=1; + wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;*/ + pmt->subtype=MEDIASUBTYPE_MPEG1Payload; + pmt->formattype=FORMAT_WaveFormatEx; + pmt->cbFormat=sizeof(wfe); + pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); + memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); + pmt->lSampleSize=0; + hr=S_OK; + } break; + default: { + hr=VFW_S_NO_MORE_ITEMS; + }break; + }; + return hr ; +} - if (isaudiopin){ - if (iPosition==0) { - ZeroMemory(pmt,sizeof(*pmt)); - pmt->lSampleSize = 1; - pmt->bFixedSizeSamples = TRUE; - pmt->majortype=MEDIATYPE_Audio; - MPEG1WAVEFORMAT wfe; - ZeroMemory(&wfe,sizeof(wfe)); - wfe.wfx.cbSize=22; - wfe.wfx.nSamplesPerSec=48000; - wfe.wfx.nChannels=2; - wfe.wfx.nAvgBytesPerSec=32000; - wfe.wfx.nBlockAlign=768; - wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG; - wfe.wfx.wBitsPerSample=0; - wfe.fwHeadLayer=2; - wfe.dwHeadBitrate=256000; - wfe.fwHeadMode=ACM_MPEG_STEREO; - wfe.fwHeadModeExt=1; - wfe.wHeadEmphasis=1; - wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT; - pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO; - pmt->formattype=FORMAT_WaveFormatEx; - pmt->cbFormat=sizeof(wfe); - pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); +HRESULT DsSourcePin::GetMediaTypeAc3(int iPosition, AM_MEDIA_TYPE *pmt) +{ + HRESULT hr; + switch (iPosition) + { + case 0: + { //AC3 for future use + ZeroMemory(pmt,sizeof(*pmt)); + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype = MEDIATYPE_Audio; + WAVEFORMATEX wfe; + ZeroMemory(&wfe,sizeof(wfe)); + wfe.cbSize = 22; + wfe.nSamplesPerSec = 48000; + wfe.nChannels = 2; + wfe.nAvgBytesPerSec = 32000; + wfe.nBlockAlign = 768; + wfe.wFormatTag = WAVE_FORMAT_UNKNOWN; + wfe.wBitsPerSample = 0; + pmt->subtype = MEDIASUBTYPE_DOLBY_AC3; + // pmt->subtype = MEDIASUBTYPE_DOLBY_AC3_SPDIF; + pmt->formattype = FORMAT_WaveFormatEx; + pmt->cbFormat = sizeof(wfe); + pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe)); memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); - pmt->lSampleSize=0; - hr=S_OK; - + pmt->lSampleSize = 0; + hr = S_OK; + } break; + default: { + hr=VFW_S_NO_MORE_ITEMS; + }break; + }; + return hr ; +} - } else { - hr=VFW_S_NO_MORE_ITEMS ; - } - } else { - if (iPosition == 0) { +HRESULT DsSourcePin::GetMediaTypeMpegVideo(int iPosition, AM_MEDIA_TYPE *pmt) +{ + HRESULT hr; + if (iPosition == 0) + { ZeroMemory(pmt,sizeof(*pmt)); pmt->lSampleSize = 1; pmt->bFixedSizeSamples = TRUE; - pmt->majortype=MEDIATYPE_Video; - hr=S_OK; - pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO; - pmt->formattype=FORMAT_MPEG2Video; - - MPEG2VIDEOINFO hdr; - ZeroMemory(&hdr,sizeof(hdr)); - hdr.dwProfile=AM_MPEG2Profile_Main; - hdr.dwLevel=AM_MPEG2Level_Main; - hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader); - hdr.hdr.bmiHeader.biWidth = 720; - hdr.hdr.bmiHeader.biHeight = 568; - pmt->cbFormat=sizeof(hdr); - pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr)); + pmt->majortype = MEDIATYPE_Video; + hr = S_OK; + pmt->subtype = MEDIASUBTYPE_MPEG2_VIDEO; + pmt->formattype = FORMAT_MPEG2Video; + MPEG2VIDEOINFO hdr; + ZeroMemory(&hdr,sizeof(hdr)); + hdr.dwProfile = AM_MPEG2Profile_Main; + hdr.dwLevel = AM_MPEG2Level_Main; + hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader); + hdr.hdr.bmiHeader.biWidth = 720; + hdr.hdr.bmiHeader.biHeight = 568; + pmt->cbFormat = sizeof(hdr); + pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(hdr)); memcpy(pmt->pbFormat,&hdr,sizeof(hdr)); - - } else { + } else { hr=VFW_S_NO_MORE_ITEMS; - } } - return hr ; + + return hr; +} + +HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt) +{ + + switch (pinmode){ + case MPTYPE_MPEG_AUDIO: + return GetMediaTypeMpegAudio(iPosition,pmt); + break; + case MPTYPE_VIDEO: + return GetMediaTypeMpegVideo(iPosition,pmt); + break; + case MPTYPE_AC3_PRE13: + case MPTYPE_AC3: + return GetMediaTypeAc3(iPosition,pmt); + }; +} + +void DsSourcePin::SetPinMode(int mode) { + pinmode=mode; + AM_MEDIA_TYPE amtype; + ReleaseMType(&medtype); + GetMediaType(0,&medtype); } HRESULT DsSourcePin::Inactive() { @@ -507,27 +676,46 @@ HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){ // No description HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt) { - HRESULT res; - - if (isaudiopin) { - bool subtype=false; -#if 0 /* For future demands ac3 */ - subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3); -#endif + HRESULT res=S_FALSE; + bool subtype=false; + switch (pinmode) { + case MPTYPE_MPEG_AUDIO: subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO)); - if (pmt->majortype==MEDIATYPE_Audio && subtype) { - res = S_OK ; - } else { - res = S_FALSE ; + subtype=(pmt->subtype==MEDIASUBTYPE_MPEG1Payload) || subtype; + if (pmt->majortype==MEDIATYPE_Audio && subtype) + { + res = S_OK ; + } + else + { + res = S_FALSE ; + } + break; + case MPTYPE_VIDEO: + if (pmt->majortype==MEDIATYPE_Video && + pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) + { + res = S_OK ; } - } else { - if (pmt->majortype==MEDIATYPE_Video && - pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) { - res = S_OK ; - } else { + else + { res = S_FALSE ; } - } + break; + case MPTYPE_AC3_PRE13: + case MPTYPE_AC3: + subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3); + subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3_SPDIF) || subtype; + if (pmt->majortype==MEDIATYPE_Audio && subtype) + { + res = S_OK ; + } + else + { + res = S_FALSE ; + } + break; + }; return res; } @@ -540,14 +728,14 @@ HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *al if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) { //all_pp->cBuffers = 300;//old - all_pp->cBuffers = 10; + all_pp->cBuffers = 50; all_pp->cbBuffer = 64*1024; } } else { if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) { //all_pp->cBuffers = 300;//old - all_pp->cBuffers = 30; + all_pp->cBuffers = 300; all_pp->cbBuffer = 64*1024; } } @@ -566,4 +754,3 @@ HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *al return S_OK; } - diff --git a/dssourcepin.h b/dssourcepin.h index 8b023d3..bb2a8e2 100644 --- a/dssourcepin.h +++ b/dssourcepin.h @@ -23,7 +23,7 @@ #include -#include +#include @@ -33,53 +33,60 @@ class DsSourceFilter; class DsSourcePin: public IPin { public: - DsSourcePin(DsSourceFilter *pFilter,HRESULT *phr,LPCWSTR pName,bool audio); - ~DsSourcePin(); - BOOL IsConnected() {return (connected!=NULL);}; - HRESULT getCurrentMediaSample(IMediaSample**ms); - HRESULT deliver(IMediaSample * ms); - - virtual HRESULT DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp); - - HRESULT Inactive(); - HRESULT Active(); - HRESULT Run(REFERENCE_TIME reftime); - /*IPin*/ - - virtual HRESULT STDMETHODCALLTYPE Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype); - virtual HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *connect,const AM_MEDIA_TYPE *mtype); - virtual HRESULT STDMETHODCALLTYPE Disconnect(); - virtual HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pin); - virtual HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *mtype); - virtual HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *info); - virtual HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *dir); - virtual HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *id); - virtual HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *mtype); - virtual HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **enuma); - virtual HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **pin,ULONG *numpin); - virtual HRESULT STDMETHODCALLTYPE EndOfStream(); - virtual HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate); - /* IUnknown */ - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); - virtual ULONG STDMETHODCALLTYPE AddRef(); + DsSourcePin(DsSourceFilter *pFilter,HRESULT *phr,LPCWSTR pName,bool audio); + ~DsSourcePin(); + BOOL IsConnected() {return (connected!=NULL);}; + HRESULT getCurrentMediaSample(IMediaSample**ms); + HRESULT deliver(IMediaSample * ms); + void SetMsToMt(IMediaSample *ms); + bool supportsAc3(); + + virtual HRESULT DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp); + + HRESULT Inactive(); + HRESULT Active(); + HRESULT Run(REFERENCE_TIME reftime); + /*IPin*/ + + virtual HRESULT STDMETHODCALLTYPE Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *connect,const AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE Disconnect(); + virtual HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pin); + virtual HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *info); + virtual HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *dir); + virtual HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *id); + virtual HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **enuma); + virtual HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **pin,ULONG *numpin); + virtual HRESULT STDMETHODCALLTYPE EndOfStream(); + virtual HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate); + /* IUnknown */ + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE Release(); - virtual HRESULT STDMETHODCALLTYPE BeginFlush(){return E_UNEXPECTED;}; - virtual HRESULT STDMETHODCALLTYPE EndFlush(){return E_UNEXPECTED;}; - virtual HRESULT GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt); + virtual HRESULT STDMETHODCALLTYPE BeginFlush(){return E_UNEXPECTED;}; + virtual HRESULT STDMETHODCALLTYPE EndFlush(){return E_UNEXPECTED;}; + virtual HRESULT GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt); protected: - virtual HRESULT CheckMediaType(const AM_MEDIA_TYPE *pmt); + virtual HRESULT CheckMediaType(const AM_MEDIA_TYPE *pmt); + HRESULT GetMediaTypeMpegAudio(int iPosition, AM_MEDIA_TYPE *pmt); + HRESULT GetMediaTypeAc3(int iPosition, AM_MEDIA_TYPE *pmt); + HRESULT GetMediaTypeMpegVideo(int iPosition, AM_MEDIA_TYPE *pmt); + + void SetPinMode(int mode); + int pinmode; + bool isaudiopin; + DsSourceFilter *m_pFilter; + IPin* connected; + IMemInputPin* connectedinput; + AM_MEDIA_TYPE medtype; + IMemAllocator* allocator; - bool isaudiopin; - DsSourceFilter *m_pFilter; - IPin* connected; - IMemInputPin* connectedinput; - AM_MEDIA_TYPE medtype; - IMemAllocator* allocator; - }; diff --git a/player.cc b/player.cc index 6266041..8ea268c 100644 --- a/player.cc +++ b/player.cc @@ -143,11 +143,16 @@ ULONG Player::getCurrentFrameNum() } } -bool* Player::getDemuxerAudioChannels() +bool* Player::getDemuxerMpegAudioChannels() { return demuxer->getmpAudioChannels(); } +bool* Player::getDemuxerAc3AudioChannels() +{ + return demuxer->getac3AudioChannels(); +} + int Player::getCurrentAudioChannel() { return demuxer->getselAudioChannel(); @@ -155,7 +160,7 @@ int Player::getCurrentAudioChannel() void Player::setAudioChannel(int newChannel) { - demuxer->setmpAudioChannel(newChannel); + demuxer->setAudioChannel(newChannel); } // ----------------------------------- Externally called events diff --git a/player.h b/player.h index 666cc17..4c884e8 100644 --- a/player.h +++ b/player.h @@ -74,7 +74,8 @@ class Player : public Thread_TYPE, public Callback ULONG getCurrentFrameNum(); ULONG getLengthFrames(); UCHAR getIScanRate() { return ifactor; } - bool* getDemuxerAudioChannels(); + bool* getDemuxerMpegAudioChannels(); + bool* getDemuxerAc3AudioChannels(); int getCurrentAudioChannel(); void call(void*); // for callback interface diff --git a/stream.cc b/stream.cc index 21b847a..556d7b3 100644 --- a/stream.cc +++ b/stream.cc @@ -68,13 +68,14 @@ void Stream::flush() if (draintarget) draintarget->ResetTimeOffsets(); } -int Stream::put(const UCHAR* inbuf, int len) +int Stream::put(const UCHAR* inbuf, int len, UCHAR type) { int ret = 0; if (!draintarget) return 0; MediaPacket newPacket; newPacket.length = len; newPacket.pos_buffer = 0; + newPacket.type = type; #ifdef WIN32 newPacket.synched=false; newPacket.disconti=false; diff --git a/stream.h b/stream.h index d963330..59c5575 100644 --- a/stream.h +++ b/stream.h @@ -44,7 +44,7 @@ class Stream int init(DrainTarget* tdt, int bufsize); void shutdown(); void flush(); - int put(const UCHAR* inbuf, int len); + int put(const UCHAR* inbuf, int len, UCHAR type); bool drain(); private: diff --git a/vaudioselector.cc b/vaudioselector.cc index d800f62..61782f3 100644 --- a/vaudioselector.cc +++ b/vaudioselector.cc @@ -20,7 +20,9 @@ #include "vaudioselector.h" -VAudioSelector::VAudioSelector(void* tparent, bool* availableAudioChannels, int currentAudioChannel, RecInfo* recInfo) +VAudioSelector::VAudioSelector(void* tparent,bool* availableMpegAudioChannels, + bool* availableAc3AudioChannels, + int currentAudioChannel, RecInfo* recInfo) { Log::getInstance()->log("VAS", Log::DEBUG, "%i", currentAudioChannel); @@ -42,7 +44,7 @@ VAudioSelector::VAudioSelector(void* tparent, bool* availableAudioChannels, int for (i = 0; i < PES_AUDIO_MAXCHANNELS; i++) { - if (availableAudioChannels[i]) + if (availableMpegAudioChannels[i]) { AudioChannel* ac = new AudioChannel(); ac->type = 0; @@ -51,6 +53,20 @@ VAudioSelector::VAudioSelector(void* tparent, bool* availableAudioChannels, int acl.push_back(ac); } } + if (availableAc3AudioChannels != NULL) + { + for (i = 0; i < PES_AUDIO_AC3_MAXCHANNELS; i++) + { + if (availableAc3AudioChannels[i]) + { + AudioChannel* ac = new AudioChannel(); + ac->type = 1;//ac3 + ac->name = NULL; + ac->pestype = PES_AUDIO_AC3_START + i; + acl.push_back(ac); + } + } + } unsigned char numchan_recinfo = recInfo->numComponents; unsigned char numchan_siz = acl.size(); @@ -142,7 +158,18 @@ VAudioSelector::VAudioSelector(void* tparent, bool* availableAudioChannels, int } else { - SNPRINTF(tempString, 299, "%lu", (ULONG)(ac->pestype - PES_AUDIO_START)); + if (ac->type==0) + { + SNPRINTF(tempString, 299, "%lu", (ULONG)(ac->pestype - PES_AUDIO_START)); + } + else if (ac->type==1) + { + SNPRINTF(tempString, 299, "ac3 %lu", (ULONG)(ac->pestype - PES_AUDIO_AC3_START)); + } + else + { + SNPRINTF(tempString, 299, "unknown"); + } sl.addOption(tempString, (ULONG)ac, (ac->pestype == currentAudioChannel)); } } diff --git a/vaudioselector.h b/vaudioselector.h index d6aebef..e1efc04 100644 --- a/vaudioselector.h +++ b/vaudioselector.h @@ -38,6 +38,8 @@ #define PES_AUDIO_START 0xc0 #define PES_AUDIO_MAXCHANNELS 0x20 +#define PES_AUDIO_AC3_MAXCHANNELS 0x08 +#define PES_AUDIO_AC3_START 0x80 class AudioChannel { @@ -52,11 +54,12 @@ typedef vector AudioChannelList; class VAudioSelector : public View { public: - VAudioSelector(void* parent, bool* availableAudioChannels, int currentAudioChannel, RecInfo* recInfo); + VAudioSelector(void* parent, bool* availableMpegAudioChannels, + bool* availableAc3AudioChannels, int currentAudioChannel, RecInfo* recInfo); ~VAudioSelector(); int handleCommand(int command); - void processMessage(Message* m); + void processMessage(Message* m); void draw(); private: @@ -67,3 +70,4 @@ class VAudioSelector : public View }; #endif + diff --git a/videowin.cc b/videowin.cc index c27268e..4307b62 100644 --- a/videowin.cc +++ b/videowin.cc @@ -41,6 +41,8 @@ VideoWin::VideoWin() sourcefilter=NULL; allocatorvmr=NULL; cr_time=0; + lastaudiomode=MPTYPE_MPEG_AUDIO; + //lastaudiomode=MPTYPE_AC3; dsvmrsurfnotify=NULL; filtermutex=CreateMutex(NULL,FALSE,NULL); offsetnotset=true; @@ -216,7 +218,7 @@ int VideoWin::dsplay() WaitForSingleObject(filtermutex,INFINITE); if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) { - ReleaseMutex(filtermutex); + ReleaseMutex(filtermutex); return 0; } #ifdef DS_DEBUG @@ -224,20 +226,22 @@ int VideoWin::dsplay() #endif //This is just a try to see if building the graph works // dsgraphbuilder->RenderFile(L"D:\\Projekte\\VTP Client\\test.mpa" ,NULL); - + firstsynched=false; + lastaudiomode=MPTYPE_MPEG_AUDIO; + //lastaudiomode=MPTYPE_AC3; sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data // to DirectShow if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!"); - ReleaseMutex(filtermutex); + ReleaseMutex(filtermutex); CleanupDS(); return 0; } //if (audioon) { if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*/)!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!"); - ReleaseMutex(filtermutex); + ReleaseMutex(filtermutex); CleanupDS(); return 0; } @@ -248,22 +252,22 @@ int VideoWin::dsplay() if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0, CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!"); - ReleaseMutex(filtermutex); + ReleaseMutex(filtermutex); CleanupDS(); - + } /*VMR 9 stuff**/ if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) { - ReleaseMutex(filtermutex); + ReleaseMutex(filtermutex); CleanupDS(); Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!"); - + return 0; } IVMRFilterConfig9* vmrfilconfig; if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) { ReleaseMutex(filtermutex); - CleanupDS(); + CleanupDS(); Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!"); return 0; } @@ -272,15 +276,15 @@ int VideoWin::dsplay() if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { ReleaseMutex(filtermutex); - CleanupDS(); + CleanupDS(); Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!"); - + return 0; } allocatorvmr=new DsAllocator(); dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr); allocatorvmr->AdviseNotify(dsvmrsurfnotify); - + @@ -289,18 +293,18 @@ int VideoWin::dsplay() if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!"); ReleaseMutex(filtermutex); - CleanupDS(); + CleanupDS(); return 0; } if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*/, AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!"); - fg2->Release(); - ReleaseMutex(filtermutex); - CleanupDS(); + fg2->Release(); + ReleaseMutex(filtermutex); + CleanupDS(); return 0; } - fg2->Release(); + fg2->Release(); } #endif if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER, @@ -312,7 +316,7 @@ int VideoWin::dsplay() HRESULT hresdeb=dsmediafilter->SetSyncSource(dsrefclock); dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol); - dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); + dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); dsinited=true; //MILLISLEEP(100); @@ -324,28 +328,28 @@ int VideoWin::dsplay() int VideoWin::EnterIframePlayback() { - if (!initted) return 0; - CleanupDS(); - //So this is the real code, this prevents the feeder from calling noexisting objects! + if (!initted) return 0; + CleanupDS(); + //So this is the real code, this prevents the feeder from calling noexisting objects! WaitForSingleObject(filtermutex,INFINITE); - iframemode=true;//enter iframe mode - //Build filter graph - HRESULT hres; - if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, - IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) { - ReleaseMutex(filtermutex); - return 0; - } + iframemode=true;//enter iframe mode + //Build filter graph + HRESULT hres; + if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, + IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) { + ReleaseMutex(filtermutex); + return 0; + } #ifdef DS_DEBUG - AddToRot(dsgraphbuilder,&graphidentifier); + AddToRot(dsgraphbuilder,&graphidentifier); #endif - + //firstsynched=false; sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data // to DirectShow if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!"); - ReleaseMutex(filtermutex); + ReleaseMutex(filtermutex); CleanupDS(); return 0; } @@ -356,54 +360,54 @@ int VideoWin::EnterIframePlayback() CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!"); ReleaseMutex(filtermutex); - CleanupDS(); - return 0; + CleanupDS(); + return 0; } /*VMR 9 stuff**/ if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!"); ReleaseMutex(filtermutex); - CleanupDS(); + CleanupDS(); return 0; } IVMRFilterConfig9* vmrfilconfig; if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) { ReleaseMutex(filtermutex); - CleanupDS(); + CleanupDS(); Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!"); - + return 0; } vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless); vmrfilconfig->Release(); - if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { + if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!"); ReleaseMutex(filtermutex); - CleanupDS(); + CleanupDS(); return 0; } allocatorvmr=new DsAllocator(); dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr); allocatorvmr->AdviseNotify(dsvmrsurfnotify); - + /*VMR 9 stuff end */ IFilterGraph2*fg2=NULL; if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!"); ReleaseMutex(filtermutex); - CleanupDS(); + CleanupDS(); return 0; } if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*/, AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) { Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!"); - fg2->Release(); - ReleaseMutex(filtermutex); + fg2->Release(); + ReleaseMutex(filtermutex); CleanupDS(); return 0; } - fg2->Release(); + fg2->Release(); } #endif /* if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER, @@ -415,9 +419,9 @@ int VideoWin::EnterIframePlayback() dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can! dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol); - dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); + dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); dsinited=true; - + dsmediacontrol->Run(); ReleaseMutex(filtermutex); @@ -446,7 +450,7 @@ int VideoWin::stop() int VideoWin::reset() { if (!initted) return 0; - + return 1; } @@ -474,7 +478,7 @@ int VideoWin::dspause() int VideoWin::pause() { if (!initted) return 0; - + return 1; } @@ -504,7 +508,7 @@ int VideoWin::fastForward() int VideoWin::unFastForward() { if (!initted) return 0; - + return 1; } @@ -522,22 +526,22 @@ int VideoWin::blank(void) ULLONG VideoWin::getCurrentTimestamp() { - REFERENCE_TIME startoffset; - REFERENCE_TIME ncr_time; + REFERENCE_TIME startoffset; + REFERENCE_TIME ncr_time; if (iframemode) return 0; //Not in iframe mode! if (!dsrefclock || !sourcefilter) return 0; - FILTER_STATE state; - sourcefilter->GetState(10,&state); + FILTER_STATE state; + sourcefilter->GetState(10,&state); - if (state==State_Running) dsrefclock->GetTime(&cr_time); - ncr_time=cr_time; + if (state==State_Running) dsrefclock->GetTime(&cr_time); + ncr_time=cr_time; startoffset=sourcefilter->getStartOffset(); - ncr_time-=startoffset; - ncr_time-=lastreftimeRT; + ncr_time-=startoffset; + ncr_time-=lastreftimeRT; /* ULLONG result=frameNumberToTimecode( VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/ - ULLONG result=lastreftimePTS; - result+=(ULLONG)(ncr_time/10000LL*90LL); + ULLONG result=lastreftimePTS; + result+=(ULLONG)(ncr_time/10000LL*90LL); return result; } @@ -568,8 +572,8 @@ void VideoWin::CleanupDS() cur_video_media_sample=NULL; } if (dsbasicaudio) { - dsbasicaudio->Release(); - dsbasicaudio=NULL; + dsbasicaudio->Release(); + dsbasicaudio=NULL; } if (dsvmrsurfnotify) { dsvmrsurfnotify->Release(); @@ -605,9 +609,9 @@ void VideoWin::CleanupDS() #ifdef DS_DEBUG RemoveFromRot(graphidentifier); #endif - dsgraphbuilder->Release(); + dsgraphbuilder->Release(); dsgraphbuilder=NULL; - + sourcefilter=NULL; //The Graph Builder destroys our SourceFilter } ReleaseMutex(filtermutex); @@ -635,18 +639,18 @@ UINT VideoWin::DeliverMediaPacket(MediaPacket packet, UINT *samplepos) { /*First Check, if we have an audio sample*/ - if (!isdsinited()) return 0; + if (!isdsinited()) return 0; #ifdef DO_VIDEO - if (!videoon) { - *samplepos+=packet.length; + if (!videoon) { + *samplepos+=packet.length; MILLISLEEP(0); //yet not implemented//bad idea return packet.length; - } + } /*First Check, if we have an audio sample*/ if (iframemode) { - samplepos=0; - MILLISLEEP(10); - return 0; //Not in iframe mode! + samplepos=0; + MILLISLEEP(10); + return 0; //Not in iframe mode! } IMediaSample* ms=NULL; REFERENCE_TIME reftime1=0; @@ -658,8 +662,6 @@ UINT VideoWin::DeliverMediaPacket(MediaPacket packet, DeliverVideoMediaSample(); } - - /*Inspect PES-Header */ if (*samplepos==0) {//stripheader @@ -686,7 +688,7 @@ UINT VideoWin::DeliverMediaPacket(MediaPacket packet, UINT ms_length; UINT ms_pos; UINT haveToCopy; - + if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample samplepos=0; MILLISLEEP(10); @@ -724,13 +726,13 @@ UINT VideoWin::DeliverMediaPacket(MediaPacket packet, else ms->SetPreroll(FALSE); /*Timecode handling*/ lastreftimeRT=reftime1; - lastreftimePTS=packet.pts; + lastreftimePTS=packet.pts; }else { ms->SetSyncPoint(FALSE); ms->SetTime(NULL,NULL); ms->SetMediaTime(NULL, NULL); - ms->SetPreroll(FALSE); + ms->SetPreroll(FALSE); // ms->SetSyncPoint(TRUE); } @@ -838,7 +840,7 @@ long long VideoWin::SetStartOffset(long long curreftime, bool *rsync) } lastrefvideotime=curreftime; - + return startoffset; } @@ -885,14 +887,14 @@ void VideoWin::ResetTimeOffsets() { void VideoWin::SetAudioVolume(long volume) { - if (dsbasicaudio) dsbasicaudio->put_Volume(volume); + if (dsbasicaudio) dsbasicaudio->put_Volume(volume); } void VideoWin::displayIFrame(const UCHAR* buffer, UINT length) { - if (!iframemode) EnterIframePlayback(); + if (!iframemode) EnterIframePlayback(); - if (!isdsinited()) return ; + if (!isdsinited()) return ; #ifdef DO_VIDEO IMediaSample* ms=NULL; REFERENCE_TIME reftime1=0; @@ -907,7 +909,7 @@ void VideoWin::displayIFrame(const UCHAR* buffer, UINT length) DWORD ms_length; ms->GetPointer(&ms_buf); ms_length=ms->GetSize(); - + /*First Check, if we have an video sample*/ DWORD read_pos = 0, write_pos = 0; DWORD pattern, packet_length; @@ -923,41 +925,44 @@ void VideoWin::displayIFrame(const UCHAR* buffer, UINT length) read_pos++; else { - headerstrip=buffer[read_pos+8]+9/*is this right*/; + headerstrip=buffer[read_pos+8]+9/*is this right*/; packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6; if (read_pos + packet_length > length) read_pos = length; else { - if ((write_pos+packet_length-headerstrip)>ms_length) { - if (first) {ms->SetSyncPoint(TRUE);first=false;} - else ms->SetSyncPoint(FALSE); - ms->SetTime(NULL,NULL); - ms->SetMediaTime(NULL, NULL); - ms->SetActualDataLength(write_pos); - DeliverVideoMediaSample(); - - if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample - MILLISLEEP(10); - return ; - } - write_pos=0; - ms_length=ms->GetSize(); - ms->GetPointer(&ms_buf); - } - if (packet_length-headerstrip>0) { - memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip); - write_pos += packet_length-headerstrip; - } - read_pos += packet_length; - - pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8) + if ((write_pos+packet_length-headerstrip)>ms_length) { + if (first) { + ms->SetSyncPoint(TRUE); + ms->SetDiscontinuity(TRUE); + first=false; + } else ms->SetSyncPoint(FALSE); + ms->SetTime(NULL,NULL); + ms->SetMediaTime(NULL, NULL); + ms->SetActualDataLength(write_pos); + DeliverVideoMediaSample(); + + if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample + MILLISLEEP(10); + return ; + } + write_pos=0; + ms_length=ms->GetSize(); + ms->GetPointer(&ms_buf); + } + if (packet_length-headerstrip>0) { + memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip); + write_pos += packet_length-headerstrip; + } + read_pos += packet_length; + + pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8) | (buffer[read_pos+2]); } } } - if (first) {ms->SetSyncPoint(TRUE);first=false;} + if (first) {ms->SetSyncPoint(TRUE);first=false;} else ms->SetSyncPoint(FALSE); ms->SetTime(NULL,NULL); ms->SetMediaTime(NULL, NULL); @@ -972,6 +977,24 @@ void VideoWin::displayIFrame(const UCHAR* buffer, UINT length) #endif } +bool VideoWin::supportsAc3(){ + if (sourcefilter != NULL) { + return sourcefilter->supportsAc3(); + } else { + return false; + } +} + +bool VideoWin::changeAType(int type,IMediaSample* ms){ + if (sourcefilter!= NULL) { + lastaudiomode=type; + return sourcefilter->changeAType(type,ms); + } + else + { + return false; + } +} #ifdef DEV int VideoWin::test() diff --git a/videowin.h b/videowin.h index 8fbb07c..2a64edf 100644 --- a/videowin.h +++ b/videowin.h @@ -82,6 +82,8 @@ class VideoWin : public Video virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos); + + virtual bool supportsAc3(); private: MediaPacket mediapacket; public: @@ -108,6 +110,8 @@ class VideoWin : public Video unsigned int getPosy() {return videoposy;}; bool isVideoOn() {return videoon;}; bool isdsinited() {return dsinited;}; + int lastAType() {return lastaudiomode;}; + bool changeAType(int type,IMediaSample* ms); #ifdef DEV int test(); @@ -147,6 +151,7 @@ private: ULLONG lastreftimePTS; unsigned int videoposx; unsigned int videoposy; + int lastaudiomode; #ifdef DS_DEBUG DWORD graphidentifier; #endif @@ -155,4 +160,3 @@ private: #endif - diff --git a/vvideorec.cc b/vvideorec.cc index afe0ef0..fdd81d7 100644 --- a/vvideorec.cc +++ b/vvideorec.cc @@ -532,10 +532,15 @@ void VVideoRec::toggleChopSides() void VVideoRec::doAudioSelector() { - bool* availableAudioChannels = player->getDemuxerAudioChannels(); + bool* availableMpegAudioChannels = player->getDemuxerMpegAudioChannels(); + bool* availableAc3AudioChannels = 0; int currentAudioChannel = player->getCurrentAudioChannel(); + if (Audio::getInstance()->supportsAc3()) + { + availableAc3AudioChannels = player->getDemuxerAc3AudioChannels(); + } - vas = new VAudioSelector(this, availableAudioChannels, currentAudioChannel, myRec->recInfo); + vas = new VAudioSelector(this, availableMpegAudioChannels,availableAc3AudioChannels, currentAudioChannel, myRec->recInfo); vas->setBackgroundColour(barBlue); if (video->getFormat() == Video::PAL) { -- 2.39.5